Revert "Revert "Switch to the new SkSL lexer.""

This reverts commit 358515491a0d6891e6a709688a30ad087df1beb1.

Bug: skia:
Change-Id: I013fac0ed83774d8ae7c6ee6819045cab37f5e97
Reviewed-on: https://skia-review.googlesource.com/45180
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 1c328b0..ef2ac07 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -45,6 +45,7 @@
   skia_vulkan_sdk = getenv("VULKAN_SDK")
   skia_qt_path = getenv("QT_PATH")
   skia_compile_processors = false
+  skia_lex = false
 
   skia_jumper_clang = ""
   skia_jumper_objdump = ""
@@ -411,7 +412,7 @@
   ]
 }
 
-if (skia_compile_processors) {
+if (skia_lex) {
   executable("sksllex") {
     sources = [
       "src/sksl/lex/Main.cpp",
@@ -422,6 +423,38 @@
     include_dirs = [ "src/sksl/lex" ]
   }
 
+  action("run_sksllex") {
+    script = "gn/run_sksllex.py"
+    sources = [
+      "src/sksl/lex/layout.lex",
+      "src/sksl/lex/sksl.lex",
+    ]
+
+    # GN insists its outputs should go somewhere underneath target_out_dir, so we trick it with a
+    # path that starts with target_out_dir and then uses ".." to back up into the src dir.
+    outputs = [
+      "$target_out_dir/" +
+          rebase_path("src/sksl/lex/SkSLLexer.h", target_out_dir),
+      # the script also modifies the corresponding .cpp file, but if we tell GN that it gets
+      # confused due to the same file being named by two different paths
+    ]
+    sksllex_path = "$root_out_dir/"
+    sksllex_path += "sksllex"
+    if (host_os == "win") {
+      sksllex_path += ".exe"
+    }
+    args = [
+      rebase_path(sksllex_path),
+      rebase_path("bin/clang-format"),
+      rebase_path("src"),
+    ]
+  }
+} else {
+  group("run_sksllex") {
+  }
+}
+
+if (skia_compile_processors) {
   executable("skslc") {
     defines = [ "SKSL_STANDALONE" ]
     sources = [
@@ -482,6 +515,7 @@
   enabled = skia_enable_gpu
   deps = [
     ":compile_processors",
+    ":run_sksllex",
   ]
   public_defines = []
 
diff --git a/gn/run_sksllex.py b/gn/run_sksllex.py
new file mode 100644
index 0000000..0377283
--- /dev/null
+++ b/gn/run_sksllex.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+sksllex = sys.argv[1]
+clangFormat = sys.argv[2]
+src = sys.argv[3]
+try:
+    subprocess.check_output([sksllex, src + "/sksl/lex/sksl.lex", "Lexer",
+                             "Token", src + "/sksl/SkSLLexer.h", src +
+                             "/sksl/SkSLLexer.cpp"])
+    subprocess.check_call(clangFormat + " -i \"" + src + "/sksl/SkSLLexer.h\"",
+                          shell=True)
+    subprocess.check_call(clangFormat + " -i \"" + src +
+                          "/sksl/SkSLLexer.cpp\"", shell=True)
+    subprocess.check_output([sksllex, src + "/sksl/lex/layout.lex",
+                             "LayoutLexer", "LayoutToken",
+                             src + "/sksl/SkSLLayoutLexer.h",
+                             src + "/sksl/SkSLLayoutLexer.cpp"])
+    subprocess.check_call(clangFormat + " -i \"" + src +
+                          "/sksl/SkSLLayoutLexer.h\"", shell=True)
+    subprocess.check_call(clangFormat + " -i \"" + src +
+                          "/sksl/SkSLLayoutLexer.cpp\"", shell=True)
+except subprocess.CalledProcessError as err:
+    print("### Lexer error:")
+    print(err.output)
+    exit(1)
diff --git a/gn/sksl.gni b/gn/sksl.gni
index c1b6aba..65913e3 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -9,15 +9,16 @@
 skia_sksl_sources = [
   "$_src/sksl/SkSLCFGGenerator.cpp",
   "$_src/sksl/SkSLCompiler.cpp",
-  "$_src/sksl/SkSLIRGenerator.cpp",
-  "$_src/sksl/SkSLParser.cpp",
   "$_src/sksl/SkSLCPPCodeGenerator.cpp",
-  "$_src/sksl/SkSLHCodeGenerator.cpp",
   "$_src/sksl/SkSLGLSLCodeGenerator.cpp",
+  "$_src/sksl/SkSLHCodeGenerator.cpp",
+  "$_src/sksl/SkSLIRGenerator.cpp",
+  "$_src/sksl/SkSLLexer.cpp",
+  "$_src/sksl/SkSLLayoutLexer.cpp",
+  "$_src/sksl/SkSLParser.cpp",
   "$_src/sksl/SkSLSPIRVCodeGenerator.cpp",
   "$_src/sksl/SkSLString.cpp",
   "$_src/sksl/SkSLUtil.cpp",
-  "$_src/sksl/lex.layout.cpp",
   "$_src/sksl/ir/SkSLSymbolTable.cpp",
   "$_src/sksl/ir/SkSLSetting.cpp",
   "$_src/sksl/ir/SkSLType.cpp",
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
index 96961cf..aebb7d3 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -130,7 +130,7 @@
         GrProcessorTestData* testData) {
     sk_sp<GrTextureProxy> bmpProxy = testData->textureProxy(GrProcessorUnitTest::kSkiaPMTextureIdx);
     sk_sp<GrTextureProxy> maskProxy = testData->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
-
+    // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
     float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
     float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
     const int kMaxWidth = 1000;
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index 7cec3cc..75d73bd 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -13,11 +13,13 @@
 
 #include "GrResourceProvider.h"
 
+// Computes an unnormalized half kernel (right side). Returns the summation of all the half
+// kernel values.
 static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize, float sigma) {
     const float invSigma = 1.f / sigma;
     const float b = -0.5f * invSigma * invSigma;
     float tot = 0.0f;
-
+    // Compute half kernel values at half pixel steps out from the center.
     float t = 0.5f;
     for (int i = 0; i < halfKernelSize; ++i) {
         float value = expf(t * t * b);
@@ -28,8 +30,11 @@
     return tot;
 }
 
+// Create a Gaussian half-kernel (right side) and a summed area table given a sigma and number
+// of discrete steps. The half kernel is normalized to sum to 0.5.
 static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel,
                                               int halfKernelSize, float sigma) {
+    // The half kernel should sum to 0.5 not 1.0.
     const float tot = 2.f * make_unnormalized_half_kernel(halfKernel, halfKernelSize, sigma);
     float sum = 0.f;
     for (int i = 0; i < halfKernelSize; ++i) {
@@ -39,6 +44,8 @@
     }
 }
 
+// Applies the 1D half kernel vertically at points along the x axis to a circle centered at the
+// origin with radius circleR.
 void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR,
                        int halfKernelSize, const float* summedHalfKernelTable) {
     float x = firstX;
@@ -48,7 +55,8 @@
             continue;
         }
         float y = sqrtf(circleR * circleR - x * x);
-
+        // In the column at x we exit the circle at +y and -y
+        // The summed table entry j is actually reflects an offset of j + 0.5.
         y -= 0.5f;
         int yInt = SkScalarFloorToInt(y);
         SkASSERT(yInt >= -1);
@@ -64,6 +72,10 @@
     }
 }
 
+// Apply a Gaussian at point (evalX, 0) to a circle centered at the origin with radius circleR.
+// This relies on having a half kernel computed for the Gaussian and a table of applications of
+// the half kernel in y to columns at (evalX - halfKernel, evalX - halfKernel + 1, ..., evalX +
+// halfKernel) passed in as yKernelEvaluations.
 static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize,
                        const float* yKernelEvaluations) {
     float acc = 0;
@@ -83,18 +95,28 @@
         float verticalEval = yKernelEvaluations[i + halfKernelSize];
         acc += verticalEval * halfKernel[i];
     }
-
+    // Since we applied a half kernel in y we multiply acc by 2 (the circle is symmetric about
+    // the x axis).
     return SkUnitScalarClampToByte(2.f * acc);
 }
 
+// This function creates a profile of a blurred circle. It does this by computing a kernel for
+// half the Gaussian and a matching summed area table. The summed area table is used to compute
+// an array of vertical applications of the half kernel to the circle along the x axis. The
+// table of y evaluations has 2 * k + n entries where k is the size of the half kernel and n is
+// the size of the profile being computed. Then for each of the n profile entries we walk out k
+// steps in each horizontal direction multiplying the corresponding y evaluation by the half
+// kernel entry and sum these values to compute the profile entry.
 static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) {
     const int numSteps = profileTextureWidth;
     uint8_t* weights = new uint8_t[numSteps];
 
+    // The full kernel is 6 sigmas wide.
     int halfKernelSize = SkScalarCeilToInt(6.0f * sigma);
-
+    // round up to next multiple of 2 and then divide by 2
     halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1;
 
+    // Number of x steps at which to apply kernel in y to cover all the profile samples in x.
     int numYSteps = numSteps + 2 * halfKernelSize;
 
     SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps);
@@ -110,34 +132,36 @@
         float evalX = i + 0.5f;
         weights[i] = eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i);
     }
-
+    // Ensure the tail of the Gaussian goes to zero.
     weights[numSteps - 1] = 0;
     return weights;
 }
 
 static uint8_t* create_half_plane_profile(int profileWidth) {
     SkASSERT(!(profileWidth & 0x1));
-
+    // The full kernel is 6 sigmas wide.
     float sigma = profileWidth / 6.f;
     int halfKernelSize = profileWidth / 2;
 
     SkAutoTArray<float> halfKernel(halfKernelSize);
     uint8_t* profile = new uint8_t[profileWidth];
 
+    // The half kernel should sum to 0.5.
     const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, sigma);
     float sum = 0.f;
-
+    // Populate the profile from the right edge to the middle.
     for (int i = 0; i < halfKernelSize; ++i) {
         halfKernel[halfKernelSize - i - 1] /= tot;
         sum += halfKernel[halfKernelSize - i - 1];
         profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum);
     }
-
+    // Populate the profile from the middle to the left edge (by flipping the half kernel and
+    // continuing the summation).
     for (int i = 0; i < halfKernelSize; ++i) {
         sum += halfKernel[i];
         profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum);
     }
-
+    // Ensure tail goes to 0.
     profile[profileWidth - 1] = 0;
     return profile;
 }
@@ -146,9 +170,13 @@
                                                     const SkRect& circle, float sigma,
                                                     float* solidRadius, float* textureRadius) {
     float circleR = circle.width() / 2.0f;
-
+    // Profile textures are cached by the ratio of sigma to circle radius and by the size of the
+    // profile texture (binned by powers of 2).
     SkScalar sigmaToCircleRRatio = sigma / circleR;
-
+    // When sigma is really small this becomes a equivalent to convolving a Gaussian with a
+    // half-plane. Similarly, in the extreme high ratio cases circle becomes a point WRT to the
+    // Guassian and the profile texture is a just a Gaussian evaluation. However, we haven't yet
+    // implemented this latter optimization.
     sigmaToCircleRRatio = SkTMin(sigmaToCircleRRatio, 8.f);
     SkFixed sigmaToCircleRRatioFixed;
     static const SkScalar kHalfPlaneThreshold = 0.1f;
@@ -159,8 +187,10 @@
         *solidRadius = circleR - 3 * sigma;
         *textureRadius = 6 * sigma;
     } else {
+        // Convert to fixed point for the key.
         sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio);
-
+        // We shave off some bits to reduce the number of unique entries. We could probably
+        // shave off more than we do.
         sigmaToCircleRRatioFixed &= ~0xff;
         sigmaToCircleRRatio = SkFixedToScalar(sigmaToCircleRRatioFixed);
         sigma = circleR * sigmaToCircleRRatio;
@@ -188,6 +218,7 @@
         if (useHalfPlaneApprox) {
             profile.reset(create_half_plane_profile(kProfileTextureWidth));
         } else {
+            // Rescale params to the size of the texture we're creating.
             SkScalar scale = kProfileTextureWidth / *textureRadius;
             profile.reset(
                     create_circle_profile(sigma * scale, circleR * scale, kProfileTextureWidth));
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp
index e9443a8..3039145 100644
--- a/src/gpu/effects/GrEllipseEffect.cpp
+++ b/src/gpu/effects/GrEllipseEffect.cpp
@@ -72,7 +72,9 @@
         if (radii != prevRadii || center != prevCenter) {
             float invRXSqd;
             float invRYSqd;
-
+            // If we're using a scale factor to work around precision issues, choose the larger
+            // radius as the scale factor. The inv radii need to be pre-adjusted by the scale
+            // factor.
             if (scale.isValid()) {
                 if (radii.fX > radii.fY) {
                     invRXSqd = 1.f;
diff --git a/src/gpu/effects/GrSimpleTextureEffect.h b/src/gpu/effects/GrSimpleTextureEffect.h
index 8d3fba1..6e8fa28 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/GrSimpleTextureEffect.h
@@ -30,6 +30,7 @@
                                                          GrSamplerState::Filter::kNearest)));
     }
 
+    /* clamp mode */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
                                                      sk_sp<GrColorSpaceXform>
                                                              colorSpaceXform,
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index e8964db..5fd4229 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -319,7 +319,7 @@
                     break;
                 }
                 default:
-                    this->addExpression(cfg, &b->fLeft, !Token::IsAssignment(b->fOperator));
+                    this->addExpression(cfg, &b->fLeft, !Compiler::IsAssignment(b->fOperator));
                     this->addExpression(cfg, &b->fRight, constantPropagate);
                     cfg.fBlocks[cfg.fCurrent].fNodes.push_back({
                         BasicBlock::Node::kExpression_Kind,
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 17bcf0d..e84954e 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -14,7 +14,7 @@
 
 static bool needs_uniform_var(const Variable& var) {
     return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
-           strcmp(var.fType.fName.c_str(), "colorSpaceXform");
+           var.fType.fName != "colorSpaceXform";
 }
 
 CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
@@ -58,7 +58,7 @@
     if (type.kind() == Type::kStruct_Kind) {
         INHERITED::writeType(type);
     } else {
-        this->write(type.name());
+        this->write(type.fName);
     }
 }
 void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
@@ -87,7 +87,7 @@
         if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
             this->write("%s");
             if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
-                fErrors.error(i.fIndex->fPosition,
+                fErrors.error(i.fIndex->fOffset,
                               "index into sk_TransformedCoords2D must be an integer literal");
                 return;
             }
@@ -104,7 +104,7 @@
         } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
             this->write("%s");
             if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
-                fErrors.error(i.fIndex->fPosition,
+                fErrors.error(i.fIndex->fOffset,
                               "index into sk_TextureSamplers must be an integer literal");
                 return;
             }
@@ -118,16 +118,15 @@
 }
 
 static const char* default_value(const Type& type) {
-    const char* name = type.name().c_str();
-    if (!strcmp(name, "float")) {
+    if (type.fName == "float") {
         return "0.0";
-    } else if (!strcmp(name, "float2")) {
+    } else if (type.fName == "float2") {
         return "float2(0.0)";
-    } else if (!strcmp(name, "float3")) {
+    } else if (type.fName == "float3") {
         return "float30.0)";
-    } else if (!strcmp(name, "float4")) {
+    } else if (type.fName == "float4") {
         return "float4(0.0)";
-    } else if (!strcmp(name, "floatt4x4") || !strcmp(name, "colorSpaceXform")) {
+    } else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") {
         return "float4x4(1.0)";
     }
     ABORT("unsupported default_value type\n");
@@ -155,7 +154,8 @@
         fFormatArgs.push_back(cppCode + ".fX");
         fFormatArgs.push_back(cppCode + ".fY");
     } else {
-        printf("%s\n", type.name().c_str());
+        this->write(type.fName);
+        this->write("\n");
         ABORT("unsupported runtime value type\n");
     }
 }
@@ -227,11 +227,11 @@
                 }
                 fFormatArgs.push_back(code);
             } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
-                const char* name = ref.fVariable.fName.c_str();
+                String name(ref.fVariable.fName);
                 this->writeRuntimeValue(ref.fVariable.fType,
-                                        String::printf("_outer.%s()", name).c_str());
+                                        String::printf("_outer.%s()", name.c_str()).c_str());
             } else {
-                this->write(ref.fVariable.fName.c_str());
+                this->write(ref.fVariable.fName);
             }
     }
 }
@@ -358,14 +358,16 @@
                var.fType == *fContext.fColorSpaceXform_Type) {
         type = "kMat44f_GrSLType";
     } else {
-        ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str());
+        ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
+              String(var.fName).c_str());
     }
     if (var.fModifiers.fLayout.fWhen.size()) {
         this->writef("        if (%s) {\n    ", var.fModifiers.fLayout.fWhen.c_str());
     }
-    const char* name = var.fName.c_str();
+    String name(var.fName);
     this->writef("        %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
-                 "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name);
+                 "%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision,
+                 name.c_str());
     if (var.fModifiers.fLayout.fWhen.size()) {
         this->write("        }\n");
     }
@@ -380,7 +382,7 @@
                 if (is_private(*decl.fVar)) {
                     this->writef("%s %s;\n",
                                  HCodeGenerator::FieldType(decl.fVar->fType).c_str(),
-                                 decl.fVar->fName.c_str());
+                                 String(decl.fVar->fName).c_str());
                 }
             }
         }
@@ -395,7 +397,7 @@
                 VarDeclaration& decl = (VarDeclaration&) *raw;
                 if (is_private(*decl.fVar) && decl.fValue) {
                     this->writef("%s = %s;\n",
-                                 decl.fVar->fName.c_str(),
+                                 String(decl.fVar->fName).c_str(),
                                  decl.fValue->description().c_str());
                 }
             }
@@ -414,12 +416,12 @@
         this->addUniform(*u);
         if (u->fType == *fContext.fColorSpaceXform_Type) {
             if (fNeedColorSpaceHelper) {
-                fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported");
+                fErrors.error(u->fOffset, "only a single ColorSpaceXform is supported");
             }
             fNeedColorSpaceHelper = true;
             this->writef("        fColorSpaceHelper.emitCode(args.fUniformHandler, "
                                                             "_outer.%s().get());\n",
-                         u->fName.c_str());
+                         String(u->fName).c_str());
         }
     }
     this->writeSection(EMIT_CODE_SECTION);
@@ -453,7 +455,8 @@
                 wroteProcessor = true;
                 this->writef("        {\n");
             }
-            const char* name = u->fName.c_str();
+            String nameString(u->fName);
+            const char* name = nameString.c_str();
             if (u->fType == *fContext.fFloat4_Type) {
                 this->writef("        const SkRect %sValue = _outer.%s();\n"
                              "        %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
@@ -485,13 +488,13 @@
                 const VarDeclarations* decls = (const VarDeclarations*) p.get();
                 for (const auto& raw : decls->fVars) {
                     VarDeclaration& decl = (VarDeclaration&) *raw;
+                    String nameString(decl.fVar->fName);
+                    const char* name = nameString.c_str();
                     if (needs_uniform_var(*decl.fVar)) {
-                        const char* name = decl.fVar->fName.c_str();
                         this->writef("        UniformHandle& %s = %sVar;\n"
                                      "        (void) %s;\n",
                                      name, HCodeGenerator::FieldName(name).c_str(), name);
                     } else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) {
-                        const char* name = decl.fVar->fName.c_str();
                         if (!wroteProcessor) {
                             this->writef("        const %s& _outer = _proc.cast<%s>();\n", fullName,
                                          fullName);
@@ -512,14 +515,14 @@
 void CPPCodeGenerator::writeClone() {
     if (!this->writeSection(CLONE_SECTION)) {
         if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) {
-            fErrors.error(Position(1, 1), "fragment processors with custom @fields must also have "
-                                          "a custom @clone");
+            fErrors.error(0, "fragment processors with custom @fields must also have a custom"
+                             "@clone");
         }
         this->writef("%s::%s(const %s& src)\n"
                      ": INHERITED(src.optimizationFlags())", fFullName.c_str(), fFullName.c_str(),
                      fFullName.c_str());
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-            String fieldName = HCodeGenerator::FieldName(param->fName.c_str());
+            String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
             this->writef("\n, %s(%s)",
                          fieldName.c_str(),
                          ("src." + fieldName).c_str());
@@ -535,7 +538,7 @@
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
             if (param->fType.kind() == Type::kSampler_Kind) {
                 this->writef("    this->addTextureSampler(&%s);\n",
-                             HCodeGenerator::FieldName(param->fName.c_str()).c_str());
+                             HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
             }
         }
         for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
@@ -572,7 +575,8 @@
                                                 "GrProcessorKeyBuilder* b) const {\n",
                  fFullName.c_str());
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        const char* name = param->fName.c_str();
+        String nameString(param->fName);
+        const char* name = nameString.c_str();
         if (param->fType == *fContext.fColorSpaceXform_Type) {
             this->writef("    b->add32(GrColorSpaceXform::XformKey(%s.get()));\n",
                          HCodeGenerator::FieldName(name).c_str());
@@ -580,7 +584,7 @@
         }
         if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
             (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
-            fErrors.error(param->fPosition,
+            fErrors.error(param->fOffset,
                           "layout(key) may not be specified on uniforms");
         }
         switch (param->fModifiers.fLayout.fKey) {
@@ -608,7 +612,7 @@
                 break;
             case Layout::kIdentity_Key:
                 if (param->fType.kind() != Type::kMatrix_Kind) {
-                    fErrors.error(param->fPosition,
+                    fErrors.error(param->fOffset,
                                   "layout(key=identity) requires matrix type");
                 }
                 this->writef("    b->add32(%s.isIdentity() ? 1 : 0);\n",
@@ -656,15 +660,15 @@
     this->writeSetData(uniforms);
     this->writePrivateVars();
     for (const auto& u : uniforms) {
-        const char* name = u->fName.c_str();
         if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
-            this->writef("    UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
+            this->writef("    UniformHandle %sVar;\n",
+                         HCodeGenerator::FieldName(String(u->fName).c_str()).c_str());
         }
     }
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        const char* name = param->fName.c_str();
         if (needs_uniform_var(*param)) {
-            this->writef("    UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
+            this->writef("    UniformHandle %sVar;\n",
+                         HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
         }
     }
     if (fNeedColorSpaceHelper) {
@@ -681,7 +685,8 @@
                  "    (void) that;\n",
                  fullName, fullName, fullName);
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        const char* name = param->fName.c_str();
+        String nameString(param->fName);
+        const char* name = nameString.c_str();
         this->writef("    if (%s != that.%s) return false;\n",
                      HCodeGenerator::FieldName(name).c_str(),
                      HCodeGenerator::FieldName(name).c_str());
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 4ea956c..638e4d6 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -51,7 +51,6 @@
 #include "sksl_fp.include"
 ;
 
-
 namespace SkSL {
 
 Compiler::Compiler(Flags flags)
@@ -187,20 +186,23 @@
     ADD_TYPE(GSamplerCubeArrayShadow);
     ADD_TYPE(ColorSpaceXform);
 
-    String skCapsName("sk_Caps");
-    Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
+    StringFragment skCapsName("sk_Caps");
+    Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
                                     *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
     fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
 
-    String skArgsName("sk_Args");
-    Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName,
+    StringFragment skArgsName("sk_Args");
+    Variable* skArgs = new Variable(-1, Modifiers(), skArgsName,
                                     *fContext.fSkArgs_Type, Variable::kGlobal_Storage);
     fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
 
     Modifiers::Flag ignored1;
     std::vector<std::unique_ptr<ProgramElement>> ignored2;
-    fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
+    fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
+    if (fErrorCount) {
+        printf("Unexpected errors: %s\n", fErrorText.c_str());
+    }
     ASSERT(!fErrorCount);
 }
 
@@ -260,7 +262,7 @@
                     BinaryExpression* b = (BinaryExpression*) expr;
                     if (b->fOperator == Token::EQ) {
                         this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
-                    } else if (Token::IsAssignment(b->fOperator)) {
+                    } else if (Compiler::IsAssignment(b->fOperator)) {
                         this->addDefinition(
                                        b->fLeft.get(),
                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
@@ -401,7 +403,7 @@
  * to a dead target and lack of side effects on the left hand side.
  */
 static bool dead_assignment(const BinaryExpression& b) {
-    if (!Token::IsAssignment(b.fOperator)) {
+    if (!Compiler::IsAssignment(b.fOperator)) {
         return false;
     }
     return is_dead(*b.fLeft);
@@ -540,7 +542,7 @@
 static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
     std::vector<std::unique_ptr<Expression>> args;
     args.push_back(std::move(v));
-    auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
+    auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
     return result;
 }
 
@@ -642,7 +644,7 @@
             if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
                 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
                 (*undefinedVariables).insert(&var);
-                this->error(expr->fPosition,
+                this->error(expr->fOffset,
                             "'" + var.fName + "' has not been assigned");
             }
             break;
@@ -877,7 +879,7 @@
     for (const auto& s : statementPtrs) {
         statements.push_back(std::move(*s));
     }
-    return std::unique_ptr<Statement>(new Block(Position(), std::move(statements), s->fSymbols));
+    return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols));
 }
 
 void Compiler::simplifyStatement(DefinitionMap& definitions,
@@ -964,7 +966,7 @@
                             break;
                         } else {
                             if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
-                                this->error(s.fPosition,
+                                this->error(s.fOffset,
                                             "static switch contains non-static conditional break");
                                 s.fIsStatic = false;
                             }
@@ -980,7 +982,7 @@
                             (*iter)->setStatement(std::move(newBlock));
                         } else {
                             if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
-                                this->error(s.fPosition,
+                                this->error(s.fOffset,
                                             "static switch contains non-static conditional break");
                                 s.fIsStatic = false;
                             }
@@ -1022,16 +1024,16 @@
     for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
         if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
             cfg.fBlocks[i].fNodes.size()) {
-            Position p;
+            int offset;
             switch (cfg.fBlocks[i].fNodes[0].fKind) {
                 case BasicBlock::Node::kStatement_Kind:
-                    p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
+                    offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset;
                     break;
                 case BasicBlock::Node::kExpression_Kind:
-                    p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
+                    offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
                     break;
             }
-            this->error(p, String("unreachable"));
+            this->error(offset, String("unreachable"));
         }
     }
     if (fErrorCount) {
@@ -1081,14 +1083,14 @@
                     case Statement::kIf_Kind:
                         if (((const IfStatement&) s).fIsStatic &&
                             !(fFlags & kPermitInvalidStaticTests_Flag)) {
-                            this->error(s.fPosition, "static if has non-static test");
+                            this->error(s.fOffset, "static if has non-static test");
                         }
                         ++iter;
                         break;
                     case Statement::kSwitch_Kind:
                         if (((const SwitchStatement&) s).fIsStatic &&
                              !(fFlags & kPermitInvalidStaticTests_Flag)) {
-                            this->error(s.fPosition, "static switch has non-static test");
+                            this->error(s.fOffset, "static switch has non-static test");
                         }
                         ++iter;
                         break;
@@ -1121,7 +1123,7 @@
     // check for missing return
     if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
         if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
-            this->error(f.fPosition, String("function can exit without returning a value"));
+            this->error(f.fOffset, String("function can exit without returning a value"));
         }
     }
 }
@@ -1135,21 +1137,28 @@
     Modifiers::Flag ignored;
     switch (kind) {
         case Program::kVertex_Kind:
-            fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
+            fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes,
+                                         &ignored, &elements);
             break;
         case Program::kFragment_Kind:
-            fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
+            fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes,
+                                         &ignored, &elements);
             break;
         case Program::kGeometry_Kind:
-            fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
+            fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes,
+                                         &ignored, &elements);
             break;
         case Program::kFragmentProcessor_Kind:
-            fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
+            fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
+                                         &ignored, &elements);
             break;
     }
     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
     Modifiers::Flag defaultPrecision;
-    fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements);
+    std::unique_ptr<String> textPtr(new String(std::move(text)));
+    fSource = textPtr.get();
+    fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &defaultPrecision,
+                                 &elements);
     if (!fErrorCount) {
         for (auto& element : elements) {
             if (element->fKind == ProgramElement::kFunction_Kind) {
@@ -1157,11 +1166,13 @@
             }
         }
     }
-    auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
+    auto result = std::unique_ptr<Program>(new Program(kind, std::move(textPtr), settings,
+                                                       defaultPrecision, &fContext,
                                                        std::move(elements),
                                                        fIRGenerator->fSymbolTable,
                                                        fIRGenerator->fInputs));
     fIRGenerator->finish();
+    fSource = nullptr;
     this->writeErrorCount();
     if (fErrorCount) {
         return nullptr;
@@ -1172,8 +1183,10 @@
 bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
 #ifdef SK_ENABLE_SPIRV_VALIDATION
     StringStream buffer;
+    fSource = program.fSource.get();
     SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
     bool result = cg.generateCode();
+    fSource = nullptr;
     if (result) {
         spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
         const String& data = buffer.str();
@@ -1188,8 +1201,10 @@
         out.write(data.c_str(), data.size());
     }
 #else
+    fSource = program.fSource.get();
     SPIRVCodeGenerator cg(&fContext, &program, this, &out);
     bool result = cg.generateCode();
+    fSource = nullptr;
 #endif
     this->writeErrorCount();
     return result;
@@ -1205,8 +1220,10 @@
 }
 
 bool Compiler::toGLSL(const Program& program, OutputStream& out) {
+    fSource = program.fSource.get();
     GLSLCodeGenerator cg(&fContext, &program, this, &out);
     bool result = cg.generateCode();
+    fSource = nullptr;
     this->writeErrorCount();
     return result;
 }
@@ -1221,22 +1238,111 @@
 }
 
 bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
+    fSource = program.fSource.get();
     CPPCodeGenerator cg(&fContext, &program, this, name, &out);
     bool result = cg.generateCode();
+    fSource = nullptr;
     this->writeErrorCount();
     return result;
 }
 
 bool Compiler::toH(const Program& program, String name, OutputStream& out) {
+    fSource = program.fSource.get();
     HCodeGenerator cg(&program, this, name, &out);
     bool result = cg.generateCode();
+    fSource = nullptr;
     this->writeErrorCount();
     return result;
 }
 
-void Compiler::error(Position position, String msg) {
+const char* Compiler::OperatorName(Token::Kind kind) {
+    switch (kind) {
+        case Token::PLUS:         return "+";
+        case Token::MINUS:        return "-";
+        case Token::STAR:         return "*";
+        case Token::SLASH:        return "/";
+        case Token::PERCENT:      return "%";
+        case Token::SHL:          return "<<";
+        case Token::SHR:          return ">>";
+        case Token::LOGICALNOT:   return "!";
+        case Token::LOGICALAND:   return "&&";
+        case Token::LOGICALOR:    return "||";
+        case Token::LOGICALXOR:   return "^^";
+        case Token::BITWISENOT:   return "~";
+        case Token::BITWISEAND:   return "&";
+        case Token::BITWISEOR:    return "|";
+        case Token::BITWISEXOR:   return "^";
+        case Token::EQ:           return "=";
+        case Token::EQEQ:         return "==";
+        case Token::NEQ:          return "!=";
+        case Token::LT:           return "<";
+        case Token::GT:           return ">";
+        case Token::LTEQ:         return "<=";
+        case Token::GTEQ:         return ">=";
+        case Token::PLUSEQ:       return "+=";
+        case Token::MINUSEQ:      return "-=";
+        case Token::STAREQ:       return "*=";
+        case Token::SLASHEQ:      return "/=";
+        case Token::PERCENTEQ:    return "%=";
+        case Token::SHLEQ:        return "<<=";
+        case Token::SHREQ:        return ">>=";
+        case Token::LOGICALANDEQ: return "&&=";
+        case Token::LOGICALOREQ:  return "||=";
+        case Token::LOGICALXOREQ: return "^^=";
+        case Token::BITWISEANDEQ: return "&=";
+        case Token::BITWISEOREQ:  return "|=";
+        case Token::BITWISEXOREQ: return "^=";
+        case Token::PLUSPLUS:     return "++";
+        case Token::MINUSMINUS:   return "--";
+        case Token::COMMA:        return ",";
+        default:
+            ABORT("unsupported operator: %d\n", kind);
+    }
+}
+
+
+bool Compiler::IsAssignment(Token::Kind op) {
+    switch (op) {
+        case Token::EQ:           // fall through
+        case Token::PLUSEQ:       // fall through
+        case Token::MINUSEQ:      // fall through
+        case Token::STAREQ:       // fall through
+        case Token::SLASHEQ:      // fall through
+        case Token::PERCENTEQ:    // fall through
+        case Token::SHLEQ:        // fall through
+        case Token::SHREQ:        // fall through
+        case Token::BITWISEOREQ:  // fall through
+        case Token::BITWISEXOREQ: // fall through
+        case Token::BITWISEANDEQ: // fall through
+        case Token::LOGICALOREQ:  // fall through
+        case Token::LOGICALXOREQ: // fall through
+        case Token::LOGICALANDEQ:
+            return true;
+        default:
+            return false;
+    }
+}
+
+Position Compiler::position(int offset) {
+    ASSERT(fSource);
+    int line = 1;
+    int column = 1;
+    for (int i = 0; i < offset; i++) {
+        if ((*fSource)[i] == '\n') {
+            ++line;
+            column = 1;
+        }
+        else {
+            ++column;
+        }
+    }
+    return Position(line, column);
+}
+
+void Compiler::error(int offset, String msg) {
     fErrorCount++;
-    fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
+    Position pos = this->position(offset);
+    fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n";
 }
 
 String Compiler::errorText() {
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 38f63e5..894ac41 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -16,7 +16,6 @@
 #include "SkSLCFGGenerator.h"
 #include "SkSLContext.h"
 #include "SkSLErrorReporter.h"
-#include "SkSLIRGenerator.h"
 
 #define SK_FRAGCOLOR_BUILTIN           10001
 #define SK_IN_BUILTIN                  10002
@@ -70,7 +69,7 @@
 
     bool toH(const Program& program, String name, OutputStream& out);
 
-    void error(Position position, String msg) override;
+    void error(int offset, String msg) override;
 
     String errorText();
 
@@ -80,6 +79,10 @@
         return fErrorCount;
     }
 
+    static const char* OperatorName(Token::Kind token);
+
+    static bool IsAssignment(Token::Kind token);
+
 private:
     void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
                        DefinitionMap* definitions);
@@ -114,11 +117,14 @@
 
     void scanCFG(FunctionDefinition& f);
 
+    Position position(int offset);
+
     std::shared_ptr<SymbolTable> fTypes;
     IRGenerator* fIRGenerator;
     String fSkiaVertText; // FIXME store parsed version instead
     int fFlags;
 
+    const String* fSource;
     Context fContext;
     int fErrorCount;
     String fErrorText;
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index b132cec..e421695 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -19,172 +19,172 @@
 class Context {
 public:
     Context()
-    : fInvalid_Type(new Type(String("<INVALID>")))
-    , fVoid_Type(new Type(String("void")))
-    , fDouble_Type(new Type(String("double"), Type::kFloat_NumberKind))
-    , fDouble2_Type(new Type(String("double2"), *fDouble_Type, 2))
-    , fDouble3_Type(new Type(String("double3"), *fDouble_Type, 3))
-    , fDouble4_Type(new Type(String("double4"), *fDouble_Type, 4))
-    , fFloat_Type(new Type(String("float"), Type::kFloat_NumberKind))
-    , fFloat2_Type(new Type(String("float2"), *fFloat_Type, 2))
-    , fFloat3_Type(new Type(String("float3"), *fFloat_Type, 3))
-    , fFloat4_Type(new Type(String("float4"), *fFloat_Type, 4))
-    , fHalf_Type(new Type(String("half"), Type::kFloat_NumberKind))
-    , fHalf2_Type(new Type(String("half2"), *fHalf_Type, 2))
-    , fHalf3_Type(new Type(String("half3"), *fHalf_Type, 3))
-    , fHalf4_Type(new Type(String("half4"), *fHalf_Type, 4))
-    , fUInt_Type(new Type(String("uint"), Type::kUnsigned_NumberKind))
-    , fUInt2_Type(new Type(String("uint2"), *fUInt_Type, 2))
-    , fUInt3_Type(new Type(String("uint3"), *fUInt_Type, 3))
-    , fUInt4_Type(new Type(String("uint4"), *fUInt_Type, 4))
-    , fInt_Type(new Type(String("int"), Type::kSigned_NumberKind))
-    , fInt2_Type(new Type(String("int2"), *fInt_Type, 2))
-    , fInt3_Type(new Type(String("int3"), *fInt_Type, 3))
-    , fInt4_Type(new Type(String("int4"), *fInt_Type, 4))
-    , fUShort_Type(new Type(String("ushort"), Type::kUnsigned_NumberKind))
-    , fUShort2_Type(new Type(String("ushort2"), *fUShort_Type, 2))
-    , fUShort3_Type(new Type(String("ushort3"), *fUShort_Type, 3))
-    , fUShort4_Type(new Type(String("ushort4"), *fUShort_Type, 4))
-    , fShort_Type(new Type(String("short"), Type::kSigned_NumberKind))
-    , fShort2_Type(new Type(String("short2"), *fShort_Type, 2))
-    , fShort3_Type(new Type(String("short3"), *fShort_Type, 3))
-    , fShort4_Type(new Type(String("short4"), *fShort_Type, 4))
-    , fBool_Type(new Type(String("bool"), Type::kNonnumeric_NumberKind))
-    , fBool2_Type(new Type(String("bool2"), *fBool_Type, 2))
-    , fBool3_Type(new Type(String("bool3"), *fBool_Type, 3))
-    , fBool4_Type(new Type(String("bool4"), *fBool_Type, 4))
-    , fFloat2x2_Type(new Type(String("float2x2"), *fFloat_Type, 2, 2))
-    , fFloat2x3_Type(new Type(String("float2x3"), *fFloat_Type, 2, 3))
-    , fFloat2x4_Type(new Type(String("float2x4"), *fFloat_Type, 2, 4))
-    , fFloat3x2_Type(new Type(String("float3x2"), *fFloat_Type, 3, 2))
-    , fFloat3x3_Type(new Type(String("float3x3"), *fFloat_Type, 3, 3))
-    , fFloat3x4_Type(new Type(String("float3x4"), *fFloat_Type, 3, 4))
-    , fFloat4x2_Type(new Type(String("float4x2"), *fFloat_Type, 4, 2))
-    , fFloat4x3_Type(new Type(String("float4x3"), *fFloat_Type, 4, 3))
-    , fFloat4x4_Type(new Type(String("float4x4"), *fFloat_Type, 4, 4))
-    , fHalf2x2_Type(new Type(String("half2x2"), *fHalf_Type, 2, 2))
-    , fHalf2x3_Type(new Type(String("half2x3"), *fHalf_Type, 2, 3))
-    , fHalf2x4_Type(new Type(String("half2x4"), *fHalf_Type, 2, 4))
-    , fHalf3x2_Type(new Type(String("half3x2"), *fHalf_Type, 3, 2))
-    , fHalf3x3_Type(new Type(String("half3x3"), *fHalf_Type, 3, 3))
-    , fHalf3x4_Type(new Type(String("half3x4"), *fHalf_Type, 3, 4))
-    , fHalf4x2_Type(new Type(String("half4x2"), *fHalf_Type, 4, 2))
-    , fHalf4x3_Type(new Type(String("half4x3"), *fHalf_Type, 4, 3))
-    , fHalf4x4_Type(new Type(String("half4x4"), *fHalf_Type, 4, 4))
-    , fDouble2x2_Type(new Type(String("double2x2"), *fDouble_Type, 2, 2))
-    , fDouble2x3_Type(new Type(String("double2x3"), *fDouble_Type, 2, 3))
-    , fDouble2x4_Type(new Type(String("double2x4"), *fDouble_Type, 2, 4))
-    , fDouble3x2_Type(new Type(String("double3x2"), *fDouble_Type, 3, 2))
-    , fDouble3x3_Type(new Type(String("double3x3"), *fDouble_Type, 3, 3))
-    , fDouble3x4_Type(new Type(String("double3x4"), *fDouble_Type, 3, 4))
-    , fDouble4x2_Type(new Type(String("double4x2"), *fDouble_Type, 4, 2))
-    , fDouble4x3_Type(new Type(String("double4x3"), *fDouble_Type, 4, 3))
-    , fDouble4x4_Type(new Type(String("double4x4"), *fDouble_Type, 4, 4))
-    , fSampler1D_Type(new Type(String("sampler1D"), SpvDim1D, false, false, false, true))
-    , fSampler2D_Type(new Type(String("sampler2D"), SpvDim2D, false, false, false, true))
-    , fSampler3D_Type(new Type(String("sampler3D"), SpvDim3D, false, false, false, true))
-    , fSamplerExternalOES_Type(new Type(String("samplerExternalOES"), SpvDim2D, false, false,
+    : fInvalid_Type(new Type("<INVALID>"))
+    , fVoid_Type(new Type("void"))
+    , fDouble_Type(new Type("double", Type::kFloat_NumberKind))
+    , fDouble2_Type(new Type("double2", *fDouble_Type, 2))
+    , fDouble3_Type(new Type("double3", *fDouble_Type, 3))
+    , fDouble4_Type(new Type("double4", *fDouble_Type, 4))
+    , fFloat_Type(new Type("float", Type::kFloat_NumberKind))
+    , fFloat2_Type(new Type("float2", *fFloat_Type, 2))
+    , fFloat3_Type(new Type("float3", *fFloat_Type, 3))
+    , fFloat4_Type(new Type("float4", *fFloat_Type, 4))
+    , fHalf_Type(new Type("half", Type::kFloat_NumberKind))
+    , fHalf2_Type(new Type("half2", *fHalf_Type, 2))
+    , fHalf3_Type(new Type("half3", *fHalf_Type, 3))
+    , fHalf4_Type(new Type("half4", *fHalf_Type, 4))
+    , fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind))
+    , fUInt2_Type(new Type("uint2", *fUInt_Type, 2))
+    , fUInt3_Type(new Type("uint3", *fUInt_Type, 3))
+    , fUInt4_Type(new Type("uint4", *fUInt_Type, 4))
+    , fInt_Type(new Type("int", Type::kSigned_NumberKind))
+    , fInt2_Type(new Type("int2", *fInt_Type, 2))
+    , fInt3_Type(new Type("int3", *fInt_Type, 3))
+    , fInt4_Type(new Type("int4", *fInt_Type, 4))
+    , fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind))
+    , fUShort2_Type(new Type("ushort2", *fUShort_Type, 2))
+    , fUShort3_Type(new Type("ushort3", *fUShort_Type, 3))
+    , fUShort4_Type(new Type("ushort4", *fUShort_Type, 4))
+    , fShort_Type(new Type("short", Type::kSigned_NumberKind))
+    , fShort2_Type(new Type("short2", *fShort_Type, 2))
+    , fShort3_Type(new Type("short3", *fShort_Type, 3))
+    , fShort4_Type(new Type("short4", *fShort_Type, 4))
+    , fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind))
+    , fBool2_Type(new Type("bool2", *fBool_Type, 2))
+    , fBool3_Type(new Type("bool3", *fBool_Type, 3))
+    , fBool4_Type(new Type("bool4", *fBool_Type, 4))
+    , fFloat2x2_Type(new Type("float2x2", *fFloat_Type, 2, 2))
+    , fFloat2x3_Type(new Type("float2x3", *fFloat_Type, 2, 3))
+    , fFloat2x4_Type(new Type("float2x4", *fFloat_Type, 2, 4))
+    , fFloat3x2_Type(new Type("float3x2", *fFloat_Type, 3, 2))
+    , fFloat3x3_Type(new Type("float3x3", *fFloat_Type, 3, 3))
+    , fFloat3x4_Type(new Type("float3x4", *fFloat_Type, 3, 4))
+    , fFloat4x2_Type(new Type("float4x2", *fFloat_Type, 4, 2))
+    , fFloat4x3_Type(new Type("float4x3", *fFloat_Type, 4, 3))
+    , fFloat4x4_Type(new Type("float4x4", *fFloat_Type, 4, 4))
+    , fHalf2x2_Type(new Type("half2x2", *fHalf_Type, 2, 2))
+    , fHalf2x3_Type(new Type("half2x3", *fHalf_Type, 2, 3))
+    , fHalf2x4_Type(new Type("half2x4", *fHalf_Type, 2, 4))
+    , fHalf3x2_Type(new Type("half3x2", *fHalf_Type, 3, 2))
+    , fHalf3x3_Type(new Type("half3x3", *fHalf_Type, 3, 3))
+    , fHalf3x4_Type(new Type("half3x4", *fHalf_Type, 3, 4))
+    , fHalf4x2_Type(new Type("half4x2", *fHalf_Type, 4, 2))
+    , fHalf4x3_Type(new Type("half4x3", *fHalf_Type, 4, 3))
+    , fHalf4x4_Type(new Type("half4x4", *fHalf_Type, 4, 4))
+    , fDouble2x2_Type(new Type("double2x2", *fDouble_Type, 2, 2))
+    , fDouble2x3_Type(new Type("double2x3", *fDouble_Type, 2, 3))
+    , fDouble2x4_Type(new Type("double2x4", *fDouble_Type, 2, 4))
+    , fDouble3x2_Type(new Type("double3x2", *fDouble_Type, 3, 2))
+    , fDouble3x3_Type(new Type("double3x3", *fDouble_Type, 3, 3))
+    , fDouble3x4_Type(new Type("double3x4", *fDouble_Type, 3, 4))
+    , fDouble4x2_Type(new Type("double4x2", *fDouble_Type, 4, 2))
+    , fDouble4x3_Type(new Type("double4x3", *fDouble_Type, 4, 3))
+    , fDouble4x4_Type(new Type("double4x4", *fDouble_Type, 4, 4))
+    , fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true))
+    , fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true))
+    , fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
+    , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false,
                                         false, true))
-    , fSamplerCube_Type(new Type(String("samplerCube"), SpvDimCube, false, false, false, true))
-    , fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false, true))
-    , fSampler1DArray_Type(new Type(String("sampler1DArray")))
-    , fSampler2DArray_Type(new Type(String("sampler2DArray")))
-    , fSamplerCubeArray_Type(new Type(String("samplerCubeArray")))
-    , fSamplerBuffer_Type(new Type(String("samplerBuffer"), SpvDimBuffer, false, false, false,
+    , fSamplerCube_Type(new Type("samplerCube", SpvDimCube, false, false, false, true))
+    , fSampler2DRect_Type(new Type("sampler2DRect", SpvDimRect, false, false, false, true))
+    , fSampler1DArray_Type(new Type("sampler1DArray"))
+    , fSampler2DArray_Type(new Type("sampler2DArray"))
+    , fSamplerCubeArray_Type(new Type("samplerCubeArray"))
+    , fSamplerBuffer_Type(new Type("samplerBuffer", SpvDimBuffer, false, false, false,
                                    true))
-    , fSampler2DMS_Type(new Type(String("sampler2DMS")))
-    , fSampler2DMSArray_Type(new Type(String("sampler2DMSArray")))
-    , fSampler1DShadow_Type(new Type(String("sampler1DShadow")))
-    , fSampler2DShadow_Type(new Type(String("sampler2DShadow")))
-    , fSamplerCubeShadow_Type(new Type(String("samplerCubeShadow")))
-    , fSampler2DRectShadow_Type(new Type(String("sampler2DRectShadow")))
-    , fSampler1DArrayShadow_Type(new Type(String("sampler1DArrayShadow")))
-    , fSampler2DArrayShadow_Type(new Type(String("sampler2DArrayShadow")))
-    , fSamplerCubeArrayShadow_Type(new Type(String("samplerCubeArrayShadow")))
+    , fSampler2DMS_Type(new Type("sampler2DMS"))
+    , fSampler2DMSArray_Type(new Type("sampler2DMSArray"))
+    , fSampler1DShadow_Type(new Type("sampler1DShadow"))
+    , fSampler2DShadow_Type(new Type("sampler2DShadow"))
+    , fSamplerCubeShadow_Type(new Type("samplerCubeShadow"))
+    , fSampler2DRectShadow_Type(new Type("sampler2DRectShadow"))
+    , fSampler1DArrayShadow_Type(new Type("sampler1DArrayShadow"))
+    , fSampler2DArrayShadow_Type(new Type("sampler2DArrayShadow"))
+    , fSamplerCubeArrayShadow_Type(new Type("samplerCubeArrayShadow"))
 
     // Related to below FIXME, gsampler*s don't currently expand to cover integer case.
-    , fISampler2D_Type(new Type(String("isampler2D"), SpvDim2D, false, false, false, true))
+    , fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true))
 
     // FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D.
-    , fImage2D_Type(new Type(String("image2D"), SpvDim2D, false, false, false, true))
-    , fIImage2D_Type(new Type(String("iimage2D"), SpvDim2D, false, false, false, true))
+    , fImage2D_Type(new Type("image2D", SpvDim2D, false, false, false, true))
+    , fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true))
 
     // FIXME express these as "gsubpassInput" that expand to subpassInput, isubpassInput,
     // and usubpassInput.
-    , fSubpassInput_Type(new Type(String("subpassInput"), SpvDimSubpassData, false, false,
-                                           false, false))
-    , fSubpassInputMS_Type(new Type(String("subpassInputMS"), SpvDimSubpassData, false, false,
-                                             true, false))
+    , fSubpassInput_Type(new Type("subpassInput", SpvDimSubpassData, false, false,
+                                  false, false))
+    , fSubpassInputMS_Type(new Type("subpassInputMS", SpvDimSubpassData, false, false,
+                                    true, false))
 
     // FIXME figure out what we're supposed to do with the gsampler et al. types)
-    , fGSampler1D_Type(new Type(String("$gsampler1D"), static_type(*fSampler1D_Type)))
-    , fGSampler2D_Type(new Type(String("$gsampler2D"), static_type(*fSampler2D_Type)))
-    , fGSampler3D_Type(new Type(String("$gsampler3D"), static_type(*fSampler3D_Type)))
-    , fGSamplerCube_Type(new Type(String("$gsamplerCube"), static_type(*fSamplerCube_Type)))
-    , fGSampler2DRect_Type(new Type(String("$gsampler2DRect"), static_type(*fSampler2DRect_Type)))
-    , fGSampler1DArray_Type(new Type(String("$gsampler1DArray"),
+    , fGSampler1D_Type(new Type("$gsampler1D", static_type(*fSampler1D_Type)))
+    , fGSampler2D_Type(new Type("$gsampler2D", static_type(*fSampler2D_Type)))
+    , fGSampler3D_Type(new Type("$gsampler3D", static_type(*fSampler3D_Type)))
+    , fGSamplerCube_Type(new Type("$gsamplerCube", static_type(*fSamplerCube_Type)))
+    , fGSampler2DRect_Type(new Type("$gsampler2DRect", static_type(*fSampler2DRect_Type)))
+    , fGSampler1DArray_Type(new Type("$gsampler1DArray",
                                      static_type(*fSampler1DArray_Type)))
-    , fGSampler2DArray_Type(new Type(String("$gsampler2DArray"),
+    , fGSampler2DArray_Type(new Type("$gsampler2DArray",
                                      static_type(*fSampler2DArray_Type)))
-    , fGSamplerCubeArray_Type(new Type(String("$gsamplerCubeArray"),
+    , fGSamplerCubeArray_Type(new Type("$gsamplerCubeArray",
                                        static_type(*fSamplerCubeArray_Type)))
-    , fGSamplerBuffer_Type(new Type(String("$gsamplerBuffer"), static_type(*fSamplerBuffer_Type)))
-    , fGSampler2DMS_Type(new Type(String("$gsampler2DMS"), static_type(*fSampler2DMS_Type)))
-    , fGSampler2DMSArray_Type(new Type(String("$gsampler2DMSArray"),
+    , fGSamplerBuffer_Type(new Type("$gsamplerBuffer", static_type(*fSamplerBuffer_Type)))
+    , fGSampler2DMS_Type(new Type("$gsampler2DMS", static_type(*fSampler2DMS_Type)))
+    , fGSampler2DMSArray_Type(new Type("$gsampler2DMSArray",
                                        static_type(*fSampler2DMSArray_Type)))
-    , fGSampler2DArrayShadow_Type(new Type(String("$gsampler2DArrayShadow"),
+    , fGSampler2DArrayShadow_Type(new Type("$gsampler2DArrayShadow",
                                            static_type(*fSampler2DArrayShadow_Type)))
-    , fGSamplerCubeArrayShadow_Type(new Type(String("$gsamplerCubeArrayShadow"),
+    , fGSamplerCubeArrayShadow_Type(new Type("$gsamplerCubeArrayShadow",
                                              static_type(*fSamplerCubeArrayShadow_Type)))
-    , fGenType_Type(new Type(String("$genType"), { fFloat_Type.get(), fFloat2_Type.get(),
-                                                   fFloat3_Type.get(), fFloat4_Type.get() }))
-    , fGenHType_Type(new Type(String("$genHType"), { fHalf_Type.get(), fHalf2_Type.get(),
-                                                     fHalf3_Type.get(), fHalf4_Type.get() }))
-    , fGenDType_Type(new Type(String("$genDType"), { fDouble_Type.get(), fDouble2_Type.get(),
-                                                     fDouble3_Type.get(), fDouble4_Type.get() }))
-    , fGenIType_Type(new Type(String("$genIType"), { fInt_Type.get(), fInt2_Type.get(),
-                                                     fInt3_Type.get(), fInt4_Type.get() }))
-    , fGenUType_Type(new Type(String("$genUType"), { fUInt_Type.get(), fUInt2_Type.get(),
-                                                     fUInt3_Type.get(), fUInt4_Type.get() }))
-    , fGenBType_Type(new Type(String("$genBType"), { fBool_Type.get(), fBool2_Type.get(),
-                                                     fBool3_Type.get(), fBool4_Type.get() }))
-    , fMat_Type(new Type(String("$mat"), { fFloat2x2_Type.get(),  fFloat2x3_Type.get(),
-                                           fFloat2x4_Type.get(),  fFloat3x2_Type.get(),
-                                           fFloat3x3_Type.get(),  fFloat3x4_Type.get(),
-                                           fFloat4x2_Type.get(),  fFloat4x3_Type.get(),
-                                           fFloat4x4_Type.get(),  fHalf2x2_Type.get(),
-                                           fHalf2x3_Type.get(),   fHalf2x4_Type.get(),
-                                           fHalf3x2_Type.get(),   fHalf3x3_Type.get(),
-                                           fHalf3x4_Type.get(),   fHalf4x2_Type.get(),
-                                           fHalf4x3_Type.get(),   fHalf4x4_Type.get(),
-                                           fDouble2x2_Type.get(), fDouble2x3_Type.get(),
-                                           fDouble2x4_Type.get(), fDouble3x2_Type.get(),
-                                           fDouble3x3_Type.get(), fDouble3x4_Type.get(),
-                                           fDouble4x2_Type.get(), fDouble4x3_Type.get(),
-                                           fDouble4x4_Type.get() }))
-    , fVec_Type(new Type(String("$vec"), { fInvalid_Type.get(), fFloat2_Type.get(),
+    , fGenType_Type(new Type("$genType", { fFloat_Type.get(), fFloat2_Type.get(),
                                            fFloat3_Type.get(), fFloat4_Type.get() }))
-    , fGVec_Type(new Type(String("$gvec")))
-    , fGVec2_Type(new Type(String("$gfloat2")))
-    , fGVec3_Type(new Type(String("$gfloat3")))
-    , fGVec4_Type(new Type(String("$gfloat4"), static_type(*fFloat4_Type)))
-    , fHVec_Type(new Type(String("$hvec"), { fInvalid_Type.get(), fHalf2_Type.get(),
+    , fGenHType_Type(new Type("$genHType", { fHalf_Type.get(), fHalf2_Type.get(),
                                              fHalf3_Type.get(), fHalf4_Type.get() }))
-    , fDVec_Type(new Type(String("$dvec"), { fInvalid_Type.get(), fDouble2_Type.get(),
+    , fGenDType_Type(new Type("$genDType", { fDouble_Type.get(), fDouble2_Type.get(),
                                              fDouble3_Type.get(), fDouble4_Type.get() }))
-    , fIVec_Type(new Type(String("$ivec"), { fInvalid_Type.get(), fInt2_Type.get(),
+    , fGenIType_Type(new Type("$genIType", { fInt_Type.get(), fInt2_Type.get(),
                                              fInt3_Type.get(), fInt4_Type.get() }))
-    , fUVec_Type(new Type(String("$uvec"), { fInvalid_Type.get(), fUInt2_Type.get(),
+    , fGenUType_Type(new Type("$genUType", { fUInt_Type.get(), fUInt2_Type.get(),
                                              fUInt3_Type.get(), fUInt4_Type.get() }))
-    , fSVec_Type(new Type(String("$svec"), { fInvalid_Type.get(), fShort2_Type.get(),
-                                             fShort3_Type.get(), fShort4_Type.get() }))
-    , fUSVec_Type(new Type(String("$usvec"), { fInvalid_Type.get(), fUShort2_Type.get(),
-                                               fUShort3_Type.get(), fUShort4_Type.get() }))
-    , fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBool2_Type.get(),
+    , fGenBType_Type(new Type("$genBType", { fBool_Type.get(), fBool2_Type.get(),
                                              fBool3_Type.get(), fBool4_Type.get() }))
-    , fSkCaps_Type(new Type(String("$sk_Caps")))
-    , fSkArgs_Type(new Type(String("$sk_Args")))
-    , fColorSpaceXform_Type(new Type(String("colorSpaceXform"), *fFloat_Type, 4, 4))
+    , fMat_Type(new Type("$mat", { fFloat2x2_Type.get(),  fFloat2x3_Type.get(),
+                                   fFloat2x4_Type.get(),  fFloat3x2_Type.get(),
+                                   fFloat3x3_Type.get(),  fFloat3x4_Type.get(),
+                                   fFloat4x2_Type.get(),  fFloat4x3_Type.get(),
+                                   fFloat4x4_Type.get(),  fHalf2x2_Type.get(),
+                                   fHalf2x3_Type.get(),   fHalf2x4_Type.get(),
+                                   fHalf3x2_Type.get(),   fHalf3x3_Type.get(),
+                                   fHalf3x4_Type.get(),   fHalf4x2_Type.get(),
+                                   fHalf4x3_Type.get(),   fHalf4x4_Type.get(),
+                                   fDouble2x2_Type.get(), fDouble2x3_Type.get(),
+                                   fDouble2x4_Type.get(), fDouble3x2_Type.get(),
+                                   fDouble3x3_Type.get(), fDouble3x4_Type.get(),
+                                   fDouble4x2_Type.get(), fDouble4x3_Type.get(),
+                                   fDouble4x4_Type.get() }))
+    , fVec_Type(new Type("$vec", { fInvalid_Type.get(), fFloat2_Type.get(),
+                                           fFloat3_Type.get(), fFloat4_Type.get() }))
+    , fGVec_Type(new Type("$gvec"))
+    , fGVec2_Type(new Type("$gfloat2"))
+    , fGVec3_Type(new Type("$gfloat3"))
+    , fGVec4_Type(new Type("$gfloat4", static_type(*fFloat4_Type)))
+    , fHVec_Type(new Type("$hvec", { fInvalid_Type.get(), fHalf2_Type.get(),
+                                     fHalf3_Type.get(), fHalf4_Type.get() }))
+    , fDVec_Type(new Type("$dvec", { fInvalid_Type.get(), fDouble2_Type.get(),
+                                     fDouble3_Type.get(), fDouble4_Type.get() }))
+    , fIVec_Type(new Type("$ivec", { fInvalid_Type.get(), fInt2_Type.get(),
+                                     fInt3_Type.get(), fInt4_Type.get() }))
+    , fUVec_Type(new Type("$uvec", { fInvalid_Type.get(), fUInt2_Type.get(),
+                                     fUInt3_Type.get(), fUInt4_Type.get() }))
+    , fSVec_Type(new Type("$svec", { fInvalid_Type.get(), fShort2_Type.get(),
+                                     fShort3_Type.get(), fShort4_Type.get() }))
+    , fUSVec_Type(new Type("$usvec", { fInvalid_Type.get(), fUShort2_Type.get(),
+                                       fUShort3_Type.get(), fUShort4_Type.get() }))
+    , fBVec_Type(new Type("$bvec", { fInvalid_Type.get(), fBool2_Type.get(),
+                                     fBool3_Type.get(), fBool4_Type.get() }))
+    , fSkCaps_Type(new Type("$sk_Caps"))
+    , fSkArgs_Type(new Type("$sk_Args"))
+    , fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4))
     , fDefined_Expression(new Defined(*fInvalid_Type)) {}
 
     static std::vector<const Type*> static_type(const Type& t) {
@@ -343,14 +343,14 @@
     class Defined : public Expression {
     public:
         Defined(const Type& type)
-        : INHERITED(Position(), kDefined_Kind, type) {}
+        : INHERITED(-1, kDefined_Kind, type) {}
 
         bool hasSideEffects() const override {
             return false;
         }
 
         String description() const override {
-            return String("<defined>");
+            return "<defined>";
         }
 
         typedef Expression INHERITED;
diff --git a/src/sksl/SkSLErrorReporter.h b/src/sksl/SkSLErrorReporter.h
index 172e488..303a0e1 100644
--- a/src/sksl/SkSLErrorReporter.h
+++ b/src/sksl/SkSLErrorReporter.h
@@ -19,11 +19,11 @@
 public:
     virtual ~ErrorReporter() {}
 
-    void error(Position position, const char* msg) {
-        this->error(position, String(msg));
+    void error(int offset, const char* msg) {
+        this->error(offset, String(msg));
     }
 
-    virtual void error(Position position, String msg) = 0;
+    virtual void error(int offset, String msg) = 0;
 
     virtual int errorCount() = 0;
 };
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 64527a0..52a40f8 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -42,6 +42,19 @@
     this->write(s.c_str());
 }
 
+void GLSLCodeGenerator::write(StringFragment s) {
+    if (!s.fLength) {
+        return;
+    }
+    if (fAtLineStart) {
+        for (int i = 0; i < fIndentation; i++) {
+            fOut->writeText("    ");
+        }
+    }
+    fOut->write(s.fChars, s.fLength);
+    fAtLineStart = false;
+}
+
 void GLSLCodeGenerator::writeLine(const String& s) {
     this->writeLine(s.c_str());
 }
@@ -51,7 +64,9 @@
 }
 
 void GLSLCodeGenerator::writeExtension(const Extension& ext) {
-    this->writeLine("#extension " + ext.fName + " : enable");
+    this->write("#extension ");
+    this->write(ext.fName);
+    this->writeLine(" : enable");
 }
 
 void GLSLCodeGenerator::writeType(const Type& type) {
@@ -59,19 +74,23 @@
         for (const Type* search : fWrittenStructs) {
             if (*search == type) {
                 // already written
-                this->write(type.name());
+                this->write(type.fName);
                 return;
             }
         }
         fWrittenStructs.push_back(&type);
-        this->writeLine("struct " + type.name() + " {");
+        this->write("struct ");
+        this->write(type.fName);
+        this->writeLine(" {");
         fIndentation++;
         for (const auto& f : type.fields()) {
             this->writeModifiers(f.fModifiers, false);
             this->writeTypePrecision(*f.fType);
             // sizes (which must be static in structs) are part of the type name here
             this->writeType(*f.fType);
-            this->writeLine(" " + f.fName + ";");
+            this->write(" ");
+            this->write(f.fName);
+            this->writeLine(";");
         }
         fIndentation--;
         this->write("}");
@@ -138,12 +157,12 @@
                     this->write("uint");
                 }
                 else {
-                    this->write(type.name());
+                    this->write(type.fName);
                 }
                 break;
             }
             default:
-                this->write(type.name());
+                this->write(type.fName);
         }
     }
 }
@@ -210,8 +229,8 @@
     ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
     String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
     String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
-    this->fFunctionHeader += "    " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
-    this->fFunctionHeader += "    " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
+    this->fFunctionHeader += String("    ") + absExpr.fType.fName + " " + tmpVar1 + ";\n";
+    this->fFunctionHeader += String("    ") + otherExpr.fType.fName + " " + tmpVar2 + ";\n";
     this->write("((" + tmpVar1 + " = ");
     this->writeExpression(absExpr, kTopLevel_Precedence);
     this->write(") < (" + tmpVar2 + " = ");
@@ -503,7 +522,9 @@
         this->write("(");
     }
     this->writeExpression(*b.fLeft, precedence);
-    this->write(" " + Token::OperatorName(b.fOperator) + " ");
+    this->write(" ");
+    this->write(Compiler::OperatorName(b.fOperator));
+    this->write(" ");
     this->writeExpression(*b.fRight, precedence);
     if (precedence >= parentPrecedence) {
         this->write(")");
@@ -530,7 +551,7 @@
     if (kPrefix_Precedence >= parentPrecedence) {
         this->write("(");
     }
-    this->write(Token::OperatorName(p.fOperator));
+    this->write(Compiler::OperatorName(p.fOperator));
     this->writeExpression(*p.fOperand, kPrefix_Precedence);
     if (kPrefix_Precedence >= parentPrecedence) {
         this->write(")");
@@ -543,7 +564,7 @@
         this->write("(");
     }
     this->writeExpression(*p.fOperand, kPostfix_Precedence);
-    this->write(Token::OperatorName(p.fOperator));
+    this->write(Compiler::OperatorName(p.fOperator));
     if (kPostfix_Precedence >= parentPrecedence) {
         this->write(")");
     }
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index e10299a..353cd66 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -90,6 +90,8 @@
 
     void write(const String& s);
 
+    void write(StringFragment s);
+
     void writeLine(const String& s);
 
     virtual void writeHeader();
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 50d2428..482020a 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -23,17 +23,17 @@
 , fSectionAndParameterHelper(*program, *errors) {}
 
 String HCodeGenerator::ParameterType(const Type& type) {
-    if (type.fName == "float2") {
+    if (type.name() == "float2") {
         return "SkPoint";
-    } else if (type.fName == "int4") {
+    } else if (type.name() == "int4") {
         return "SkIRect";
-    } else if (type.fName == "float4") {
+    } else if (type.name() == "float4") {
         return "SkRect";
-    } else if (type.fName == "float4x4") {
+    } else if (type.name() == "float4x4") {
         return "SkMatrix44";
     } else if (type.kind() == Type::kSampler_Kind) {
         return "sk_sp<GrTextureProxy>";
-    } else if (type.fName == "colorSpaceXform") {
+    } else if (type.name() == "colorSpaceXform") {
         return "sk_sp<GrColorSpaceXform>";
     }
     return type.name();
@@ -127,7 +127,7 @@
         separator = "";
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
             this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
-                         param->fName.c_str());
+                         String(param->fName).c_str());
             separator = ", ";
         }
         this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
@@ -136,7 +136,7 @@
                      fFullName.c_str());
         separator = "";
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-            this->writef("%s%s", separator, param->fName.c_str());
+            this->writef("%s%s", separator, String(param->fName).c_str());
             separator = ", ";
         }
         this->writeExtraConstructorParams(separator);
@@ -148,7 +148,7 @@
 void HCodeGenerator::failOnSection(const char* section, const char* msg) {
     std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
     if (s.size()) {
-        fErrors.error(s[0]->fPosition, String("@") + section + " " + msg);
+        fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
     }
 }
 
@@ -165,7 +165,7 @@
     const char* separator = "";
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
         this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
-                     param->fName.c_str());
+                     String(param->fName).c_str());
         separator = ", ";
     }
     this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
@@ -177,7 +177,8 @@
     this->writef(")");
     this->writeSection(INITIALIZERS_SECTION, "\n    , ");
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        const char* name = param->fName.c_str();
+        String nameString(param->fName);
+        const char* name = nameString.c_str();
         if (param->fType.kind() == Type::kSampler_Kind) {
             this->writef("\n    , %s(std::move(%s)", FieldName(name).c_str(), name);
             for (const Section* s : fSectionAndParameterHelper.getSections(
@@ -201,7 +202,7 @@
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
         if (param->fType.kind() == Type::kSampler_Kind) {
             this->writef("        this->addTextureSampler(&%s);\n",
-                         FieldName(param->fName.c_str()).c_str());
+                         FieldName(String(param->fName).c_str()).c_str());
         }
     }
     for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
@@ -216,8 +217,8 @@
 void HCodeGenerator::writeFields() {
     this->writeSection(FIELDS_SECTION);
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        const char* name = param->fName.c_str();
-        this->writef("    %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str());
+        this->writef("    %s %s;\n", FieldType(param->fType).c_str(),
+                     FieldName(String(param->fName).c_str()).c_str());
     }
     for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
         this->writef("    GrCoordTransform %sCoordTransform;\n",
@@ -245,7 +246,8 @@
         if (param->fType.kind() == Type::kSampler_Kind) {
             continue;
         }
-        const char* name = param->fName.c_str();
+        String nameString(param->fName);
+        const char* name = nameString.c_str();
         this->writef("    %s %s() const { return %s; }\n",
                      FieldType(param->fType).c_str(), name, FieldName(name).c_str());
     }
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index a46a931..83ab993 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -162,7 +162,7 @@
 }
 
 std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
-    return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName));
+    return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName));
 }
 
 std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
@@ -206,7 +206,7 @@
         }
         statements.push_back(std::move(statement));
     }
-    return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable));
+    return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
 }
 
 std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
@@ -234,12 +234,12 @@
                 if (!size) {
                     return nullptr;
                 }
-                String name = type->fName;
+                String name(type->fName);
                 int64_t count;
                 if (size->fKind == Expression::kIntLiteral_Kind) {
                     count = ((IntLiteral&) *size).fValue;
                     if (count <= 0) {
-                        fErrors.error(size->fPosition, "array size must be positive");
+                        fErrors.error(size->fOffset, "array size must be positive");
                     }
                     name += "[" + to_string(count) + "]";
                 } else {
@@ -250,12 +250,12 @@
                 fSymbolTable->takeOwnership((Type*) type);
                 sizes.push_back(std::move(size));
             } else {
-                type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
+                type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
                 fSymbolTable->takeOwnership((Type*) type);
                 sizes.push_back(nullptr);
             }
         }
-        auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers,
+        auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
                                                           varDecl.fName, *type, storage));
         std::unique_ptr<Expression> value;
         if (varDecl.fValue) {
@@ -266,7 +266,7 @@
             value = this->coerce(std::move(value), *type);
             var->fWriteCount = 1;
         }
-        if (storage == Variable::kGlobal_Storage && varDecl.fName == String("sk_FragColor") &&
+        if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" &&
             (*fSymbolTable)[varDecl.fName]) {
             // already defined, ignore
         } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
@@ -281,7 +281,7 @@
             fSymbolTable->add(varDecl.fName, std::move(var));
         }
     }
-    return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
+    return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset,
                                                                 baseType,
                                                                 std::move(variables)));
 }
@@ -334,11 +334,11 @@
         } else {
             // False & no else clause. Not an error, so don't return null!
             std::vector<std::unique_ptr<Statement>> empty;
-            return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
+            return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty),
                                                         fSymbolTable));
         }
     }
-    return std::unique_ptr<Statement>(new IfStatement(s.fPosition, s.fIsStatic, std::move(test),
+    return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test),
                                                       std::move(ifTrue), std::move(ifFalse)));
 }
 
@@ -371,7 +371,7 @@
     if (!statement) {
         return nullptr;
     }
-    return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
+    return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer),
                                                        std::move(test), std::move(next),
                                                        std::move(statement), fSymbolTable));
 }
@@ -387,7 +387,7 @@
     if (!statement) {
         return nullptr;
     }
-    return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test),
+    return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test),
                                                          std::move(statement)));
 }
 
@@ -402,7 +402,7 @@
     if (!statement) {
         return nullptr;
     }
-    return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
+    return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
                                                       std::move(test)));
 }
 
@@ -435,13 +435,13 @@
                 }
             }
             if (!caseValue->isConstant()) {
-                fErrors.error(caseValue->fPosition, "case value must be a constant");
+                fErrors.error(caseValue->fOffset, "case value must be a constant");
                 return nullptr;
             }
             ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind);
             int64_t v = ((IntLiteral&) *caseValue).fValue;
             if (caseValues.find(v) != caseValues.end()) {
-                fErrors.error(caseValue->fPosition, "duplicate case value");
+                fErrors.error(caseValue->fOffset, "duplicate case value");
             }
             caseValues.insert(v);
         }
@@ -453,10 +453,10 @@
             }
             statements.push_back(std::move(converted));
         }
-        cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue),
+        cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue),
                                           std::move(statements)));
     }
-    return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, s.fIsStatic,
+    return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic,
                                                           std::move(value), std::move(cases),
                                                           fSymbolTable));
 }
@@ -479,7 +479,7 @@
             return nullptr;
         }
         if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
-            fErrors.error(result->fPosition, "may not return a value from a void function");
+            fErrors.error(result->fOffset, "may not return a value from a void function");
         } else {
             result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
             if (!result) {
@@ -489,45 +489,45 @@
         return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
     } else {
         if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
-            fErrors.error(r.fPosition, "expected function to return '" +
-                                       fCurrentFunction->fReturnType.description() + "'");
+            fErrors.error(r.fOffset, "expected function to return '" +
+                                     fCurrentFunction->fReturnType.description() + "'");
         }
-        return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
+        return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
     }
 }
 
 std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
     if (fLoopLevel > 0 || fSwitchLevel > 0) {
-        return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
+        return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
     } else {
-        fErrors.error(b.fPosition, "break statement must be inside a loop or switch");
+        fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
         return nullptr;
     }
 }
 
 std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
     if (fLoopLevel > 0) {
-        return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition));
+        return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
     } else {
-        fErrors.error(c.fPosition, "continue statement must be inside a loop");
+        fErrors.error(c.fOffset, "continue statement must be inside a loop");
         return nullptr;
     }
 }
 
 std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
-    return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
+    return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
 }
 
 std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main,
         std::vector<std::unique_ptr<ProgramElement>>* out) {
     Layout invokeLayout;
     Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
-    FunctionDeclaration* invokeDecl = new FunctionDeclaration(Position(),
+    FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
                                                               invokeModifiers,
                                                               "_invoke",
                                                               std::vector<const Variable*>(),
                                                               *fContext.fVoid_Type);
-    out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(Position(),
+    out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(-1,
                                                                           *invokeDecl,
                                                                           std::move(main))));
     fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
@@ -535,47 +535,47 @@
     std::vector<std::unique_ptr<VarDeclaration>> variables;
     Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
     ASSERT(loopIdx);
-    std::unique_ptr<Expression> test(new BinaryExpression(Position(),
-                    std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)),
+    std::unique_ptr<Expression> test(new BinaryExpression(-1,
+                    std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
                     Token::LT,
-                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), fInvocations)),
+                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)),
                     *fContext.fBool_Type));
     std::unique_ptr<Expression> next(new PostfixExpression(
                 std::unique_ptr<Expression>(
-                                      new VariableReference(Position(),
+                                      new VariableReference(-1,
                                                             *loopIdx,
                                                             VariableReference::kReadWrite_RefKind)),
                 Token::PLUSPLUS));
-    ASTIdentifier endPrimitiveID = ASTIdentifier(Position(), "EndPrimitive");
+    ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive");
     std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
     ASSERT(endPrimitive);
 
     std::vector<std::unique_ptr<Statement>> loopBody;
     std::vector<std::unique_ptr<Expression>> invokeArgs;
     loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
-                                          this->call(Position(),
+                                          this->call(-1,
                                                      *invokeDecl,
                                                      std::vector<std::unique_ptr<Expression>>()))));
     loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
-                                          this->call(Position(),
+                                          this->call(-1,
                                                      std::move(endPrimitive),
                                                      std::vector<std::unique_ptr<Expression>>()))));
-    std::unique_ptr<Expression> assignment(new BinaryExpression(Position(),
-                    std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)),
+    std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
+                    std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
                     Token::EQ,
-                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), 0)),
+                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)),
                     *fContext.fInt_Type));
     std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
     std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
-                new ForStatement(Position(),
+                new ForStatement(-1,
                                  std::move(initializer),
                                  std::move(test),
                                  std::move(next),
-                                 std::unique_ptr<Block>(new Block(Position(), std::move(loopBody))),
+                                 std::unique_ptr<Block>(new Block(-1, std::move(loopBody))),
                                  fSymbolTable));
     std::vector<std::unique_ptr<Statement>> children;
     children.push_back(std::move(loop));
-    return std::unique_ptr<Block>(new Block(Position(), std::move(children)));
+    return std::unique_ptr<Block>(new Block(-1, std::move(children)));
 }
 
 void IRGenerator::convertFunction(const ASTFunction& f,
@@ -597,9 +597,8 @@
             fSymbolTable->takeOwnership(newType);
             type = newType;
         }
-        String name = param->fName;
-        Position pos = param->fPosition;
-        Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type,
+        StringFragment name = param->fName;
+        Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type,
                                      Variable::kParameter_Storage);
         fSymbolTable->takeOwnership(var);
         parameters.push_back(var);
@@ -618,7 +617,7 @@
                 functions.push_back((FunctionDeclaration*) entry);
                 break;
             default:
-                fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
+                fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined");
                 return;
         }
         for (const auto& other : functions) {
@@ -633,26 +632,26 @@
                 }
                 if (match) {
                     if (*returnType != other->fReturnType) {
-                        FunctionDeclaration newDecl(f.fPosition, f.fModifiers, f.fName, parameters,
+                        FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters,
                                                     *returnType);
-                        fErrors.error(f.fPosition, "functions '" + newDecl.description() +
-                                                   "' and '" + other->description() +
-                                                   "' differ only in return type");
+                        fErrors.error(f.fOffset, "functions '" + newDecl.description() +
+                                                 "' and '" + other->description() +
+                                                 "' differ only in return type");
                         return;
                     }
                     decl = other;
                     for (size_t i = 0; i < parameters.size(); i++) {
                         if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
-                            fErrors.error(f.fPosition, "modifiers on parameter " +
-                                                       to_string((uint64_t) i + 1) +
-                                                       " differ between declaration and "
-                                                       "definition");
+                            fErrors.error(f.fOffset, "modifiers on parameter " +
+                                                     to_string((uint64_t) i + 1) +
+                                                     " differ between declaration and "
+                                                     "definition");
                             return;
                         }
                     }
                     if (other->fDefined) {
-                        fErrors.error(f.fPosition, "duplicate definition of " +
-                                                   other->description());
+                        fErrors.error(f.fOffset, "duplicate definition of " +
+                                                 other->description());
                     }
                     break;
                 }
@@ -661,7 +660,7 @@
     }
     if (!decl) {
         // couldn't find an existing declaration
-        auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition,
+        auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
                                                                                     f.fModifiers,
                                                                                     f.fName,
                                                                                     parameters,
@@ -698,7 +697,7 @@
         ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
 
         out->push_back(std::unique_ptr<FunctionDefinition>(
-                                      new FunctionDefinition(f.fPosition, *decl, std::move(body))));
+                                      new FunctionDefinition(f.fOffset, *decl, std::move(body))));
     }
 }
 
@@ -717,14 +716,14 @@
         for (const auto& stmt : decl->fVars) {
             VarDeclaration& vd = (VarDeclaration&) *stmt;
             if (haveRuntimeArray) {
-                fErrors.error(decl->fPosition,
+                fErrors.error(decl->fOffset,
                               "only the last entry in an interface block may be a runtime-sized "
                               "array");
             }
             fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
                                          &vd.fVar->fType));
             if (vd.fValue) {
-                fErrors.error(decl->fPosition,
+                fErrors.error(decl->fOffset,
                               "initializers are not permitted on interface block fields");
             }
             if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
@@ -732,7 +731,7 @@
                                                 Modifiers::kUniform_Flag |
                                                 Modifiers::kBuffer_Flag |
                                                 Modifiers::kConst_Flag)) {
-                fErrors.error(decl->fPosition,
+                fErrors.error(decl->fOffset,
                               "interface block fields may not have storage qualifiers");
             }
             if (vd.fVar->fType.kind() == Type::kArray_Kind &&
@@ -741,7 +740,7 @@
             }
         }
     }
-    Type* type = new Type(intf.fPosition, intf.fTypeName, fields);
+    Type* type = new Type(intf.fOffset, intf.fTypeName, fields);
     old->takeOwnership(type);
     std::vector<std::unique_ptr<Expression>> sizes;
     for (const auto& size : intf.fSizes) {
@@ -755,7 +754,7 @@
             if (converted->fKind == Expression::kIntLiteral_Kind) {
                 count = ((IntLiteral&) *converted).fValue;
                 if (count <= 0) {
-                    fErrors.error(converted->fPosition, "array size must be positive");
+                    fErrors.error(converted->fOffset, "array size must be positive");
                 }
                 name += "[" + to_string(count) + "]";
             } else {
@@ -766,24 +765,24 @@
             fSymbolTable->takeOwnership((Type*) type);
             sizes.push_back(std::move(converted));
         } else {
-            type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
+            type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
             fSymbolTable->takeOwnership((Type*) type);
             sizes.push_back(nullptr);
         }
     }
-    Variable* var = new Variable(intf.fPosition, intf.fModifiers,
-                                 intf.fInstanceName.size() ? intf.fInstanceName : intf.fTypeName,
+    Variable* var = new Variable(intf.fOffset, intf.fModifiers,
+                                 intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
                                  *type, Variable::kGlobal_Storage);
     old->takeOwnership(var);
-    if (intf.fInstanceName.size()) {
+    if (intf.fInstanceName.fLength) {
         old->addWithoutOwnership(intf.fInstanceName, var);
     } else {
         for (size_t i = 0; i < fields.size(); i++) {
-            old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
+            old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
                                                                        (int) i)));
         }
     }
-    return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition,
+    return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
                                                               var,
                                                               intf.fTypeName,
                                                               intf.fInstanceName,
@@ -795,7 +794,8 @@
     const Symbol* result = (*fSymbolTable)[type.fName];
     if (result && result->fKind == Symbol::kType_Kind) {
         for (int size : type.fSizes) {
-            String name = result->fName + "[";
+            String name(result->fName);
+            name += "[";
             if (size != -1) {
                 name += to_string(size);
             }
@@ -805,7 +805,7 @@
         }
         return (const Type*) result;
     }
-    fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
+    fErrors.error(type.fOffset, "unknown type '" + type.fName + "'");
     return nullptr;
 }
 
@@ -814,13 +814,13 @@
         case ASTExpression::kIdentifier_Kind:
             return this->convertIdentifier((ASTIdentifier&) expr);
         case ASTExpression::kBool_Kind:
-            return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition,
+            return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
                                                                ((ASTBoolLiteral&) expr).fValue));
         case ASTExpression::kInt_Kind:
-            return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition,
+            return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
                                                               ((ASTIntLiteral&) expr).fValue));
         case ASTExpression::kFloat_Kind:
-            return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition,
+            return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
                                                                 ((ASTFloatLiteral&) expr).fValue));
         case ASTExpression::kBinary_Kind:
             return this->convertBinaryExpression((ASTBinaryExpression&) expr);
@@ -838,7 +838,7 @@
 std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
     const Symbol* result = (*fSymbolTable)[identifier.fText];
     if (!result) {
-        fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'");
+        fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'");
         return nullptr;
     }
     switch (result->fKind) {
@@ -847,13 +847,13 @@
                 (const FunctionDeclaration*) result
             };
             return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
-                                                                            identifier.fPosition,
+                                                                            identifier.fOffset,
                                                                             f));
         }
         case Symbol::kUnresolvedFunction_Kind: {
             const UnresolvedFunction* f = (const UnresolvedFunction*) result;
             return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
-                                                                            identifier.fPosition,
+                                                                            identifier.fOffset,
                                                                             f->fFunctions));
         }
         case Symbol::kVariable_Kind: {
@@ -870,13 +870,13 @@
 #endif
             // default to kRead_RefKind; this will be corrected later if the variable is written to
             return std::unique_ptr<VariableReference>(new VariableReference(
-                                                                 identifier.fPosition,
+                                                                 identifier.fOffset,
                                                                  *var,
                                                                  VariableReference::kRead_RefKind));
         }
         case Symbol::kField_Kind: {
             const Field* field = (const Field*) result;
-            VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner,
+            VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
                                                             VariableReference::kRead_RefKind);
             return std::unique_ptr<Expression>(new FieldAccess(
                                                   std::unique_ptr<Expression>(base),
@@ -885,7 +885,7 @@
         }
         case Symbol::kType_Kind: {
             const Type* t = (const Type*) result;
-            return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
+            return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset,
                                                                     *t));
         }
         default:
@@ -894,7 +894,7 @@
 }
 
 std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
-    return std::unique_ptr<Section>(new Section(s.fPosition, s.fName, s.fArgument, s.fText));
+    return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText));
 }
 
 
@@ -911,24 +911,24 @@
         return nullptr;
     }
     if (expr->coercionCost(type) == INT_MAX) {
-        fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
+        fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
                                         expr->fType.description() + "'");
         return nullptr;
     }
     if (type.kind() == Type::kScalar_Kind) {
         std::vector<std::unique_ptr<Expression>> args;
         args.push_back(std::move(expr));
-        ASTIdentifier id(Position(), type.description());
+        ASTIdentifier id(-1, type.fName);
         std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
         ASSERT(ctor);
-        return this->call(Position(), std::move(ctor), std::move(args));
+        return this->call(-1, std::move(ctor), std::move(args));
     }
     if (type == *fContext.fColorSpaceXform_Type && expr->fType == *fContext.fFloat4x4_Type) {
         return expr;
     }
     std::vector<std::unique_ptr<Expression>> args;
     args.push_back(std::move(expr));
-    return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
+    return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
 }
 
 static bool is_matrix_multiply(const Type& left, const Type& right) {
@@ -1094,9 +1094,9 @@
             case Token::LOGICALXOR: result = leftVal ^  rightVal; break;
             default: return nullptr;
         }
-        return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosition, result));
+        return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
     }
-    #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \
+    #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \
                                                                        leftVal op rightVal))
     if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
         int64_t leftVal  = ((IntLiteral&) left).fValue;
@@ -1109,13 +1109,13 @@
                 if (rightVal) {
                     return RESULT(Int, /);
                 }
-                fErrors.error(right.fPosition, "division by zero");
+                fErrors.error(right.fOffset, "division by zero");
                 return nullptr;
             case Token::PERCENT:
                 if (rightVal) {
                     return RESULT(Int, %);
                 }
-                fErrors.error(right.fPosition, "division by zero");
+                fErrors.error(right.fOffset, "division by zero");
                 return nullptr;
             case Token::BITWISEAND: return RESULT(Int,  &);
             case Token::BITWISEOR:  return RESULT(Int,  |);
@@ -1143,7 +1143,7 @@
                 if (rightVal) {
                     return RESULT(Float, /);
                 }
-                fErrors.error(right.fPosition, "division by zero");
+                fErrors.error(right.fOffset, "division by zero");
                 return nullptr;
             case Token::EQEQ:       return RESULT(Bool, ==);
             case Token::NEQ:        return RESULT(Bool, !=);
@@ -1164,16 +1164,16 @@
             for (int i = 0; i < left.fType.columns(); i++) {                           \
                 float value = ((Constructor&) left).getFVecComponent(i) op             \
                               ((Constructor&) right).getFVecComponent(i);              \
-                args.emplace_back(new FloatLiteral(fContext, Position(), value));      \
+                args.emplace_back(new FloatLiteral(fContext, -1, value));              \
             }                                                                          \
-            return std::unique_ptr<Expression>(new Constructor(Position(), left.fType, \
+            return std::unique_ptr<Expression>(new Constructor(-1, left.fType,         \
                                                                std::move(args)));
         switch (op) {
             case Token::EQEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(),
+                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
                                                             left.compareConstant(fContext, right)));
             case Token::NEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(),
+                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
                                                            !left.compareConstant(fContext, right)));
             case Token::PLUS:  RETURN_VEC_COMPONENTWISE_RESULT(+);
             case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
@@ -1187,10 +1187,10 @@
         left.fKind == right.fKind) {
         switch (op) {
             case Token::EQEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(),
+                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
                                                             left.compareConstant(fContext, right)));
             case Token::NEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(),
+                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
                                                            !left.compareConstant(fContext, right)));
             default:
                 return nullptr;
@@ -1227,14 +1227,14 @@
     }
     if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
                                &leftType, &rightType, &resultType,
-                               !Token::IsAssignment(expression.fOperator))) {
-        fErrors.error(expression.fPosition, "type mismatch: '" +
-                                            Token::OperatorName(expression.fOperator) +
-                                            "' cannot operate on '" + left->fType.fName +
-                                            "', '" + right->fType.fName + "'");
+                               !Compiler::IsAssignment(expression.fOperator))) {
+        fErrors.error(expression.fOffset, String("type mismatch: '") +
+                                          Compiler::OperatorName(expression.fOperator) +
+                                          "' cannot operate on '" + left->fType.fName +
+                                          "', '" + right->fType.fName + "'");
         return nullptr;
     }
-    if (Token::IsAssignment(expression.fOperator)) {
+    if (Compiler::IsAssignment(expression.fOperator)) {
         this->markWrittenTo(*left, expression.fOperator != Token::EQ);
     }
     left = this->coerce(std::move(left), *leftType);
@@ -1245,7 +1245,7 @@
     std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
                                                             *right.get());
     if (!result) {
-        result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
+        result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
                                                                   std::move(left),
                                                                   expression.fOperator,
                                                                   std::move(right),
@@ -1274,9 +1274,9 @@
     const Type* resultType;
     if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
                                &falseType, &resultType, true) || trueType != falseType) {
-        fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
-                                            ifTrue->fType.fName + "', '" +
-                                            ifFalse->fType.fName + "'");
+        fErrors.error(expression.fOffset, "ternary operator result mismatch: '" +
+                                          ifTrue->fType.fName + "', '" +
+                                          ifFalse->fType.fName + "'");
         return nullptr;
     }
     ifTrue = this->coerce(std::move(ifTrue), *trueType);
@@ -1295,7 +1295,7 @@
             return ifFalse;
         }
     }
-    return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
+    return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset,
                                                              std::move(test),
                                                              std::move(ifTrue),
                                                              std::move(ifFalse)));
@@ -1315,8 +1315,8 @@
     ASSERT(textureSizeSymbol->fKind == Symbol::kFunctionDeclaration_Kind);
     const FunctionDeclaration& textureSize = (FunctionDeclaration&) *textureSizeSymbol;
     std::vector<std::unique_ptr<Expression>> sizeArguments;
-    sizeArguments.emplace_back(new VariableReference(Position(), sampler));
-    std::unique_ptr<Expression> float2ize = call(Position(), textureSize, std::move(sizeArguments));
+    sizeArguments.emplace_back(new VariableReference(-1, sampler));
+    std::unique_ptr<Expression> float2ize = call(-1, textureSize, std::move(sizeArguments));
     const Type& type = arguments[1]->fType;
     std::unique_ptr<Expression> scale;
     if (type == *fContext.fFloat2_Type) {
@@ -1325,14 +1325,14 @@
         ASSERT(type == *fContext.fFloat3_Type);
         std::vector<std::unique_ptr<Expression>> float3rguments;
         float3rguments.push_back(std::move(float2ize));
-        float3rguments.emplace_back(new FloatLiteral(fContext, Position(), 1.0));
-        scale.reset(new Constructor(Position(), *fContext.fFloat3_Type, std::move(float3rguments)));
+        float3rguments.emplace_back(new FloatLiteral(fContext, -1, 1.0));
+        scale.reset(new Constructor(-1, *fContext.fFloat3_Type, std::move(float3rguments)));
     }
-    arguments[1].reset(new BinaryExpression(Position(), std::move(scale), Token::STAR,
+    arguments[1].reset(new BinaryExpression(-1, std::move(scale), Token::STAR,
                                             std::move(arguments[1]), type));
 }
 
-std::unique_ptr<Expression> IRGenerator::call(Position position,
+std::unique_ptr<Expression> IRGenerator::call(int offset,
                                               const FunctionDeclaration& function,
                                               std::vector<std::unique_ptr<Expression>> arguments) {
     if (function.fParameters.size() != arguments.size()) {
@@ -1343,7 +1343,7 @@
             msg += "s";
         }
         msg += ", but found " + to_string((uint64_t) arguments.size());
-        fErrors.error(position, msg);
+        fErrors.error(offset, msg);
         return nullptr;
     }
     std::vector<const Type*> types;
@@ -1357,7 +1357,7 @@
             msg += arguments[i]->fType.description();
         }
         msg += ")";
-        fErrors.error(position, msg);
+        fErrors.error(offset, msg);
         return nullptr;
     }
     for (size_t i = 0; i < arguments.size(); i++) {
@@ -1374,7 +1374,7 @@
         arguments[0]->fType == *fContext.fSampler2DRect_Type) {
         this->fixRectSampling(arguments);
     }
-    return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function,
+    return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
                                                           std::move(arguments)));
 }
 
@@ -1409,26 +1409,26 @@
                                                          std::unique_ptr<Expression> xform) {
     // Before: texture(img, coords, xform);
     // After: COLORSPACE(texture(img, coords), xform)
-    Position p = texture->fPosition;
+    int offset = texture->fOffset;
     std::vector<std::unique_ptr<Expression>> args;
     args.push_back(std::move(texture));
     args.push_back(std::move(xform));
     const Symbol* colorspaceSymbol = (*fSymbolTable)["COLORSPACE"];
     ASSERT(colorspaceSymbol->fKind == Symbol::kFunctionDeclaration_Kind);
     const FunctionDeclaration& colorspaceFunction = (FunctionDeclaration&) *colorspaceSymbol;
-    return this->call(p, colorspaceFunction, std::move(args));
+    return this->call(offset, colorspaceFunction, std::move(args));
 }
 
-std::unique_ptr<Expression> IRGenerator::call(Position position,
+std::unique_ptr<Expression> IRGenerator::call(int offset,
                                               std::unique_ptr<Expression> functionValue,
                                               std::vector<std::unique_ptr<Expression>> arguments) {
     if (functionValue->fKind == Expression::kTypeReference_Kind) {
-        return this->convertConstructor(position,
+        return this->convertConstructor(offset,
                                         ((TypeReference&) *functionValue).fValue,
                                         std::move(arguments));
     }
     if (functionValue->fKind != Expression::kFunctionReference_Kind) {
-        fErrors.error(position, "'" + functionValue->description() + "' is not a function");
+        fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
         return nullptr;
     }
     FunctionReference* ref = (FunctionReference*) functionValue.get();
@@ -1436,7 +1436,7 @@
         arguments.back()->fType == *fContext.fColorSpaceXform_Type) {
         std::unique_ptr<Expression> colorspace = std::move(arguments.back());
         arguments.pop_back();
-        return this->applyColorSpace(this->call(position,
+        return this->applyColorSpace(this->call(offset,
                                                 std::move(functionValue),
                                                 std::move(arguments)),
                                      std::move(colorspace));
@@ -1453,7 +1453,7 @@
             }
         }
         if (best) {
-            return this->call(position, *best, std::move(arguments));
+            return this->call(offset, *best, std::move(arguments));
         }
         String msg = "no match for " + ref->fFunctions[0]->fName + "(";
         String separator;
@@ -1463,21 +1463,21 @@
             msg += arguments[i]->fType.description();
         }
         msg += ")";
-        fErrors.error(position, msg);
+        fErrors.error(offset, msg);
         return nullptr;
     }
-    return this->call(position, *ref->fFunctions[0], std::move(arguments));
+    return this->call(offset, *ref->fFunctions[0], std::move(arguments));
 }
 
 std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
-                                                    Position position,
+                                                    int offset,
                                                     const Type& type,
                                                     std::vector<std::unique_ptr<Expression>> args) {
     ASSERT(type.isNumber());
     if (args.size() != 1) {
-        fErrors.error(position, "invalid arguments to '" + type.description() +
-                                "' constructor, (expected exactly 1 argument, but found " +
-                                to_string((uint64_t) args.size()) + ")");
+        fErrors.error(offset, "invalid arguments to '" + type.description() +
+                              "' constructor, (expected exactly 1 argument, but found " +
+                              to_string((uint64_t) args.size()) + ")");
         return nullptr;
     }
     if (type.isFloat() && args[0]->fType.isFloat()) {
@@ -1491,31 +1491,31 @@
     }
     if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
         int64_t value = ((IntLiteral&) *args[0]).fValue;
-        return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
+        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, (double) value));
     }
     if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
         type == *fContext.fUInt_Type)) {
         return std::unique_ptr<Expression>(new IntLiteral(fContext,
-                                                          position,
+                                                          offset,
                                                           ((IntLiteral&) *args[0]).fValue,
                                                           &type));
     }
     if (args[0]->fType == *fContext.fBool_Type) {
-        std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
-        std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1));
+        std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
+        std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
         return std::unique_ptr<Expression>(
-                                     new TernaryExpression(position, std::move(args[0]),
+                                     new TernaryExpression(offset, std::move(args[0]),
                                                            this->coerce(std::move(one), type),
                                                            this->coerce(std::move(zero),
                                                                         type)));
     }
     if (!args[0]->fType.isNumber()) {
-        fErrors.error(position, "invalid argument to '" + type.description() +
-                                "' constructor (expected a number or bool, but found '" +
-                                args[0]->fType.description() + "')");
+        fErrors.error(offset, "invalid argument to '" + type.description() +
+                              "' constructor (expected a number or bool, but found '" +
+                              args[0]->fType.description() + "')");
         return nullptr;
     }
-    return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
+    return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
 }
 
 int component_count(const Type& type) {
@@ -1530,14 +1530,14 @@
 }
 
 std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
-                                                    Position position,
+                                                    int offset,
                                                     const Type& type,
                                                     std::vector<std::unique_ptr<Expression>> args) {
     ASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
     if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
         args[0]->fType.kind() == Type::kMatrix_Kind) {
         // matrix from matrix is always legal
-        return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
+        return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
     }
     int actual = 0;
     int expected = type.rows() * type.columns();
@@ -1547,9 +1547,9 @@
             if (args[i]->fType.kind() == Type::kVector_Kind) {
                 if (type.componentType().isNumber() !=
                     args[i]->fType.componentType().isNumber()) {
-                    fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
-                                            "parameter to '" + type.description() +
-                                            "' constructor");
+                    fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
+                                          "parameter to '" + type.description() +
+                                          "' constructor");
                     return nullptr;
                 }
                 actual += args[i]->fType.columns();
@@ -1562,23 +1562,23 @@
                     }
                 }
             } else {
-                fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
-                                        "parameter to '" + type.description() + "' constructor");
+                fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
+                                      "parameter to '" + type.description() + "' constructor");
                 return nullptr;
             }
         }
         if (actual != 1 && actual != expected) {
-            fErrors.error(position, "invalid arguments to '" + type.description() +
-                                    "' constructor (expected " + to_string(expected) +
-                                    " scalars, but found " + to_string(actual) + ")");
+            fErrors.error(offset, "invalid arguments to '" + type.description() +
+                                  "' constructor (expected " + to_string(expected) +
+                                  " scalars, but found " + to_string(actual) + ")");
             return nullptr;
         }
     }
-    return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
+    return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
 }
 
 std::unique_ptr<Expression> IRGenerator::convertConstructor(
-                                                    Position position,
+                                                    int offset,
                                                     const Type& type,
                                                     std::vector<std::unique_ptr<Expression>> args) {
     // FIXME: add support for structs
@@ -1588,7 +1588,7 @@
         return std::move(args[0]);
     }
     if (type.isNumber()) {
-        return this->convertNumberConstructor(position, type, std::move(args));
+        return this->convertNumberConstructor(offset, type, std::move(args));
     } else if (kind == Type::kArray_Kind) {
         const Type& base = type.componentType();
         for (size_t i = 0; i < args.size(); i++) {
@@ -1597,11 +1597,11 @@
                 return nullptr;
             }
         }
-        return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args)));
+        return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
     } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
-        return this->convertCompoundConstructor(position, type, std::move(args));
+        return this->convertCompoundConstructor(offset, type, std::move(args));
     } else {
-        fErrors.error(position, "cannot construct '" + type.description() + "'");
+        fErrors.error(offset, "cannot construct '" + type.description() + "'");
         return nullptr;
     }
 }
@@ -1615,31 +1615,31 @@
     switch (expression.fOperator) {
         case Token::PLUS:
             if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
-                fErrors.error(expression.fPosition,
+                fErrors.error(expression.fOffset,
                               "'+' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
             return base;
         case Token::MINUS:
             if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
-                fErrors.error(expression.fPosition,
+                fErrors.error(expression.fOffset,
                               "'-' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
             if (base->fKind == Expression::kIntLiteral_Kind) {
-                return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition,
+                return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
                                                                   -((IntLiteral&) *base).fValue));
             }
             if (base->fKind == Expression::kFloatLiteral_Kind) {
                 double value = -((FloatLiteral&) *base).fValue;
-                return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
+                return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
                                                                     value));
             }
             return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
         case Token::PLUSPLUS:
             if (!base->fType.isNumber()) {
-                fErrors.error(expression.fPosition,
-                              "'" + Token::OperatorName(expression.fOperator) +
+                fErrors.error(expression.fOffset,
+                              String("'") + Compiler::OperatorName(expression.fOperator) +
                               "' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
@@ -1647,8 +1647,8 @@
             break;
         case Token::MINUSMINUS:
             if (!base->fType.isNumber()) {
-                fErrors.error(expression.fPosition,
-                              "'" + Token::OperatorName(expression.fOperator) +
+                fErrors.error(expression.fOffset,
+                              String("'") + Compiler::OperatorName(expression.fOperator) +
                               "' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
@@ -1656,20 +1656,20 @@
             break;
         case Token::LOGICALNOT:
             if (base->fType != *fContext.fBool_Type) {
-                fErrors.error(expression.fPosition,
-                              "'" + Token::OperatorName(expression.fOperator) +
+                fErrors.error(expression.fOffset,
+                              String("'") + Compiler::OperatorName(expression.fOperator) +
                               "' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
             if (base->fKind == Expression::kBoolLiteral_Kind) {
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fPosition,
+                return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
                                                                    !((BoolLiteral&) *base).fValue));
             }
             break;
         case Token::BITWISENOT:
             if (base->fType != *fContext.fInt_Type) {
-                fErrors.error(expression.fPosition,
-                              "'" + Token::OperatorName(expression.fOperator) +
+                fErrors.error(expression.fOffset,
+                              String("'") + Compiler::OperatorName(expression.fOperator) +
                               "' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
@@ -1690,18 +1690,18 @@
             Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]",
                                      Type::kArray_Kind, oldType, size);
             fSymbolTable->takeOwnership(newType);
-            return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
+            return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
                                                                  *newType));
 
         } else {
-            fErrors.error(base->fPosition, "array size must be a constant");
+            fErrors.error(base->fOffset, "array size must be a constant");
             return nullptr;
         }
     }
     if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
             base->fType.kind() != Type::kVector_Kind) {
-        fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
-                                       "'");
+        fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
+                                     "'");
         return nullptr;
     }
     std::unique_ptr<Expression> converted = this->convertExpression(index);
@@ -1719,26 +1719,26 @@
 }
 
 std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
-                                                      const String& field) {
+                                                      StringFragment field) {
     auto fields = base->fType.fields();
     for (size_t i = 0; i < fields.size(); i++) {
         if (fields[i].fName == field) {
             return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
         }
     }
-    fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a "
-                                   "field named '" + field + "");
+    fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
+                                 "field named '" + field + "");
     return nullptr;
 }
 
 std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
-                                                        const String& fields) {
+                                                        StringFragment fields) {
     if (base->fType.kind() != Type::kVector_Kind) {
-        fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'");
+        fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
         return nullptr;
     }
     std::vector<int> swizzleComponents;
-    for (size_t i = 0; i < fields.size(); i++) {
+    for (size_t i = 0; i < fields.fLength; i++) {
         switch (fields[i]) {
             case 'x': // fall through
             case 'r': // fall through
@@ -1770,40 +1770,40 @@
                 }
                 // fall through
             default:
-                fErrors.error(base->fPosition, String::printf("invalid swizzle component '%c'",
-                                                              fields[i]));
+                fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
+                                                            fields[i]));
                 return nullptr;
         }
     }
     ASSERT(swizzleComponents.size() > 0);
     if (swizzleComponents.size() > 4) {
-        fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'");
+        fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
         return nullptr;
     }
     return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
 }
 
-std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name) {
+std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
     auto found = fCapsMap.find(name);
     if (found == fCapsMap.end()) {
-        fErrors.error(position, "unknown capability flag '" + name + "'");
+        fErrors.error(offset, "unknown capability flag '" + name + "'");
         return nullptr;
     }
     String fullName = "sk_Caps." + name;
-    return std::unique_ptr<Expression>(new Setting(position, fullName,
-                                                   found->second.literal(fContext, position)));
+    return std::unique_ptr<Expression>(new Setting(offset, fullName,
+                                                   found->second.literal(fContext, offset)));
 }
 
-std::unique_ptr<Expression> IRGenerator::getArg(Position position, String name) {
+std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) {
     auto found = fSettings->fArgs.find(name);
     if (found == fSettings->fArgs.end()) {
-        fErrors.error(position, "unknown argument '" + name + "'");
+        fErrors.error(offset, "unknown argument '" + name + "'");
         return nullptr;
     }
     String fullName = "sk_Args." + name;
-    return std::unique_ptr<Expression>(new Setting(position,
+    return std::unique_ptr<Expression>(new Setting(offset,
                                                    fullName,
-                                                   found->second.literal(fContext, position)));
+                                                   found->second.literal(fContext, offset)));
 }
 
 std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
@@ -1822,10 +1822,10 @@
                 Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
                                          -1);
                 fSymbolTable->takeOwnership(newType);
-                return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
+                return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
                                                                      *newType));
             } else {
-                fErrors.error(expression.fPosition, "'[]' must follow a type name");
+                fErrors.error(expression.fOffset, "'[]' must follow a type name");
                 return nullptr;
             }
         }
@@ -1840,15 +1840,15 @@
                 }
                 arguments.push_back(std::move(converted));
             }
-            return this->call(expression.fPosition, std::move(base), std::move(arguments));
+            return this->call(expression.fOffset, std::move(base), std::move(arguments));
         }
         case ASTSuffix::kField_Kind: {
             if (base->fType == *fContext.fSkCaps_Type) {
-                return this->getCap(expression.fPosition,
+                return this->getCap(expression.fOffset,
                                     ((ASTFieldSuffix&) *expression.fSuffix).fField);
             }
             if (base->fType == *fContext.fSkArgs_Type) {
-                return this->getArg(expression.fPosition,
+                return this->getArg(expression.fOffset,
                                     ((ASTFieldSuffix&) *expression.fSuffix).fField);
             }
             switch (base->fType.kind()) {
@@ -1859,14 +1859,14 @@
                     return this->convertField(std::move(base),
                                               ((ASTFieldSuffix&) *expression.fSuffix).fField);
                 default:
-                    fErrors.error(base->fPosition, "cannot swizzle value of type '" +
-                                                   base->fType.description() + "'");
+                    fErrors.error(base->fOffset, "cannot swizzle value of type '" +
+                                                 base->fType.description() + "'");
                     return nullptr;
             }
         }
         case ASTSuffix::kPostIncrement_Kind:
             if (!base->fType.isNumber()) {
-                fErrors.error(expression.fPosition,
+                fErrors.error(expression.fOffset,
                               "'++' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
@@ -1875,7 +1875,7 @@
                                                                      Token::PLUSPLUS));
         case ASTSuffix::kPostDecrement_Kind:
             if (!base->fType.isNumber()) {
-                fErrors.error(expression.fPosition,
+                fErrors.error(expression.fOffset,
                               "'--' cannot operate on '" + base->fType.description() + "'");
                 return nullptr;
             }
@@ -1890,14 +1890,14 @@
 void IRGenerator::checkValid(const Expression& expr) {
     switch (expr.fKind) {
         case Expression::kFunctionReference_Kind:
-            fErrors.error(expr.fPosition, "expected '(' to begin function call");
+            fErrors.error(expr.fOffset, "expected '(' to begin function call");
             break;
         case Expression::kTypeReference_Kind:
-            fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
+            fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
             break;
         default:
             if (expr.fType == *fContext.fInvalid_Type) {
-                fErrors.error(expr.fPosition, "invalid expression");
+                fErrors.error(expr.fOffset, "invalid expression");
             }
     }
 }
@@ -1920,7 +1920,7 @@
         case Expression::kVariableReference_Kind: {
             const Variable& var = ((VariableReference&) expr).fVariable;
             if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
-                fErrors.error(expr.fPosition,
+                fErrors.error(expr.fOffset,
                               "cannot modify immutable variable '" + var.fName + "'");
             }
             ((VariableReference&) expr).setRefKind(readWrite ? VariableReference::kReadWrite_RefKind
@@ -1932,7 +1932,7 @@
             break;
         case Expression::kSwizzle_Kind:
             if (has_duplicates((Swizzle&) expr)) {
-                fErrors.error(expr.fPosition,
+                fErrors.error(expr.fOffset,
                               "cannot write to the same swizzle field more than once");
             }
             this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite);
@@ -1941,18 +1941,20 @@
             this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite);
             break;
         default:
-            fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'");
+            fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
             break;
     }
 }
 
-void IRGenerator::convertProgram(String text,
+void IRGenerator::convertProgram(const char* text,
+                                 size_t length,
                                  SymbolTable& types,
                                  Modifiers::Flag* defaultPrecision,
                                  std::vector<std::unique_ptr<ProgramElement>>* out) {
-    Parser parser(text, types, fErrors);
+    Parser parser(text, length, types, fErrors);
     std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
     if (fErrors.errorCount()) {
+        printf("float type has name: '%s'\n", fContext.fFloat_Type->name().c_str());
         return;
     }
     *defaultPrecision = Modifiers::kHighp_Flag;
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 0a1bae4..3dda028 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -61,7 +61,8 @@
     IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
                 ErrorReporter& errorReporter);
 
-    void convertProgram(String text,
+    void convertProgram(const char* text,
+                        size_t length,
                         SymbolTable& types,
                         Modifiers::Flag* defaultPrecision,
                         std::vector<std::unique_ptr<ProgramElement>>* result);
@@ -103,26 +104,26 @@
                                                                   const ASTModifiersDeclaration& m);
 
     const Type* convertType(const ASTType& type);
-    std::unique_ptr<Expression> call(Position position,
+    std::unique_ptr<Expression> call(int offset,
                                      const FunctionDeclaration& function,
                                      std::vector<std::unique_ptr<Expression>> arguments);
     int callCost(const FunctionDeclaration& function,
                  const std::vector<std::unique_ptr<Expression>>& arguments);
-    std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
+    std::unique_ptr<Expression> call(int offset, std::unique_ptr<Expression> function,
                                      std::vector<std::unique_ptr<Expression>> arguments);
     int coercionCost(const Expression& expr, const Type& type);
     std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
     std::unique_ptr<Block> convertBlock(const ASTBlock& block);
     std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
     std::unique_ptr<Expression> convertNumberConstructor(
-                                                   Position position,
+                                                   int offset,
                                                    const Type& type,
                                                    std::vector<std::unique_ptr<Expression>> params);
     std::unique_ptr<Expression> convertCompoundConstructor(
-                                                   Position position,
+                                                   int offset,
                                                    const Type& type,
                                                    std::vector<std::unique_ptr<Expression>> params);
-    std::unique_ptr<Expression> convertConstructor(Position position,
+    std::unique_ptr<Expression> convertConstructor(int offset,
                                                    const Type& type,
                                                    std::vector<std::unique_ptr<Expression>> params);
     std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
@@ -142,13 +143,13 @@
     std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
     std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
     std::unique_ptr<Section> convertSection(const ASTSection& e);
-    std::unique_ptr<Expression> getCap(Position position, String name);
-    std::unique_ptr<Expression> getArg(Position position, String name);
+    std::unique_ptr<Expression> getCap(int offset, String name);
+    std::unique_ptr<Expression> getArg(int offset, String name);
     std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
     std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
-                                             const String& field);
+                                             StringFragment field);
     std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
-                                               const String& fields);
+                                               StringFragment fields);
     std::unique_ptr<Expression> convertTernaryExpression(const ASTTernaryExpression& expression);
     std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s);
     std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);
diff --git a/src/sksl/SkSLLayoutLexer.cpp b/src/sksl/SkSLLayoutLexer.cpp
new file mode 100644
index 0000000..968391e
--- /dev/null
+++ b/src/sksl/SkSLLayoutLexer.cpp
@@ -0,0 +1,1343 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*****************************************************************************************
+ ******************** This file was generated by sksllex. Do not edit. *******************
+ *****************************************************************************************/
+#include "SkSLLayoutLexer.h"
+
+namespace SkSL {
+
+static int16_t transitions[127][207] = {
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   2, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 14, 0, 0, 0, 0,   0,   0,  0,
+                22,  0, 0, 0,   26,  0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
+                0,   0, 0, 0,   0,   0,  0, 50, 0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   61,  0,  0,
+                0,   0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   83, 0,
+                0,   0, 0, 0,   0,   90, 0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
+                0,   0, 0, 0,   110, 0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
+                0,   0, 0, 130, 0,   0,  0, 0,  0, 136, 0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
+                148, 0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   166, 0,  0,
+                0,   0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 186, 0,   0,  0,
+                0,   0, 0, 193, 0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2,  0,   0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 23, 0,   0,   0,   0, 0,   0,   30, 0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   0,   0, 0,   0,   51, 0,  0, 54, 0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   0,   0, 70,  0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   0,   0, 91,  0,   0,  94, 0, 0,  0,   0, 0, 0, 0, 102, 0, 0, 0,
+                0, 0,  108, 0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   0,   0, 154, 0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   172, 0,   0, 0,   0,   0,  0,  0, 0,  181, 0, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0,   0,   194, 0, 0,   197, 0,  0,  0, 0,  0,   0, 0, 0, 0, 0,
+        },
+        {
+                0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   2, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 0,  0, 0, 0,   0, 0, 55,  0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 69,
+                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 95, 0, 0, 98,  0, 0, 101, 0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                116, 0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 149, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 0,  0, 0, 167, 0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
+                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 198, 0, 0, 201, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0,  13,  0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 44, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   92, 0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 146, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  195, 0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   2, 0,   0,   0,   0,  0,  0,  0,   0, 11, 0, 0, 0,   0,   0, 0,   0, 0,
+                0,   0, 0,   0,   0,   0,  0,  27, 0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                0,   0, 0,   0,   0,   0,  45, 0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                58,  0, 0,   0,   0,   0,  0,  65, 0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                77,  0, 0,   0,   0,   82, 0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                96,  0, 0,   0,   0,   0,  0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 112, 0, 0,
+                0,   0, 117, 0,   0,   0,  0,  0,  123, 0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                134, 0, 0,   0,   138, 0,  0,  0,  142, 0, 0,  0, 0, 147, 0,   0, 0,   0, 152,
+                0,   0, 0,   156, 0,   0,  0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
+                0,   0, 0,   0,   176, 0,  0,  0,  0,   0, 0,  0, 0, 185, 0,   0, 0,   0, 0,
+                0,   0, 0,   0,   0,   0,  0,  0,  199, 0, 0,  0, 0, 0,   205, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 120, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0,   0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 155, 0,
+                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
+                183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
+        },
+        {
+                0, 2, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 56, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0,
+        },
+        {
+                0,   42,  0,  4, 0, 0, 7, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   0,   0,
+                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   32, 0,   0, 0, 0, 37, 0,  0, 40,  0,   0,
+                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   62,  0,
+                0,   0,   0,  0, 0, 0, 0, 0, 72, 0,   0,  0,   0, 0, 0, 0,  80, 0, 0,   0,   0,
+                0,   0,   87, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   104, 0,
+                0,   0,   0,  0, 0, 0, 0, 0, 0,  115, 0,  0,   0, 0, 0, 0,  0,  0, 0,   0,   126,
+                0,   128, 0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 145, 0,   0,
+                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  159, 0, 0, 0, 0,  0,  0, 0,   0,   0,
+                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  180, 0, 0, 0, 0,  0,  0, 0,   0,   0,
+                190, 0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  79, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                24, 25, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,   0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 137, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   184,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+        },
+        {
+                0, 107, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   2, 0,   0, 5,   0, 0, 8, 0, 0, 0,   12, 0,   0,   0, 0, 0,   0,  0, 0,  0,
+                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  34,  0,   0, 0, 0,   0,  0, 41, 0,
+                43,  0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 59,  0,  0, 0,  63,
+                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 74,  0,  0,   0,   0, 0, 0,   81, 0, 0,  0,
+                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  97,  0,   0, 0, 0,   0,  0, 0,  0,
+                106, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 0,   0,  0, 0,  0,
+                0,   0, 129, 0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 0,   0,  0, 0,  0,
+                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  160, 0,   0, 0, 0,   0,  0, 0,  0,
+                169, 0, 0,   0, 173, 0, 0, 0, 0, 0, 0,   0,  0,   182, 0, 0, 0,   0,  0, 0,  0,
+                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 200, 0,  0,   0,   0, 0, 206, 0,
+        },
+        {
+                0, 119, 0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 19, 0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 33, 0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 68, 0,
+                0, 0,   0, 73, 0, 0, 0,   0, 0, 0,  100, 0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   105, 0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   150, 0,   0, 0, 0, 0, 0, 0,  158, 0, 0,  0,
+                0, 0,   0, 0,  0, 0, 168, 0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+        },
+        {
+                0, 157, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 17,  18,  0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 47, 0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   88, 0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, 0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+                0, 0,   0, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+        },
+        {
+                0, 2,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 20,  0,   0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 86, 0,   0, 0,   0,   0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   113, 0, 0,
+                0, 0, 0, 0, 125, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 135, 0,   0, 0,
+                0, 0, 0, 0, 143, 144, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0,  0,   0, 0,   0,   0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  179, 0, 0,   0,   0, 0,
+                0, 0, 0, 0, 189, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
+        },
+        {
+                0,   175, 0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  15, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 35, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   0,   0, 0, 75, 0,   0, 0,   0, 0, 0,  0, 89, 84, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   118, 0, 0, 0,  122, 0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                162, 0,   164, 0, 0, 0,  0,   0, 170, 0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,   192, 187, 0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  178, 0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   0,   21,
+                0,  0,   0,   0, 0, 0,   0,  0,  0,   31, 0,  0, 0, 0,   0, 0, 0, 39, 0,   0,   0,
+                0,  0,   0,   0, 0, 0,   49, 0,  0,   52, 53, 0, 0, 0,   0, 0, 0, 60, 0,   0,   0,
+                0,  0,   0,   0, 0, 0,   0,  71, 0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   0,   0,
+                85, 0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  103, 0,   0,
+                0,  0,   0,   0, 0, 0,   0,  0,  114, 0,  0,  0, 0, 0,   0, 0, 0, 0,  124, 0,   0,
+                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 140, 0, 0, 0, 0,  0,   0,   0,
+                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 161, 0, 0, 0, 0,  0,   0,   0,
+                0,  0,   171, 0, 0, 174, 0,  0,  177, 0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   188, 0,
+                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,
+        },
+        {
+                0, 2,  0, 36, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 16,  0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 48, 0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 163, 0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 67, 0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 151, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0,
+        },
+        {
+                0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 78,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   99, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0,  0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+};
+
+static int16_t accepts[207] = {
+        -1, -1, 23, 23, -1, -1, -1, -1, -1, 3,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, 6,  23, -1, -1, -1,
+        4,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7,  -1, -1,
+        -1, -1, -1, -1, -1, -1, 20, 23, -1, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, 14, 13, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, 1,  23, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, 19, 23, -1, -1, -1, -1, 2,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, 8,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9,  23, -1, -1, -1,
+        -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 23, -1, 5,  23, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, 17, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 23, -1, -1, 21,
+};
+
+LayoutToken LayoutLexer::next() {
+    int startOffset = fOffset;
+    if (startOffset == fLength) {
+        return LayoutToken(LayoutToken::END_OF_FILE, startOffset, 0);
+    }
+    int offset = startOffset;
+    int state = 1;
+    LayoutToken::Kind lastAccept = LayoutToken::Kind::INVALID;
+    int lastAcceptEnd = startOffset + 1;
+    while (offset < fLength) {
+        state = transitions[(int)fText[offset]][state];
+        ++offset;
+        if (!state) {
+            break;
+        }
+        if (accepts[state]) {
+            lastAccept = (LayoutToken::Kind)accepts[state];
+            lastAcceptEnd = offset;
+        }
+    }
+    fOffset = lastAcceptEnd;
+    return LayoutToken(lastAccept, startOffset, lastAcceptEnd - startOffset);
+}
+
+}  // namespace
diff --git a/src/sksl/SkSLLayoutLexer.h b/src/sksl/SkSLLayoutLexer.h
new file mode 100644
index 0000000..f3d250a
--- /dev/null
+++ b/src/sksl/SkSLLayoutLexer.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*****************************************************************************************
+ ******************** This file was generated by sksllex. Do not edit. *******************
+ *****************************************************************************************/
+#ifndef SKSL_LayoutLexer
+#define SKSL_LayoutLexer
+#include <cstddef>
+#include <cstdint>
+namespace SkSL {
+
+struct LayoutToken {
+    enum Kind {
+#undef END_OF_FILE
+        END_OF_FILE,
+#undef LOCATION
+        LOCATION,
+#undef OFFSET
+        OFFSET,
+#undef BINDING
+        BINDING,
+#undef INDEX
+        INDEX,
+#undef SET
+        SET,
+#undef BUILTIN
+        BUILTIN,
+#undef INPUT_ATTACHMENT_INDEX
+        INPUT_ATTACHMENT_INDEX,
+#undef ORIGIN_UPPER_LEFT
+        ORIGIN_UPPER_LEFT,
+#undef OVERRIDE_COVERAGE
+        OVERRIDE_COVERAGE,
+#undef BLEND_SUPPORT_ALL_EQUATIONS
+        BLEND_SUPPORT_ALL_EQUATIONS,
+#undef PUSH_CONSTANT
+        PUSH_CONSTANT,
+#undef POINTS
+        POINTS,
+#undef LINES
+        LINES,
+#undef LINE_STRIP
+        LINE_STRIP,
+#undef LINES_ADJACENCY
+        LINES_ADJACENCY,
+#undef TRIANGLES
+        TRIANGLES,
+#undef TRIANGLE_STRIP
+        TRIANGLE_STRIP,
+#undef TRIANGLES_ADJACENCY
+        TRIANGLES_ADJACENCY,
+#undef MAX_VERTICES
+        MAX_VERTICES,
+#undef INVOCATIONS
+        INVOCATIONS,
+#undef WHEN
+        WHEN,
+#undef KEY
+        KEY,
+#undef INVALID
+        INVALID,
+    };
+
+    LayoutToken() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {}
+
+    LayoutToken(Kind kind, int offset, int length)
+            : fKind(kind), fOffset(offset), fLength(length) {}
+
+    Kind fKind;
+    int fOffset;
+    int fLength;
+};
+
+class LayoutLexer {
+public:
+    void start(const char* text, size_t length) {
+        fText = text;
+        fLength = length;
+        fOffset = 0;
+    }
+
+    LayoutToken next();
+
+private:
+    const char* fText;
+    int fLength;
+    int fOffset;
+};
+
+}  // namespace
+#endif
diff --git a/src/sksl/SkSLLexer.cpp b/src/sksl/SkSLLexer.cpp
new file mode 100644
index 0000000..ed905ac
--- /dev/null
+++ b/src/sksl/SkSLLexer.cpp
@@ -0,0 +1,1925 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*****************************************************************************************
+ ******************** This file was generated by sksllex. Do not edit. *******************
+ *****************************************************************************************/
+#include "SkSLLexer.h"
+
+namespace SkSL {
+
+static int16_t transitions[127][281] = {
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 3, 3, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 3, 3, 3, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 3, 3, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 2, 3, 3, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 5, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 7, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0, 11, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 13, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 17, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 18, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 19, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 35, 36, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 21, 0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 22, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 32, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 44, 0, 0,  47, 0,
+                0, 0,  51, 0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0,  0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0,
+        },
+        {
+                0, 24, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 25, 0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 26, 0,  0, 0, 0, 0, 32, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 44, 0, 0, 47, 0,
+                0, 0,  51, 0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0,  0, 0, 0,  0,
+                0, 0,  0,  0, 0, 0, 0, 0,  0, 0, 0, 0,  0,  0, 0,  0, 0,
+        },
+        {
+                0, 29, 0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0,
+                0, 0,  0, 41, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,
+                0, 0,  0, 0,  0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 34, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 38, 35, 37, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  40, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  55, 0,  0,  0,  0,  0,  0,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  30, 30, 33, 33, 33, 0,  35, 35, 0,  38, 0,  49, 42,
+                42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0, 56, 0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 57, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 58, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 59, 0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 60, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 63, 0, 0, 0, 6, 0, 0, 0, 0, 0,  12,  0,  16,  15, 0,  0, 0,  0, 20, 0, 23, 0, 0,
+                0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 39, 35,  35, 0,   38, 0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  62,  61, 0,   0,  64, 0, 66, 0, 68, 0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 83, 0,   85, 0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0,  0,  0, 0,  0, 0,  0, 0,  0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  276, 0,  278, 0,  0,  0,
+        },
+        {
+                0, 65, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 69, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 70, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  31, 0,  0,  0,  0,  35, 35, 0,  38, 0,  50, 46,
+                43, 0,  0,  0,  0,  0,  0,  50, 0,  0,  0,  54, 54, 50, 0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0, 80, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 81, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 82, 0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 84, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,  0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,   0,  8,  8,  10,  10, 0,  0,  0,  0,   0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  0,  0,   0,  35, 35, 0,
+                38, 0,  0,  0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  71, 71,  71, 71, 71, 71,
+                71, 71, 71, 71, 0,  0,   0,  0,  0,  0,   10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 215, 10, 10, 10, 219, 10, 10, 10, 10, 224, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10,  10, 10, 0,  0,   0,  0,  0,  0,  0,
+        },
+        {
+                0, 4, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0,   9,  0,   0,   0,  0,   0,   8,   8,   10, 10,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,   0,  0,   0,   0,  0,   0,   0,   0,   0,  0,   0,  0,  0,  0,  0,  35, 35, 0,
+                38,  0,  0,   0,   0,  0,   0,   0,   0,   0,  0,   0,  0,  0,  0,  54, 54, 0,  0,
+                0,   0,  0,   0,   0,  0,   0,   0,   0,   0,  0,   0,  0,  71, 71, 71, 71, 71, 71,
+                71,  71, 71,  71,  0,  0,   0,   0,   0,   0,  10,  10, 89, 10, 10, 10, 10, 10, 10,
+                10,  97, 10,  10,  10, 10,  10,  10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  118, 10, 10,  10,  10,  10,  10, 125, 10, 10, 10, 10, 10, 10, 10, 10,
+                134, 10, 10,  10,  10, 139, 10,  10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 155, 10,  10, 10,  10,  10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  10,  10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  197, 10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  10,  217, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  10,  10,  10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  10,  10,  256, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10,
+                10,  10, 10,  10,  10, 10,  10,  10,  0,   0,  0,   0,  0,  0,  0,
+        },
+        {
+                0,  86, 0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54, 54, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,   96, 0,  0,  0,  0,  0,   8,  8,  10,  10, 0,   0,  0,  0,  0,  0,   0,   0,
+                0,   0,  0,  0,  0,  0,  0,   0,  0,  0,   0,  0,   0,  0,  0,  0,  35,  35,  0,
+                38,  0,  0,  0,  0,  0,  0,   0,  0,  0,   0,  0,   0,  0,  0,  54, 54,  0,   0,
+                0,   0,  0,  0,  0,  0,  0,   0,  0,  0,   0,  0,   0,  71, 71, 71, 71,  71,  71,
+                71,  78, 71, 71, 0,  0,  0,   0,  0,  0,   10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 124, 10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 178, 10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  189, 10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 207, 10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  10,  10,
+                229, 10, 10, 10, 10, 10, 235, 10, 10, 10,  10, 240, 10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 10, 10,  10, 10,  10, 10, 10, 10, 10,  10,  10,
+                10,  10, 10, 10, 10, 10, 10,  10, 0,  0,   0,  0,   0,  0,  0,
+        },
+        {
+                0,  115, 0,  0,  0,  0,  0,  8,   8,  10, 10, 0,  0,   0,  0,  0,  0,  0,  0,
+                0,  0,   0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  35, 35, 0,
+                38, 0,   0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  54, 54, 0,  0,
+                0,  0,   0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,   71, 71, 71, 71, 71, 71,
+                71, 71,  71, 71, 0,  0,  0,  0,   0,  0,  10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 127, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 165, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 198, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 222, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10,  0,  0,  0,  0,  0,   0,  0,
+        },
+        {
+                0,  129, 0,  0,  0,  0,   0,   8,   8,   10, 10,  0,   0,   0,   0,   0,   0,   0,
+                0,  0,   0,  0,  0,  0,   0,   0,   0,   0,  0,   0,   31,  0,   0,   0,   0,   35,
+                35, 0,   38, 0,  50, 46,  43,  0,   0,   0,  0,   0,   0,   50,  0,   0,   0,   54,
+                54, 50,  0,  0,  0,  0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,   71,  71,
+                71, 71,  71, 71, 71, 71,  71,  71,  0,   0,  0,   0,   0,   0,   10,  88,  10,  10,
+                10, 10,  10, 94, 10, 10,  10,  10,  99,  10, 10,  102, 10,  104, 10,  10,  10,  10,
+                10, 10,  10, 10, 10, 114, 10,  116, 10,  10, 10,  10,  10,  10,  10,  10,  10,  10,
+                10, 10,  10, 10, 10, 132, 10,  10,  10,  10, 137, 10,  10,  10,  10,  10,  10,  10,
+                10, 10,  10, 10, 10, 10,  10,  10,  10,  10, 10,  10,  10,  10,  10,  10,  10,  10,
+                10, 164, 10, 10, 10, 10,  10,  10,  10,  10, 173, 10,  10,  10,  177, 10,  10,  10,
+                10, 182, 10, 10, 10, 10,  10,  188, 10,  10, 10,  10,  10,  10,  10,  196, 10,  10,
+                10, 10,  10, 10, 10, 10,  10,  10,  10,  10, 10,  10,  10,  10,  10,  10,  10,  10,
+                10, 10,  10, 10, 10, 10,  223, 10,  225, 10, 10,  228, 10,  10,  10,  10,  10,  10,
+                10, 10,  10, 10, 10, 10,  10,  10,  10,  10, 245, 10,  10,  10,  10,  10,  10,  10,
+                10, 10,  10, 10, 10, 10,  10,  260, 10,  10, 10,  10,  265, 10,  10,  10,  269, 10,
+                10, 10,  10, 10, 0,  0,   0,   0,   0,   0,  0,
+        },
+        {
+                0,  133, 0,   0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,   0,   0,   0,
+                0,  0,   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   35,  35,  0,
+                38, 0,   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  54,  54,  0,   0,
+                0,  0,   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 73,  71,  71,  71,
+                71, 71,  71,  71, 0,  0,  0,  0,  0,  0,  10, 10, 10, 10, 10, 92,  93,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  117, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 149, 10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  226, 227, 10,
+                10, 10,  10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 249, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,
+                10, 10,  10,  10, 10, 10, 10, 10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,   0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,   0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,   0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 145, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  143, 0,  0,  0,  0,   0,   8,  8,  10, 10, 0,  0,   0,  0,   0,  0,  0,  0,
+                0,  0,   0,  0,  0,  0,   0,   0,  0,  0,  0,  0,  0,   0,  0,   0,  35, 35, 0,
+                38, 0,   0,  0,  0,  0,   0,   0,  0,  0,  0,  0,  0,   0,  0,   0,  0,  0,  0,
+                0,  0,   0,  0,  0,  0,   0,   0,  0,  0,  0,  0,  0,   71, 71,  71, 71, 71, 71,
+                71, 71,  79, 71, 0,  0,   0,   0,  0,  0,  10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 101, 10,  10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 146, 10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  216, 10, 10, 10, 10, 10, 10,  10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 241, 10, 10,  10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 10, 10, 10, 10, 10,  10, 262, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10,  10,  10, 0,  0,  0,  0,  0,   0,  0,
+        },
+        {
+                0,   148, 0,  0,  0,  0,  0,  8,  8,   10,  10,  0,   0,  0,   0,  0,   0,  0,  0,
+                0,   0,   0,  0,  0,  0,  0,  0,  0,   0,   0,   0,   0,  0,   0,  0,   35, 35, 0,
+                38,  0,   0,  0,  0,  0,  0,  0,  0,   0,   0,   0,   0,  0,   0,  0,   0,  0,  0,
+                0,   0,   0,  0,  0,  0,  0,  0,  0,   0,   0,   0,   0,  72,  71, 71,  71, 71, 76,
+                71,  71,  71, 71, 0,  0,  0,  0,  0,   0,   10,  10,  10, 10,  10, 10,  10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 10,  10,  10,  10,  10, 10,  10, 111, 10, 10, 10,
+                10,  122, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,  10, 10,  10, 10,  10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 10,  10,  144, 10,  10, 10,  10, 10,  10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 10,  10,  10,  10,  10, 166, 10, 10,  10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 180, 10,  10,  10,  10, 10,  10, 10,  10, 10, 190,
+                10,  192, 10, 10, 10, 10, 10, 10, 10,  10,  10,  10,  10, 10,  10, 206, 10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 10,  10,  10,  221, 10, 10,  10, 10,  10, 10, 10,
+                10,  10,  10, 10, 10, 10, 10, 10, 10,  238, 10,  10,  10, 10,  10, 10,  10, 10, 10,
+                248, 10,  10, 10, 10, 10, 10, 10, 10,  10,  258, 10,  10, 10,  10, 263, 10, 10, 10,
+                267, 10,  10, 10, 10, 10, 10, 10, 0,   0,   0,   0,   0,  0,   0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,   0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,   0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10,  10, 90, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 214, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,   0,  0,  0,  0,
+        },
+        {
+                0,   154, 0,  0,  0,  0,   0,  8,   8,  10, 10,  0,   0,  0,  0,  0,   0,   0,  0,
+                0,   0,   0,  0,  0,  0,   0,  0,   0,  0,  0,   0,   0,  0,  0,  0,   35,  35, 0,
+                38,  0,   0,  0,  0,  0,   0,  0,   0,  0,  0,   0,   0,  0,  0,  0,   0,   0,  0,
+                0,   0,   0,  0,  0,  0,   0,  0,   0,  0,  0,   0,   0,  71, 71, 71,  71,  71, 71,
+                71,  71,  71, 71, 0,  0,   0,  0,   0,  0,  10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 120, 10, 10,  10, 10, 10,  10,  10, 10, 10, 130, 10,  10, 10,
+                138, 135, 10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 201, 10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 10,  10, 10, 10,  10,  10, 10, 10, 10,  10,  10, 10,
+                10,  10,  10, 10, 10, 10,  10, 255, 10, 10, 10,  259, 10, 10, 10, 10,  264, 10, 10,
+                10,  10,  10, 10, 10, 272, 10, 10,  0,  0,  0,   0,   0,  0,  0,
+        },
+        {
+                0,  163, 0,  0,  0,   0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,   0,  0,  0,
+                0,  0,   0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   35, 35, 0,
+                38, 0,   0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,
+                0,  0,   0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  71, 71, 71,  71, 71, 71,
+                71, 71,  71, 71, 0,   0,  0,  0,  0,  0,  10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 168, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 252, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  170, 0,   0,   0,   0,   0,  8,  8,  10,  10, 0,  0,  0,  0,  0,   0,   0,  0,
+                0,  0,   0,   0,   0,   0,   0,  0,  0,  0,   0,  0,  0,  0,  0,  0,   35,  35, 0,
+                38, 0,   0,   0,   0,   0,   0,  0,  0,  0,   0,  0,  0,  0,  0,  0,   0,   0,  0,
+                0,  0,   0,   0,   0,   0,   0,  0,  0,  0,   0,  0,  0,  71, 71, 71,  71,  71, 71,
+                71, 71,  71,  71,  0,   0,   0,  0,  0,  0,   10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  10,  10,  107, 10, 10, 10, 105, 10, 10, 10, 10, 10, 10,  112, 10, 10,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 150, 10,  10, 10,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  194, 10,  10,  10, 10, 10, 200, 10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  212, 10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 247,
+                10, 10,  10,  10,  10,  10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10,  10,  10, 10,
+                10, 10,  10,  10,  271, 10,  10, 10, 0,  0,   0,  0,  0,  0,  0,
+        },
+        {
+                0,   183, 0,   0,   0,   0,  0,   8,  8,   10, 10, 0,  0,  0,  0,  0,  0,  0,   0,
+                0,   0,   0,   0,   0,   0,  0,   0,  0,   0,  0,  0,  0,  0,  0,  0,  35, 35,  0,
+                38,  0,   0,   0,   0,   0,  0,   0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,   0,
+                0,   0,   0,   0,   0,   0,  0,   0,  0,   0,  0,  0,  0,  71, 71, 71, 71, 71,  71,
+                71,  71,  71,  71,  0,   0,  0,   0,  0,   0,  10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  100, 10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  128, 10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                141, 10,  10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 151, 10,
+                10,  10,  160, 10,  157, 10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  171,
+                10,  10,  10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  10,  193, 10,  10,  10, 10,  10, 199, 10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  10,  10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  10,  10,  10,  10,  10, 10,  10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  10,  250, 10,  10,  10, 254, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,  10,
+                10,  10,  10,  270, 10,  10, 10,  10, 0,   0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,   186, 0,  0,  0,   0,  0,  8,  8,  10,  10, 0,  0,  0,   0,  0,  0,   0,  0,
+                0,   0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  0,   0,  0,  35,  35, 0,
+                38,  0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  0,   0,  0,  0,   0,  0,
+                0,   0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  71,  71, 71, 71,  71, 71,
+                71,  71,  71, 71, 0,   0,  0,  0,  0,  0,   10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 147, 10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 162, 10, 10, 10, 10,  10, 10, 169, 10, 10,
+                172, 10,  10, 10, 176, 10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10,  10, 10, 10,  10, 10,
+                10,  10,  10, 10, 10,  10, 10, 10, 0,  0,   0,  0,  0,  0,   0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  195, 0,   0,   0,   0,  0,  8,   8,   10, 10, 0,   0,  0,  0,   0,   0,  0,  0,
+                0,  0,   0,   0,   0,   0,  0,  0,   0,   0,  0,  0,   0,  0,  0,   0,   35, 35, 0,
+                38, 0,   0,   0,   0,   0,  0,  0,   0,   0,  0,  0,   0,  0,  0,   0,   0,  0,  0,
+                0,  0,   0,   0,   0,   0,  0,  0,   0,   0,  0,  0,   0,  71, 71,  71,  71, 71, 71,
+                71, 71,  71,  71,  0,   0,  0,  0,   0,   0,  87, 10,  10, 10, 10,  10,  10, 10, 95,
+                10, 10,  10,  10,  10,  10, 10, 103, 10,  10, 10, 10,  10, 10, 10,  10,  10, 10, 10,
+                10, 10,  10,  10,  10,  10, 10, 10,  10,  10, 10, 126, 10, 10, 10,  10,  10, 10, 10,
+                10, 10,  10,  10,  10,  10, 10, 10,  142, 10, 10, 10,  10, 10, 10,  10,  10, 10, 10,
+                10, 10,  10,  10,  10,  10, 10, 10,  10,  10, 10, 10,  10, 10, 10,  10,  10, 10, 10,
+                10, 10,  174, 10,  10,  10, 10, 10,  10,  10, 10, 10,  10, 10, 10,  187, 10, 10, 10,
+                10, 10,  10,  10,  10,  10, 10, 10,  10,  10, 10, 10,  10, 10, 205, 10,  10, 10, 10,
+                10, 211, 10,  10,  10,  10, 10, 10,  10,  10, 10, 10,  10, 10, 10,  10,  10, 10, 10,
+                10, 10,  10,  10,  233, 10, 10, 10,  10,  10, 10, 10,  10, 10, 243, 10,  10, 10, 10,
+                10, 10,  10,  251, 10,  10, 10, 10,  10,  10, 10, 10,  10, 10, 266, 10,  10, 10, 10,
+                10, 10,  10,  10,  10,  10, 10, 10,  0,   0,  0,  0,   0,  0,  0,
+        },
+        {
+                0,   213, 0,   0,   0,  0,  0,   8,  8,   10, 10,  0,  0,   0,  0,  0,  0,   0,  0,
+                0,   0,   0,   0,   0,  0,  0,   0,  0,   0,  0,   0,  0,   0,  0,  0,  35,  35, 0,
+                38,  0,   0,   0,   0,  0,  0,   0,  0,   0,  0,   0,  0,   0,  0,  0,  0,   0,  0,
+                0,   0,   0,   0,   0,  0,  0,   0,  0,   0,  0,   0,  0,   74, 71, 71, 71,  71, 71,
+                71,  71,  71,  71,  0,  0,  0,   0,  0,   0,  10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  98,  10,  10, 10, 10,  10, 10,  10, 10,  10, 108, 10, 10, 10, 10,  10, 10,
+                10,  10,  10,  10,  10, 10, 10,  10, 123, 10, 10,  10, 10,  10, 10, 10, 131, 10, 10,
+                10,  10,  136, 10,  10, 10, 10,  10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  10,  10,  10, 10, 10,  10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  10,  175, 10, 10, 10,  10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                191, 10,  10,  10,  10, 10, 203, 10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  10,  10,  10, 10, 10,  10, 218, 10, 220, 10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  231, 10,  10, 10, 10,  10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  10,  10,  10, 10, 10,  10, 10,  10, 10,  10, 10,  10, 10, 10, 10,  10, 10,
+                10,  10,  10,  10,  10, 10, 10,  10, 0,   0,  0,   0,  0,   0,  0,
+        },
+        {
+                0,   242, 0,  0,  0,   0,   0,  8,  8,   10,  10, 0,  0,   0,   0,   0,   0,   0,
+                0,   0,   0,  0,  0,   0,   0,  0,  0,   0,   0,  0,  0,   0,   0,   0,   0,   35,
+                35,  0,   38, 0,  0,   0,   0,  0,  0,   0,   0,  0,  0,   0,   0,   0,   0,   0,
+                0,   0,   0,  0,  0,   0,   0,  0,  0,   0,   0,  0,  0,   0,   0,   0,   71,  71,
+                71,  71,  71, 71, 77,  71,  71, 71, 0,   0,   0,  0,  0,   0,   10,  10,  10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10,  106, 10,  110,
+                109, 10,  10, 10, 10,  10,  10, 10, 10,  10,  10, 10, 121, 10,  10,  10,  10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10, 10, 10,  140, 10,  10,  10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 153, 10,  10, 10, 10,  10,  159, 10,  10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10,  10,  179, 10,
+                10,  10,  10, 10, 185, 10,  10, 10, 10,  10,  10, 10, 10,  10,  10,  10,  209, 10,
+                10,  10,  10, 10, 10,  204, 10, 10, 10,  208, 10, 10, 10,  10,  10,  232, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10,  10,  10, 10, 10,  230, 10,  10,  10,  10,
+                10,  236, 10, 10, 239, 10,  10, 10, 10,  10,  10, 10, 10,  10,  10,  10,  10,  10,
+                10,  10,  10, 10, 257, 10,  10, 10, 10,  10,  10, 10, 10,  10,  10,  268, 10,  10,
+                10,  10,  10, 10, 0,   0,   0,  0,  0,   0,   0,
+        },
+        {
+                0,   246, 0,  0,  0,   0,   0,  8,  8,  10, 10, 0,  0,   0,  0,   0,   0,  0,   0,
+                0,   0,   0,  0,  0,   0,   0,  0,  0,  0,  0,  0,  0,   0,  0,   0,   35, 35,  0,
+                38,  0,   0,  0,  0,   0,   0,  0,  0,  0,  0,  0,  0,   0,  0,   0,   0,  0,   0,
+                0,   0,   0,  0,  0,   0,   0,  0,  0,  0,  0,  0,  0,   71, 71,  71,  71, 71,  71,
+                71,  71,  71, 71, 0,   0,   0,  0,  0,  0,  91, 10, 10,  10, 10,  10,  10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 113, 10,
+                10,  10,  10, 10, 119, 10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 10,  152,
+                10,  10,  10, 10, 10,  158, 10, 10, 10, 10, 10, 10, 10,  10, 167, 10,  10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 184, 10, 10,  10,  10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 10,  10,
+                210, 10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 10,  10,
+                10,  10,  10, 10, 10,  234, 10, 10, 10, 10, 10, 10, 10,  10, 10,  244, 10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 10, 10, 10, 10, 10,  10, 10,  10,  10, 10,  10,
+                10,  10,  10, 10, 10,  10,  10, 10, 0,  0,  0,  0,  0,   0,  0,
+        },
+        {
+                0,  253, 0,  0,  0,  0,  0,  8,  8,  10,  10, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,   0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  35, 35, 0,
+                38, 0,   0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,   0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  71, 71, 71, 71, 71, 71,
+                71, 71,  71, 71, 0,  0,  0,  0,  0,  0,   10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 181, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10, 10, 10, 10, 0,  0,   0,  0,  0,  0,  0,
+        },
+        {
+                0,  261, 0,  0,  0,   0,  0,  8,  8,   10, 10, 0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,   0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  35, 35, 0,
+                38, 0,   0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,   0,  0,  0,   0,  0,  0,  0,   0,  0,  0,  0,  71, 71, 71, 71, 75, 71,
+                71, 71,  71, 71, 0,   0,  0,  0,  0,   0,  10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 161, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 237, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10,  10, 10, 10,  10, 10, 10, 0,   0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  53, 0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,   0,  0,  0,   8,  8,  10, 10, 0,   0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  0,  35, 35, 0,
+                38, 0,  0,  0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,   0,  0,  0,   0,  0,  0,  0,  0,   0,  71, 71, 71, 71, 71, 71,
+                71, 71, 71, 71,  0,  0,  0,   0,  0,  0,  10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 156, 10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 202, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 10,  10, 10, 10, 10, 10,  10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10,  10, 10, 273, 10, 0,  0,  0,  0,   0,  0,  0,
+        },
+        {
+                0,  9,  0,  0,  0,  0,  0,  8,  8,  10, 10, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  35, 35, 0,  38, 0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0,  0,  0,  0,
+                0,  0,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+                10, 0,  0,  0,  0,  0,  0,  0,
+        },
+        {
+                0, 274, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 275, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 277, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 279, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+        {
+                0, 280, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
+        },
+};
+
+static int16_t accepts[281] = {
+        -1, -1, 92, 92, 95, 66, 71, 95, 40, 39, 39, 56, 80, 61, 65, 88, 85, 42, 43, 54, 78, 52,
+        50, 76, 49, 53, 51, 77, 90, 48, 1,  -1, -1, 1,  55, -1, -1, 94, 93, 79, 2,  1,  1,  -1,
+        -1, 1,  -1, -1, 1,  2,  -1, -1, 1,  -1, 2,  2,  68, 91, 89, 73, 57, 81, 75, 69, 70, 72,
+        74, 58, 82, 67, 95, 41, 41, 6,  41, 41, 41, 41, 41, 12, 46, 47, 60, 84, 64, 87, 39, 39,
+        39, 39, 15, 39, 39, 39, 39, 34, 39, 39, 39, 13, 39, 39, 39, 39, 39, 39, 31, 39, 39, 23,
+        39, 39, 39, 39, 16, 39, 39, 39, 39, 39, 39, 14, 39, 39, 39, 39, 39, 17, 10, 39, 39, 39,
+        7,  39, 39, 39, 39, 4,  39, 39, 27, 39, 8,  39, 39, 39, 39, 26, 39, 5,  19, 39, 39, 21,
+        39, 39, 39, 39, 39, 37, 39, 39, 24, 39, 39, 39, 39, 39, 39, 25, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 28, 39, 39, 20, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39,
+        39, 39, 39, 39, 29, 39, 39, 39, 39, 39, 33, 39, 39, 39, 18, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 35, 39, 39, 39, 39, 36, 39, 39, 39, 39, 11,
+        39, 39, 39, 3,  39, 39, 39, 39, 39, 39, 22, 39, 39, 39, 39, 39, 39, 39, 32, 39, 39, 39,
+        39, 9,  39, 39, 39, 39, 39, 39, 39, 30, 44, 59, 83, 63, 86, 45, 62,
+};
+
+Token Lexer::next() {
+    int startOffset = fOffset;
+    if (startOffset == fLength) {
+        return Token(Token::END_OF_FILE, startOffset, 0);
+    }
+    int offset = startOffset;
+    int state = 1;
+    Token::Kind lastAccept = Token::Kind::INVALID;
+    int lastAcceptEnd = startOffset + 1;
+    while (offset < fLength) {
+        state = transitions[(int)fText[offset]][state];
+        ++offset;
+        if (!state) {
+            break;
+        }
+        if (accepts[state]) {
+            lastAccept = (Token::Kind)accepts[state];
+            lastAcceptEnd = offset;
+        }
+    }
+    fOffset = lastAcceptEnd;
+    return Token(lastAccept, startOffset, lastAcceptEnd - startOffset);
+}
+
+}  // namespace
diff --git a/src/sksl/SkSLLexer.h b/src/sksl/SkSLLexer.h
new file mode 100644
index 0000000..246be22
--- /dev/null
+++ b/src/sksl/SkSLLexer.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/*****************************************************************************************
+ ******************** This file was generated by sksllex. Do not edit. *******************
+ *****************************************************************************************/
+#ifndef SKSL_Lexer
+#define SKSL_Lexer
+#include <cstddef>
+#include <cstdint>
+namespace SkSL {
+
+struct Token {
+    enum Kind {
+#undef END_OF_FILE
+        END_OF_FILE,
+#undef FLOAT_LITERAL
+        FLOAT_LITERAL,
+#undef INT_LITERAL
+        INT_LITERAL,
+#undef TRUE_LITERAL
+        TRUE_LITERAL,
+#undef FALSE_LITERAL
+        FALSE_LITERAL,
+#undef IF
+        IF,
+#undef STATIC_IF
+        STATIC_IF,
+#undef ELSE
+        ELSE,
+#undef FOR
+        FOR,
+#undef WHILE
+        WHILE,
+#undef DO
+        DO,
+#undef SWITCH
+        SWITCH,
+#undef STATIC_SWITCH
+        STATIC_SWITCH,
+#undef CASE
+        CASE,
+#undef DEFAULT
+        DEFAULT,
+#undef BREAK
+        BREAK,
+#undef CONTINUE
+        CONTINUE,
+#undef DISCARD
+        DISCARD,
+#undef RETURN
+        RETURN,
+#undef IN
+        IN,
+#undef OUT
+        OUT,
+#undef INOUT
+        INOUT,
+#undef UNIFORM
+        UNIFORM,
+#undef CONST
+        CONST,
+#undef LOWP
+        LOWP,
+#undef MEDIUMP
+        MEDIUMP,
+#undef HIGHP
+        HIGHP,
+#undef FLAT
+        FLAT,
+#undef NOPERSPECTIVE
+        NOPERSPECTIVE,
+#undef READONLY
+        READONLY,
+#undef WRITEONLY
+        WRITEONLY,
+#undef COHERENT
+        COHERENT,
+#undef VOLATILE
+        VOLATILE,
+#undef RESTRICT
+        RESTRICT,
+#undef BUFFER
+        BUFFER,
+#undef HASSIDEEFFECTS
+        HASSIDEEFFECTS,
+#undef STRUCT
+        STRUCT,
+#undef LAYOUT
+        LAYOUT,
+#undef PRECISION
+        PRECISION,
+#undef IDENTIFIER
+        IDENTIFIER,
+#undef DIRECTIVE
+        DIRECTIVE,
+#undef SECTION
+        SECTION,
+#undef LPAREN
+        LPAREN,
+#undef RPAREN
+        RPAREN,
+#undef LBRACE
+        LBRACE,
+#undef RBRACE
+        RBRACE,
+#undef LBRACKET
+        LBRACKET,
+#undef RBRACKET
+        RBRACKET,
+#undef DOT
+        DOT,
+#undef COMMA
+        COMMA,
+#undef PLUSPLUS
+        PLUSPLUS,
+#undef MINUSMINUS
+        MINUSMINUS,
+#undef PLUS
+        PLUS,
+#undef MINUS
+        MINUS,
+#undef STAR
+        STAR,
+#undef SLASH
+        SLASH,
+#undef PERCENT
+        PERCENT,
+#undef SHL
+        SHL,
+#undef SHR
+        SHR,
+#undef BITWISEOR
+        BITWISEOR,
+#undef BITWISEXOR
+        BITWISEXOR,
+#undef BITWISEAND
+        BITWISEAND,
+#undef BITWISENOT
+        BITWISENOT,
+#undef LOGICALOR
+        LOGICALOR,
+#undef LOGICALXOR
+        LOGICALXOR,
+#undef LOGICALAND
+        LOGICALAND,
+#undef LOGICALNOT
+        LOGICALNOT,
+#undef QUESTION
+        QUESTION,
+#undef COLON
+        COLON,
+#undef EQ
+        EQ,
+#undef EQEQ
+        EQEQ,
+#undef NEQ
+        NEQ,
+#undef GT
+        GT,
+#undef LT
+        LT,
+#undef GTEQ
+        GTEQ,
+#undef LTEQ
+        LTEQ,
+#undef PLUSEQ
+        PLUSEQ,
+#undef MINUSEQ
+        MINUSEQ,
+#undef STAREQ
+        STAREQ,
+#undef SLASHEQ
+        SLASHEQ,
+#undef PERCENTEQ
+        PERCENTEQ,
+#undef SHLEQ
+        SHLEQ,
+#undef SHREQ
+        SHREQ,
+#undef BITWISEOREQ
+        BITWISEOREQ,
+#undef BITWISEXOREQ
+        BITWISEXOREQ,
+#undef BITWISEANDEQ
+        BITWISEANDEQ,
+#undef LOGICALOREQ
+        LOGICALOREQ,
+#undef LOGICALXOREQ
+        LOGICALXOREQ,
+#undef LOGICALANDEQ
+        LOGICALANDEQ,
+#undef SEMICOLON
+        SEMICOLON,
+#undef ARROW
+        ARROW,
+#undef COLONCOLON
+        COLONCOLON,
+#undef WHITESPACE
+        WHITESPACE,
+#undef LINE_COMMENT
+        LINE_COMMENT,
+#undef BLOCK_COMMENT
+        BLOCK_COMMENT,
+#undef INVALID
+        INVALID,
+    };
+
+    Token() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {}
+
+    Token(Kind kind, int offset, int length) : fKind(kind), fOffset(offset), fLength(length) {}
+
+    Kind fKind;
+    int fOffset;
+    int fLength;
+};
+
+class Lexer {
+public:
+    void start(const char* text, size_t length) {
+        fText = text;
+        fLength = length;
+        fOffset = 0;
+    }
+
+    Token next();
+
+private:
+    const char* fText;
+    int fLength;
+    int fOffset;
+};
+
+}  // namespace
+#endif
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index f712b34..d8ecc61 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -7,26 +7,6 @@
 
 #include "stdio.h"
 #include "SkSLParser.h"
-#include "SkSLToken.h"
-
-#define register
-#include "disable_flex_warnings.h"
-#include "lex.sksl.c"
-static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
-              YY_FLEX_SUBMINOR_VERSION >= 20601,
-              "we require Flex 2.6.1 or better for security reasons");
-#undef register
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#include "lex.layout.h"
 #include "ast/SkSLASTBinaryExpression.h"
 #include "ast/SkSLASTBlock.h"
 #include "ast/SkSLASTBoolLiteral.h"
@@ -83,7 +63,7 @@
 
     bool checkValid() {
         if (fParser->fDepth > MAX_PARSE_DEPTH) {
-            fParser->error(fParser->peek().fPosition, String("exceeded max parse depth"));
+            fParser->error(fParser->peek(), String("exceeded max parse depth"));
             return false;
         }
         return true;
@@ -93,20 +73,12 @@
     Parser* fParser;
 };
 
-Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors)
-: fPushback(Position(-1, -1), Token::INVALID_TOKEN, String())
+Parser::Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors)
+: fText(text)
+, fPushback(Token::INVALID, -1, -1)
 , fTypes(types)
 , fErrors(errors) {
-    sksllex_init(&fScanner);
-    layoutlex_init(&fLayoutScanner);
-    fBuffer = sksl_scan_string(text.c_str(), fScanner);
-    skslset_lineno(1, fScanner);
-}
-
-Parser::~Parser() {
-    sksl_delete_buffer(fBuffer, fScanner);
-    sksllex_destroy(fScanner);
-    layoutlex_destroy(fLayoutScanner);
+    fLexer.start(text, length);
 }
 
 /* (precision | directive | section | declaration)* END_OF_FILE */
@@ -148,53 +120,39 @@
     }
 }
 
-Token Parser::nextRawToken(bool needText) {
-    if (fPushback.fKind != Token::INVALID_TOKEN) {
-        Token result(std::move(fPushback));
-        fPushback.fKind = Token::INVALID_TOKEN;
-        fPushback.fText.clear();
+Token Parser::nextRawToken() {
+    if (fPushback.fKind != Token::INVALID) {
+        Token result = fPushback;
+        fPushback.fKind = Token::INVALID;
         return result;
     }
-    Token::Kind kind = (Token::Kind) sksllex(fScanner);
-    if (!needText) {
-        switch (kind) {
-            case Token::Kind::DIRECTIVE:     // fall through
-            case Token::Kind::IDENTIFIER:    // fall through
-            case Token::Kind::INT_LITERAL:   // fall through
-            case Token::Kind::FLOAT_LITERAL: // fall through
-            case Token::Kind::SECTION:
-                needText = true;
-            default:
-                break;
-        }
-    }
-    static String unavailable("<unavailable>");
-    return Token(Position(skslget_lineno(fScanner), -1), kind,
-                 needText ? String(skslget_text(fScanner)) : unavailable);
+    Token result = fLexer.next();
+    return result;
 }
 
 Token Parser::nextToken() {
-    Token token;
-    do {
-        token = this->nextRawToken(false);
-    } while (token.fKind == Token::WHITESPACE);
+    Token token = this->nextRawToken();
+    while (token.fKind == Token::WHITESPACE || token.fKind == Token::LINE_COMMENT ||
+           token.fKind == Token::BLOCK_COMMENT) {
+        token = this->nextRawToken();
+    }
     return token;
 }
 
 void Parser::pushback(Token t) {
-    ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
+    ASSERT(fPushback.fKind == Token::INVALID);
     fPushback = std::move(t);
 }
 
 Token Parser::peek() {
-    if (fPushback.fKind == Token::INVALID_TOKEN) {
+    if (fPushback.fKind == Token::INVALID) {
         fPushback = this->nextToken();
     }
     return fPushback;
 }
 
 bool Parser::checkNext(Token::Kind kind, Token* result) {
-    if (fPushback.fKind != Token::INVALID_TOKEN && fPushback.fKind != kind) {
+    if (fPushback.fKind != Token::INVALID && fPushback.fKind != kind) {
         return false;
     }
     Token next = this->nextToken();
@@ -216,25 +174,25 @@
         }
         return true;
     } else {
-        if (next.fText.size()) {
-            this->error(next.fPosition, "expected " + String(expected) + ", but found '" +
-                                        next.fText + "'");
-        } else {
-            this->error(next.fPosition, "parse error, recompile in debug mode for details");
-        }
+        this->error(next, "expected " + String(expected) + ", but found '" +
+                    this->text(next) + "'");
         return false;
     }
 }
 
-void Parser::error(Position p, const char* msg) {
-    this->error(p, String(msg));
+StringFragment Parser::text(Token token) {
+    return StringFragment(fText + token.fOffset, token.fLength);
 }
 
-void Parser::error(Position p, String msg) {
-    fErrors.error(p, msg);
+void Parser::error(Token token, String msg) {
+    this->error(token.fOffset, msg);
 }
 
-bool Parser::isType(const String& name) {
+void Parser::error(int offset, String msg) {
+    fErrors.error(offset, msg);
+}
+
+bool Parser::isType(StringFragment name) {
     return nullptr != fTypes[name];
 }
 
@@ -256,8 +214,8 @@
             result = Modifiers::kHighp_Flag;
             break;
         default:
-            this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
-                                     p.fText + "'");
+            this->error(p, "expected 'lowp', 'mediump', or 'highp', but found '" +
+                           this->text(p) + "'");
             return nullptr;
     }
     // FIXME handle the type
@@ -265,7 +223,7 @@
         return nullptr;
     }
     this->expect(Token::SEMICOLON, "';'");
-    return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
+    return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fOffset, result));
 }
 
 /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
@@ -275,16 +233,18 @@
     if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
         return nullptr;
     }
-    if (start.fText == "#version") {
+    StringFragment text = this->text(start);
+    if (text == "#version") {
         this->expect(Token::INT_LITERAL, "a version number");
         Token next = this->peek();
-        if (next.fText == "es" || next.fText == "compatibility") {
+        StringFragment nextText = this->text(next);
+        if (nextText == "es" || nextText == "compatibility") {
             this->nextToken();
         }
         // version is ignored for now; it will eventually become an error when we stop pretending
         // to be GLSL
         return nullptr;
-    } else if (start.fText == "#extension") {
+    } else if (text == "#extension") {
         Token name;
         if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
             return nullptr;
@@ -296,10 +256,10 @@
         if (!this->expect(Token::IDENTIFIER, "an identifier")) {
             return nullptr;
         }
-        return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
-                                                                std::move(name.fText)));
+        return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fOffset,
+                                                                String(this->text(name))));
     } else {
-        this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
+        this->error(start, "unsupported directive '" + this->text(start) + "'");
         return nullptr;
     }
 }
@@ -318,7 +278,7 @@
         if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) {
             return nullptr;
         }
-        argument = argToken.fText;
+        argument = this->text(argToken);
         if (!this->expect(Token::RPAREN, "')'")) {
             return nullptr;
         }
@@ -329,7 +289,7 @@
     String text;
     int level = 1;
     for (;;) {
-        Token next = this->nextRawToken(true);
+        Token next = this->nextRawToken();
         switch (next.fKind) {
             case Token::LBRACE:
                 ++level;
@@ -338,7 +298,7 @@
                 --level;
                 break;
             case Token::END_OF_FILE:
-                this->error(start.fPosition, "reached end of file while parsing section");
+                this->error(start, "reached end of file while parsing section");
                 return nullptr;
             default:
                 break;
@@ -346,10 +306,13 @@
         if (!level) {
             break;
         }
-        text += next.fText;
+        text += this->text(next);
     }
-    return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition,
-                                                          String(start.fText.c_str() + 1),
+    StringFragment name = this->text(start);
+    ++name.fChars;
+    --name.fLength;
+    return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fOffset,
+                                                          String(name),
                                                           argument,
                                                           text));
 }
@@ -359,7 +322,7 @@
 std::unique_ptr<ASTDeclaration> Parser::declaration() {
     Modifiers modifiers = this->modifiers();
     Token lookahead = this->peek();
-    if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
+    if (lookahead.fKind == Token::IDENTIFIER && !this->isType(this->text(lookahead))) {
         // we have an identifier that's not a type, could be the start of an interface block
         return this->interfaceBlock(modifiers);
     }
@@ -403,14 +366,14 @@
                 return nullptr;
             }
         }
-        return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition,
+        return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fOffset,
                                                                modifiers,
                                                                std::move(type),
-                                                               std::move(name.fText),
+                                                               this->text(name),
                                                                std::move(parameters),
                                                                std::move(body)));
     } else {
-        return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
+        return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
     }
 }
 
@@ -425,7 +388,7 @@
     if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
         return nullptr;
     }
-    return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
+    return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
 }
 
 /* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
@@ -450,7 +413,7 @@
             auto type = (const Type*) fTypes[decl->fType->fName];
             for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
                 if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
-                    this->error(decl->fPosition, "array size in struct field must be a constant");
+                    this->error(decl->fOffset, "array size in struct field must be a constant");
                     return nullptr;
                 }
                 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
@@ -460,15 +423,16 @@
             }
             fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
             if (var.fValue) {
-                this->error(decl->fPosition, "initializers are not permitted on struct fields");
+                this->error(decl->fOffset, "initializers are not permitted on struct fields");
             }
         }
     }
     if (!this->expect(Token::RBRACE, "'}'")) {
         return nullptr;
     }
-    fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields)));
-    return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
+    fTypes.add(this->text(name), std::unique_ptr<Type>(new Type(name.fOffset, this->text(name),
+                                                                fields)));
+    return std::unique_ptr<ASTType>(new ASTType(name.fOffset, this->text(name),
                                                 ASTType::kStruct_Kind, std::vector<int>()));
 }
 
@@ -482,11 +446,11 @@
     if (this->checkNext(Token::IDENTIFIER, &name)) {
         std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
                                                                              std::move(type),
-                                                                             std::move(name.fText));
+                                                                             this->text(name));
         if (result) {
             for (const auto& var : result->fVars) {
                 if (var.fValue) {
-                    this->error(var.fValue->fPosition,
+                    this->error(var.fValue->fOffset,
                                 "struct variables cannot be initialized");
                 }
             }
@@ -501,7 +465,7 @@
    (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
 std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
                                                               std::unique_ptr<ASTType> type,
-                                                              String name) {
+                                                              StringFragment name) {
     std::vector<ASTVarDeclaration> vars;
     std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
     while (this->checkNext(Token::LBRACKET)) {
@@ -525,7 +489,7 @@
             return nullptr;
         }
     }
-    vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
+    vars.emplace_back(name, std::move(currentVarSizes), std::move(value));
     while (this->checkNext(Token::COMMA)) {
         Token name;
         if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
@@ -553,7 +517,7 @@
                 return nullptr;
             }
         }
-        vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
+        vars.emplace_back(this->text(name), std::move(currentVarSizes), std::move(value));
     }
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
@@ -580,14 +544,13 @@
         if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
             return nullptr;
         }
-        sizes.push_back(SkSL::stoi(sizeToken.fText));
+        sizes.push_back(SkSL::stoi(this->text(sizeToken)));
         if (!this->expect(Token::RBRACKET, "']'")) {
             return nullptr;
         }
     }
-    return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
-                                                          std::move(type), name.fText,
-                                                          std::move(sizes)));
+    return std::unique_ptr<ASTParameter>(new ASTParameter(name.fOffset, modifiers, std::move(type),
+                                                          this->text(name), std::move(sizes)));
 }
 
 /** (EQ INT_LITERAL)? */
@@ -597,7 +560,7 @@
     }
     Token resultToken;
     if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
-        return SkSL::stoi(resultToken.fText);
+        return SkSL::stoi(this->text(resultToken));
     }
     return -1;
 }
@@ -607,13 +570,13 @@
     if (!this->expect(Token::EQ, "'='")) {
         return "";
     }
-    Token start = this->nextRawToken(true);
+    Token start = this->nextRawToken();
     this->pushback(start);
     String code;
     int level = 1;
     bool done = false;
     while (!done) {
-        Token next = this->nextRawToken(true);
+        Token next = this->nextRawToken();
         switch (next.fKind) {
             case Token::LPAREN:
                 ++level;
@@ -627,7 +590,7 @@
                 }
                 break;
             case Token::END_OF_FILE:
-                this->error(start.fPosition, "reached end of file while parsing layout");
+                this->error(start, "reached end of file while parsing layout");
                 return nullptr;
             default:
                 break;
@@ -639,7 +602,7 @@
             this->pushback(std::move(next));
         }
         else {
-            code += next.fText;
+            code += this->text(next);
         }
     }
     return code;
@@ -651,10 +614,10 @@
         this->expect(Token::EQ, "'='");
         Token key;
         if (this->expect(Token::IDENTIFIER, "an identifer", &key)) {
-            if (key.fText == "identity") {
+            if (this->text(key) == "identity") {
                 return Layout::kIdentity_Key;
             } else {
-                this->error(key.fPosition, "unsupported layout key");
+                this->error(key, "unsupported layout key");
             }
         }
     }
@@ -688,84 +651,84 @@
         }
         for (;;) {
             Token t = this->nextToken();
-            YY_BUFFER_STATE buffer;
-            buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner);
-            int token = layoutlex(fLayoutScanner);
-            layout_delete_buffer(buffer, fLayoutScanner);
-            if (token != Token::INVALID_TOKEN) {
+            String text = this->text(t);
+            fLayoutLexer.start(text.c_str(), text.size());
+            int token = fLayoutLexer.next().fKind;
+            if (token != LayoutToken::INVALID) {
                 switch (token) {
-                    case Token::LOCATION:
+                    case LayoutToken::LOCATION:
                         location = this->layoutInt();
                         break;
-                    case Token::OFFSET:
+                    case LayoutToken::OFFSET:
                         offset = this->layoutInt();
                         break;
-                    case Token::BINDING:
+                    case LayoutToken::BINDING:
                         binding = this->layoutInt();
                         break;
-                    case Token::INDEX:
+                    case LayoutToken::INDEX:
                         index = this->layoutInt();
                         break;
-                    case Token::SET:
+                    case LayoutToken::SET:
                         set = this->layoutInt();
                         break;
-                    case Token::BUILTIN:
+                    case LayoutToken::BUILTIN:
                         builtin = this->layoutInt();
                         break;
-                    case Token::INPUT_ATTACHMENT_INDEX:
+                    case LayoutToken::INPUT_ATTACHMENT_INDEX:
                         inputAttachmentIndex = this->layoutInt();
                         break;
-                    case Token::ORIGIN_UPPER_LEFT:
+                    case LayoutToken::ORIGIN_UPPER_LEFT:
                         originUpperLeft = true;
                         break;
-                    case Token::OVERRIDE_COVERAGE:
+                    case LayoutToken::OVERRIDE_COVERAGE:
                         overrideCoverage = true;
                         break;
-                    case Token::BLEND_SUPPORT_ALL_EQUATIONS:
+                    case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
                         blendSupportAllEquations = true;
                         break;
-                    case Token::PUSH_CONSTANT:
+                    case LayoutToken::PUSH_CONSTANT:
                         pushConstant = true;
                         break;
-                    case Token::POINTS:
+                    case LayoutToken::POINTS:
                         primitive = Layout::kPoints_Primitive;
                         break;
-                    case Token::LINES:
+                    case LayoutToken::LINES:
                         primitive = Layout::kLines_Primitive;
                         break;
-                    case Token::LINE_STRIP:
+                    case LayoutToken::LINE_STRIP:
                         primitive = Layout::kLineStrip_Primitive;
                         break;
-                    case Token::LINES_ADJACENCY:
+                    case LayoutToken::LINES_ADJACENCY:
                         primitive = Layout::kLinesAdjacency_Primitive;
                         break;
-                    case Token::TRIANGLES:
+                    case LayoutToken::TRIANGLES:
                         primitive = Layout::kTriangles_Primitive;
                         break;
-                    case Token::TRIANGLE_STRIP:
+                    case LayoutToken::TRIANGLE_STRIP:
                         primitive = Layout::kTriangleStrip_Primitive;
                         break;
-                    case Token::TRIANGLES_ADJACENCY:
+                    case LayoutToken::TRIANGLES_ADJACENCY:
                         primitive = Layout::kTrianglesAdjacency_Primitive;
                         break;
-                    case Token::MAX_VERTICES:
+                    case LayoutToken::MAX_VERTICES:
                         maxVertices = this->layoutInt();
                         break;
-                    case Token::INVOCATIONS:
+                    case LayoutToken::INVOCATIONS:
                         invocations = this->layoutInt();
                         break;
-                    case Token::WHEN:
+                    case LayoutToken::WHEN:
                         when = this->layoutCode();
                         break;
-                    case Token::KEY:
+                    case LayoutToken::KEY:
                         key = this->layoutKey();
                         break;
+                    default:
+                        ASSERT(false);
                 }
-            } else if (Layout::ReadFormat(t.fText, &format)) {
+            } else if (Layout::ReadFormat(this->text(t), &format)) {
                // AST::ReadFormat stored the result in 'format'.
             } else {
-                this->error(t.fPosition, ("'" + t.fText +
-                                          "' is not a valid layout qualifier").c_str());
+                this->error(t, ("'" + this->text(t) + "' is not a valid layout qualifier").c_str());
             }
             if (this->checkNext(Token::RPAREN)) {
                 break;
@@ -899,7 +862,7 @@
             return this->block();
         case Token::SEMICOLON:
             this->nextToken();
-            return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
+            return std::unique_ptr<ASTStatement>(new ASTBlock(start.fOffset,
                                                      std::vector<std::unique_ptr<ASTStatement>>()));
         case Token::CONST:   // fall through
         case Token::HIGHP:   // fall through
@@ -912,7 +875,7 @@
             return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
         }
         case Token::IDENTIFIER:
-            if (this->isType(start.fText)) {
+            if (this->isType(this->text(start))) {
                 auto decl = this->varDeclarations();
                 if (!decl) {
                     return nullptr;
@@ -932,8 +895,8 @@
     if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
         return nullptr;
     }
-    if (!this->isType(type.fText)) {
-        this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
+    if (!this->isType(this->text(type))) {
+        this->error(type, ("no type named '" + this->text(type) + "'").c_str());
         return nullptr;
     }
     std::vector<int> sizes;
@@ -950,7 +913,7 @@
         }
         this->expect(Token::RBRACKET, "']'");
     }
-    return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
+    return std::unique_ptr<ASTType>(new ASTType(type.fOffset, this->text(type),
                                                 ASTType::kIdentifier_Kind, sizes));
 }
 
@@ -964,7 +927,7 @@
         // we only get into interfaceBlock if we found a top-level identifier which was not a type.
         // 99% of the time, the user was not actually intending to create an interface block, so
         // it's better to report it as an unknown type
-        this->error(name.fPosition, "no type named '" + name.fText + "'");
+        this->error(name, "no type named '" + this->text(name) + "'");
         return nullptr;
     }
     this->nextToken();
@@ -978,8 +941,9 @@
     }
     this->nextToken();
     std::vector<std::unique_ptr<ASTExpression>> sizes;
-    Token instanceName;
-    if (this->checkNext(Token::IDENTIFIER, &instanceName)) {
+    StringFragment instanceName;
+    Token instanceNameToken;
+    if (this->checkNext(Token::IDENTIFIER, &instanceNameToken)) {
         while (this->checkNext(Token::LBRACKET)) {
             if (this->peek().fKind != Token::RBRACKET) {
                 std::unique_ptr<ASTExpression> size = this->expression();
@@ -992,12 +956,13 @@
             }
             this->expect(Token::RBRACKET, "']'");
         }
+        instanceName = this->text(instanceNameToken);
     }
     this->expect(Token::SEMICOLON, "';'");
-    return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
-                                                                 std::move(name.fText),
+    return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fOffset, mods,
+                                                                 this->text(name),
                                                                  std::move(decls),
-                                                                 std::move(instanceName.fText),
+                                                                 instanceName,
                                                                  std::move(sizes)));
 }
 
@@ -1029,7 +994,7 @@
             return nullptr;
         }
     }
-    return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition,
+    return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fOffset,
                                                               isStatic,
                                                               std::move(test),
                                                               std::move(ifTrue),
@@ -1062,7 +1027,7 @@
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
+    return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fOffset,
                                                               std::move(statement),
                                                               std::move(test)));
 }
@@ -1087,7 +1052,7 @@
     if (!statement) {
         return nullptr;
     }
-    return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
+    return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fOffset,
                                                                     std::move(test),
                                                                     std::move(statement)));
 }
@@ -1114,7 +1079,7 @@
         }
         statements.push_back(std::move(s));
     }
-    return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
+    return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fOffset, std::move(value),
                                                             std::move(statements)));
 }
 
@@ -1162,13 +1127,13 @@
             }
             statements.push_back(std::move(s));
         }
-        cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
+        cases.emplace_back(new ASTSwitchCase(defaultStart.fOffset, nullptr,
                                              std::move(statements)));
     }
     if (!this->expect(Token::RBRACE, "'}'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
+    return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fOffset,
                                                                 isStatic,
                                                                 std::move(value),
                                                                 std::move(cases)));
@@ -1200,7 +1165,7 @@
             break;
         }
         case Token::IDENTIFIER: {
-            if (this->isType(nextToken.fText)) {
+            if (this->isType(this->text(nextToken))) {
                 std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
                 if (!vd) {
                     return nullptr;
@@ -1237,7 +1202,7 @@
     if (!statement) {
         return nullptr;
     }
-    return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
+    return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fOffset,
                                                                 std::move(initializer),
                                                                 std::move(test), std::move(next),
                                                                 std::move(statement)));
@@ -1259,7 +1224,7 @@
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
+    return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fOffset,
                                                                       std::move(expression)));
 }
 
@@ -1272,7 +1237,7 @@
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
+    return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fOffset));
 }
 
 /* CONTINUE SEMICOLON */
@@ -1284,7 +1249,7 @@
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
+    return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fOffset));
 }
 
 /* DISCARD SEMICOLON */
@@ -1296,7 +1261,7 @@
     if (!this->expect(Token::SEMICOLON, "';'")) {
         return nullptr;
     }
-    return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
+    return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fOffset));
 }
 
 /* LBRACE statement* RBRACE */
@@ -1314,10 +1279,10 @@
         switch (this->peek().fKind) {
             case Token::RBRACE:
                 this->nextToken();
-                return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
+                return std::unique_ptr<ASTBlock>(new ASTBlock(start.fOffset,
                                                               std::move(statements)));
             case Token::END_OF_FILE:
-                this->error(this->peek().fPosition, "expected '}', but found end of file");
+                this->error(this->peek(), "expected '}', but found end of file");
                 return nullptr;
             default: {
                 std::unique_ptr<ASTStatement> statement = this->statement();
@@ -1714,7 +1679,7 @@
     switch (next.fKind) {
         case Token::LBRACKET: {
             if (this->checkNext(Token::RBRACKET)) {
-                return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
+                return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fOffset));
             }
             std::unique_ptr<ASTExpression> e = this->expression();
             if (!e) {
@@ -1724,10 +1689,10 @@
             return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
         }
         case Token::DOT: {
-            Position pos = this->peek().fPosition;
-            String text;
+            int offset = this->peek().fOffset;
+            StringFragment text;
             if (this->identifier(&text)) {
-                return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
+                return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(offset, std::move(text)));
             }
             return nullptr;
         }
@@ -1746,17 +1711,17 @@
                 }
             }
             this->expect(Token::RPAREN, "')' to complete function parameters");
-            return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
+            return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fOffset,
                                                                 std::move(parameters)));
         }
         case Token::PLUSPLUS:
-            return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
+            return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
                                                             ASTSuffix::kPostIncrement_Kind));
         case Token::MINUSMINUS:
-            return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
+            return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
                                                             ASTSuffix::kPostDecrement_Kind));
         default: {
-            this->error(next.fPosition,  "expected expression suffix, but found '" + next.fText +
+            this->error(next,  "expected expression suffix, but found '" + this->text(next) +
                                          "'\n");
             return nullptr;
         }
@@ -1769,23 +1734,23 @@
     Token t = this->peek();
     switch (t.fKind) {
         case Token::IDENTIFIER: {
-            String text;
+            StringFragment text;
             if (this->identifier(&text)) {
-                result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
+                result.reset(new ASTIdentifier(t.fOffset, std::move(text)));
             }
             break;
         }
         case Token::INT_LITERAL: {
             int64_t i;
             if (this->intLiteral(&i)) {
-                result.reset(new ASTIntLiteral(t.fPosition, i));
+                result.reset(new ASTIntLiteral(t.fOffset, i));
             }
             break;
         }
         case Token::FLOAT_LITERAL: {
             double f;
             if (this->floatLiteral(&f)) {
-                result.reset(new ASTFloatLiteral(t.fPosition, f));
+                result.reset(new ASTFloatLiteral(t.fOffset, f));
             }
             break;
         }
@@ -1793,7 +1758,7 @@
         case Token::FALSE_LITERAL: {
             bool b;
             if (this->boolLiteral(&b)) {
-                result.reset(new ASTBoolLiteral(t.fPosition, b));
+                result.reset(new ASTBoolLiteral(t.fOffset, b));
             }
             break;
         }
@@ -1807,7 +1772,7 @@
         }
         default:
             this->nextToken();
-            this->error(t.fPosition,  "expected expression, but found '" + t.fText + "'\n");
+            this->error(t.fOffset,  "expected expression, but found '" + this->text(t) + "'\n");
             result = nullptr;
     }
     return result;
@@ -1817,7 +1782,7 @@
 bool Parser::intLiteral(int64_t* dest) {
     Token t;
     if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
-        *dest = SkSL::stol(t.fText);
+        *dest = SkSL::stol(this->text(t));
         return true;
     }
     return false;
@@ -1827,7 +1792,7 @@
 bool Parser::floatLiteral(double* dest) {
     Token t;
     if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
-        *dest = SkSL::stod(t.fText);
+        *dest = SkSL::stod(this->text(t));
         return true;
     }
     return false;
@@ -1844,16 +1809,16 @@
             *dest = false;
             return true;
         default:
-            this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
+            this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'\n");
             return false;
     }
 }
 
 /* IDENTIFIER */
-bool Parser::identifier(String* dest) {
+bool Parser::identifier(StringFragment* dest) {
     Token t;
     if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
-        *dest = std::move(t.fText);
+        *dest = this->text(t);
         return true;
     }
     return false;
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 4edd8e4..5391f6c 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -14,7 +14,8 @@
 #include <unordered_set>
 #include "SkSLErrorReporter.h"
 #include "ir/SkSLLayout.h"
-#include "SkSLToken.h"
+#include "SkSLLexer.h"
+#include "SkSLLayoutLexer.h"
 
 struct yy_buffer_state;
 #define YY_TYPEDEF_YY_BUFFER_STATE
@@ -51,9 +52,7 @@
  */
 class Parser {
 public:
-    Parser(String text, SymbolTable& types, ErrorReporter& errors);
-
-    ~Parser();
+    Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors);
 
     /**
      * Consumes a complete .sksl file and produces a list of declarations. Errors are reported via
@@ -62,13 +61,15 @@
      */
     std::vector<std::unique_ptr<ASTDeclaration>> file();
 
+    StringFragment text(Token token);
+
+    Position position(Token token);
+
 private:
     /**
-     * Return the next token, including whitespace tokens, from the parse stream. If needText is
-     * false, the token's text is only filled in if it is a token with variable text (identifiers,
-     * numbers, etc.).
+     * Return the next token, including whitespace tokens, from the parse stream.
      */
-    Token nextRawToken(bool needText);
+    Token nextRawToken();
 
     /**
      * Return the next non-whitespace token from the parse stream.
@@ -103,15 +104,15 @@
      * Returns true if the read token was as expected, false otherwise.
      */
     bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
+    bool expect(Token::Kind kind, String expected, Token* result = nullptr);
 
-    void error(Position p, const char* msg);
-    void error(Position p, String msg);
-
+    void error(Token token, String msg);
+    void error(int offset, String msg);
     /**
      * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
      * always return true.
      */
-    bool isType(const String& name);
+    bool isType(StringFragment name);
 
     // these functions parse individual grammar rules from the current parse position; you probably
     // don't need to call any of these outside of the parser. The function declarations in the .cpp
@@ -133,7 +134,7 @@
 
     std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers,
                                                           std::unique_ptr<ASTType> type,
-                                                          String name);
+                                                          StringFragment name);
 
     std::unique_ptr<ASTParameter> parameter();
 
@@ -223,10 +224,11 @@
 
     bool boolLiteral(bool* dest);
 
-    bool identifier(String* dest);
+    bool identifier(StringFragment* dest);
 
-    void* fScanner;
-    void* fLayoutScanner;
+    const char* fText;
+    Lexer fLexer;
+    LayoutLexer fLayoutLexer;
     YY_BUFFER_STATE fBuffer;
     // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
     // stack on pathological inputs
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index d367df9..7ae3252 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -850,8 +850,7 @@
     this->writeWord(word1, out);
 }
 
-void SPIRVCodeGenerator::writeString(const char* string, OutputStream& out) {
-    size_t length = strlen(string);
+void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputStream& out) {
     out.write(string, length);
     switch (length % 4) {
         case 1:
@@ -868,28 +867,25 @@
     }
 }
 
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out) {
-    int32_t length = (int32_t) strlen(string);
-    this->writeOpCode(opCode, 1 + (length + 4) / 4, out);
-    this->writeString(string, out);
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out) {
+    this->writeOpCode(opCode, 1 + (string.fLength + 4) / 4, out);
+    this->writeString(string.fChars, string.fLength, out);
 }
 
 
-void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string,
+void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string,
                                           OutputStream& out) {
-    int32_t length = (int32_t) strlen(string);
-    this->writeOpCode(opCode, 2 + (length + 4) / 4, out);
+    this->writeOpCode(opCode, 2 + (string.fLength + 4) / 4, out);
     this->writeWord(word1, out);
-    this->writeString(string, out);
+    this->writeString(string.fChars, string.fLength, out);
 }
 
 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
-                                          const char* string, OutputStream& out) {
-    int32_t length = (int32_t) strlen(string);
-    this->writeOpCode(opCode, 3 + (length + 4) / 4, out);
+                                          StringFragment string, OutputStream& out) {
+    this->writeOpCode(opCode, 3 + (string.fLength + 4) / 4, out);
     this->writeWord(word1, out);
     this->writeWord(word2, out);
-    this->writeString(string, out);
+    this->writeString(string.fChars, string.fLength, out);
 }
 
 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
@@ -1003,12 +999,12 @@
         const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout;
         if (fieldLayout.fOffset >= 0) {
             if (fieldLayout.fOffset < (int) offset) {
-                fErrors.error(type.fPosition,
+                fErrors.error(type.fOffset,
                               "offset of field '" + type.fields()[i].fName + "' must be at "
                               "least " + to_string((int) offset));
             }
             if (fieldLayout.fOffset % alignment) {
-                fErrors.error(type.fPosition,
+                fErrors.error(type.fOffset,
                               "offset of field '" + type.fields()[i].fName + "' must be a multiple"
                               " of " + to_string((int) alignment));
             }
@@ -1019,8 +1015,7 @@
                 offset += alignment - mod;
             }
         }
-        this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(),
-                               fNameBuffer);
+        this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName, fNameBuffer);
         this->writeLayout(fieldLayout, resultId, i);
         if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) {
             this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset,
@@ -1081,7 +1076,7 @@
                 break;
             case Type::kArray_Kind: {
                 if (type.columns() > 0) {
-                    IntLiteral count(fContext, Position(), type.columns());
+                    IntLiteral count(fContext, -1, type.columns());
                     this->writeInstruction(SpvOpTypeArray, result,
                                            this->getType(type.componentType(), layout),
                                            this->writeIntLiteral(count), fConstantBuffer);
@@ -1331,9 +1326,9 @@
         case kSubpassLoad_SpecialIntrinsic: {
             SpvId img = this->writeExpression(*c.fArguments[0], out);
             std::vector<std::unique_ptr<Expression>> args;
-            args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
-            args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
-            Constructor ctor(Position(), *fContext.fFloat2_Type, std::move(args));
+            args.emplace_back(new FloatLiteral(fContext, -1, 0.0));
+            args.emplace_back(new FloatLiteral(fContext, -1, 0.0));
+            Constructor ctor(-1, *fContext.fFloat2_Type, std::move(args));
             SpvId coords = this->writeConstantVector(ctor);
             if (1 == c.fArguments.size()) {
                 this->writeInstruction(SpvOpImageRead,
@@ -1566,7 +1561,7 @@
 
 void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type,
                                                  OutputStream& out) {
-    FloatLiteral zero(fContext, Position(), 0);
+    FloatLiteral zero(fContext, -1, 0);
     SpvId zeroId = this->writeFloatLiteral(zero);
     std::vector<SpvId> columnIds;
     for (int column = 0; column < type.columns(); column++) {
@@ -1603,10 +1598,10 @@
                                                                            1));
     SpvId zeroId;
     if (dstType.componentType() == *fContext.fFloat_Type) {
-        FloatLiteral zero(fContext, Position(), 0.0);
+        FloatLiteral zero(fContext, -1, 0.0);
         zeroId = this->writeFloatLiteral(zero);
     } else if (dstType.componentType() == *fContext.fInt_Type) {
-        IntLiteral zero(fContext, Position(), 0);
+        IntLiteral zero(fContext, -1, 0);
         zeroId = this->writeIntLiteral(zero);
     } else {
         ABORT("unsupported matrix component type");
@@ -1864,7 +1859,7 @@
         case Expression::kFieldAccess_Kind: {
             FieldAccess& fieldExpr = (FieldAccess&) expr;
             chain = this->getAccessChain(*fieldExpr.fBase, out);
-            IntLiteral index(fContext, Position(), fieldExpr.fFieldIndex);
+            IntLiteral index(fContext, -1, fieldExpr.fFieldIndex);
             chain.push_back(this->writeIntLiteral(index));
             break;
         }
@@ -2010,7 +2005,7 @@
             SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer();
             ASSERT(base);
             if (count == 1) {
-                IntLiteral index(fContext, Position(), swizzle.fComponents[0]);
+                IntLiteral index(fContext, -1, swizzle.fComponents[0]);
                 SpvId member = this->nextId();
                 this->writeInstruction(SpvOpAccessChain,
                                        this->getPointerType(swizzle.fType,
@@ -2064,20 +2059,19 @@
             std::shared_ptr<SymbolTable> st(new SymbolTable(&fErrors));
             ASSERT(fRTHeightFieldIndex == (SpvId) -1);
             std::vector<Type::Field> fields;
-            fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME),
-                                fContext.fFloat_Type.get());
-            String name("sksl_synthetic_uniforms");
-            Type intfStruct(Position(), name, fields);
+            fields.emplace_back(Modifiers(), SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get());
+            StringFragment name("sksl_synthetic_uniforms");
+            Type intfStruct(-1, name, fields);
             Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false,
                           Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1,
                           -1, "", Layout::kNo_Key);
-            Variable* intfVar = new Variable(Position(),
+            Variable* intfVar = new Variable(-1,
                                              Modifiers(layout, Modifiers::kUniform_Flag),
                                              name,
                                              intfStruct,
                                              Variable::kGlobal_Storage);
             fSynthetics.takeOwnership(intfVar);
-            InterfaceBlock intf(Position(), intfVar, name, String(""),
+            InterfaceBlock intf(-1, intfVar, name, String(""),
                                 std::vector<std::unique_ptr<Expression>>(), st);
             fRTHeightStructId = this->writeInterfaceBlock(intf);
             fRTHeightFieldIndex = 0;
@@ -2087,7 +2081,7 @@
         SpvId xId = this->nextId();
         this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId,
                                result, 0, out);
-        IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex);
+        IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex);
         SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
         SpvId heightPtr = this->nextId();
         this->writeOpCode(SpvOpAccessChain, 5, out);
@@ -2104,9 +2098,9 @@
         SpvId flippedYId = this->nextId();
         this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId,
                                heightRead, rawYId, out);
-        FloatLiteral zero(fContext, Position(), 0.0);
+        FloatLiteral zero(fContext, -1, 0.0);
         SpvId zeroId = writeFloatLiteral(zero);
-        FloatLiteral one(fContext, Position(), 1.0);
+        FloatLiteral one(fContext, -1, 1.0);
         SpvId oneId = writeFloatLiteral(one);
         SpvId flipped = this->nextId();
         this->writeOpCode(SpvOpCompositeConstruct, 7, out);
@@ -2509,7 +2503,7 @@
 
 SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) {
     ASSERT(a.fOperator == Token::LOGICALAND);
-    BoolLiteral falseLiteral(fContext, Position(), false);
+    BoolLiteral falseLiteral(fContext, -1, false);
     SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
     SpvId lhs = this->writeExpression(*a.fLeft, out);
     SpvId rhsLabel = this->nextId();
@@ -2530,7 +2524,7 @@
 
 SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) {
     ASSERT(o.fOperator == Token::LOGICALOR);
-    BoolLiteral trueLiteral(fContext, Position(), true);
+    BoolLiteral trueLiteral(fContext, -1, true);
     SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
     SpvId lhs = this->writeExpression(*o.fLeft, out);
     SpvId rhsLabel = this->nextId();
@@ -2584,10 +2578,10 @@
 
 std::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) {
     if (type == *context.fInt_Type) {
-        return std::unique_ptr<Expression>(new IntLiteral(context, Position(), 1));
+        return std::unique_ptr<Expression>(new IntLiteral(context, -1, 1));
     }
     else if (type == *context.fFloat_Type) {
-        return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0));
+        return std::unique_ptr<Expression>(new FloatLiteral(context, -1, 1.0));
     } else {
         ABORT("math is unsupported on type '%s'", type.name().c_str());
     }
@@ -2747,7 +2741,7 @@
     SpvId result = fFunctionMap[&f];
     this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result,
                            SpvFunctionControlMaskNone, this->getFunctionType(f), out);
-    this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer);
+    this->writeInstruction(SpvOpName, result, f.fName, fNameBuffer);
     for (size_t i = 0; i < f.fParameters.size(); i++) {
         SpvId id = this->nextId();
         fVariableMap[f.fParameters[i]] = id;
@@ -2844,8 +2838,8 @@
         std::vector<Type::Field> fields = type->fields();
         fRTHeightStructId = result;
         fRTHeightFieldIndex = fields.size();
-        fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get());
-        type = new Type(type->fPosition, type->name(), fields);
+        fields.emplace_back(Modifiers(), StringFragment(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get());
+        type = new Type(type->fOffset, type->name(), fields);
     }
     SpvId typeId = this->getType(*type, layout);
     if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) {
@@ -2922,7 +2916,7 @@
         fVariableMap[var] = id;
         SpvId type = this->getPointerType(var->fType, storageClass);
         this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer);
-        this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer);
+        this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer);
         this->writePrecisionModifier(var->fModifiers, id);
         if (varDecl.fValue) {
             ASSERT(!fCurrentBlock);
@@ -2958,7 +2952,7 @@
         fVariableMap[var] = id;
         SpvId type = this->getPointerType(var->fType, SpvStorageClassFunction);
         this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer);
-        this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer);
+        this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer);
         if (varDecl.fValue) {
             SpvId value = this->writeExpression(*varDecl.fValue, out);
             this->writeInstruction(SpvOpStore, id, value, out);
@@ -3086,7 +3080,7 @@
     // the time being, we just fail with an error due to the lack of testing. If you encounter this
     // message, simply remove the error call below to see whether our while loop support actually
     // works.
-    fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, "
+    fErrors.error(w.fOffset, "internal error: while loop support has been disabled in SPIR-V, "
                   "see SkSLSPIRVCodeGenerator.cpp for details");
 
     SpvId header = this->nextId();
@@ -3118,7 +3112,7 @@
     // the time being, we just fail with an error due to the lack of testing. If you encounter this
     // message, simply remove the error call below to see whether our do loop support actually
     // works.
-    fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see "
+    fErrors.error(d.fOffset, "internal error: do loop support has been disabled in SPIR-V, see "
                   "SkSLSPIRVCodeGenerator.cpp for details");
 
     SpvId header = this->nextId();
@@ -3268,7 +3262,7 @@
     this->writeCapabilities(out);
     this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out);
     this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out);
-    this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) +
+    this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->fName.fLength + 4) / 4) +
                       (int32_t) interfaceVars.size(), out);
     switch (program.fKind) {
         case Program::kVertex_Kind:
@@ -3285,7 +3279,7 @@
     }
     SpvId entryPoint = fFunctionMap[main];
     this->writeWord(entryPoint, out);
-    this->writeString(main->fName.c_str(), out);
+    this->writeString(main->fName.fChars, main->fName.fLength, out);
     for (int var : interfaceVars) {
         this->writeWord(var, out);
     }
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index a532c9a..eb6ec40 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -241,19 +241,19 @@
 
     void writeWord(int32_t word, OutputStream& out);
 
-    void writeString(const char* string, OutputStream& out);
+    void writeString(const char* string, size_t length, OutputStream& out);
 
     void writeLabel(SpvId id, OutputStream& out);
 
     void writeInstruction(SpvOp_ opCode, OutputStream& out);
 
-    void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out);
+    void writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out);
 
     void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out);
 
-    void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out);
+    void writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string, OutputStream& out);
 
-    void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
+    void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, StringFragment string,
                           OutputStream& out);
 
     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out);
diff --git a/src/sksl/SkSLSectionAndParameterHelper.h b/src/sksl/SkSLSectionAndParameterHelper.h
index f70b82c..fccfff4 100644
--- a/src/sksl/SkSLSectionAndParameterHelper.h
+++ b/src/sksl/SkSLSectionAndParameterHelper.h
@@ -56,21 +56,21 @@
                     if (IsSupportedSection(s->fName.c_str())) {
                         if (SectionAcceptsArgument(s->fName.c_str())) {
                             if (!s->fArgument.size()) {
-                                errors.error(s->fPosition,
+                                errors.error(s->fOffset,
                                              ("section '@" + s->fName +
                                               "' requires one parameter").c_str());
                             }
                         } else if (s->fArgument.size()) {
-                            errors.error(s->fPosition,
+                            errors.error(s->fOffset,
                                          ("section '@" + s->fName + "' has no parameters").c_str());
                         }
                     } else {
-                        errors.error(s->fPosition,
+                        errors.error(s->fOffset,
                                      ("unsupported section '@" + s->fName + "'").c_str());
                     }
                     if (!SectionPermitsDuplicates(s->fName.c_str()) &&
                             fSections.find(s->fName) != fSections.end()) {
-                        errors.error(s->fPosition,
+                        errors.error(s->fOffset,
                                      ("duplicate section '@" + s->fName + "'").c_str());
                     }
                     fSections[s->fName].push_back(s);
diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp
index ac6d7f8..2bbb772 100644
--- a/src/sksl/SkSLString.cpp
+++ b/src/sksl/SkSLString.cpp
@@ -77,6 +77,32 @@
     return result;
 }
 
+String String::operator+(StringFragment s) const {
+    String result(*this);
+    result.append(s.fChars, s.fLength);
+    return result;
+}
+
+String& String::operator+=(char c) {
+    INHERITED::operator+=(c);
+    return *this;
+}
+
+String& String::operator+=(const char* s) {
+    INHERITED::operator+=(s);
+    return *this;
+}
+
+String& String::operator+=(const String& s) {
+    INHERITED::operator+=(s);
+    return *this;
+}
+
+String& String::operator+=(StringFragment s) {
+    this->append(s.fChars, s.fLength);
+    return *this;
+}
+
 bool String::operator==(const String& s) const {
     return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
 }
@@ -107,6 +133,28 @@
     return s2 != s1;
 }
 
+bool StringFragment::operator==(StringFragment s) const {
+    if (fLength != s.fLength) {
+        return false;
+    }
+    return !memcmp(fChars, s.fChars, fLength);
+}
+
+bool StringFragment::operator!=(StringFragment s) const {
+    if (fLength != s.fLength) {
+        return true;
+    }
+    return memcmp(fChars, s.fChars, fLength);
+}
+
+bool StringFragment::operator==(const char* s) const {
+    return !strncmp(fChars, s, fLength);
+}
+
+bool StringFragment::operator!=(const char* s) const {
+    return strncmp(fChars, s, fLength);
+}
+
 String to_string(int32_t value) {
     return SkSL::String::printf("%d", value);
 }
diff --git a/src/sksl/SkSLString.h b/src/sksl/SkSLString.h
index 93bd7a5..9cfdce4 100644
--- a/src/sksl/SkSLString.h
+++ b/src/sksl/SkSLString.h
@@ -8,6 +8,8 @@
 #ifndef SKSL_STRING
 #define SKSL_STRING
 
+#include <cstring>
+
 #define SKSL_USE_STD_STRING
 
 #include <stdarg.h>
@@ -22,6 +24,33 @@
 
 namespace SkSL {
 
+// Represents a (not necessarily null-terminated) slice of a string.
+struct StringFragment {
+    StringFragment()
+    : fChars(nullptr)
+    , fLength(0) {}
+
+    StringFragment(const char* chars)
+    : fChars(chars)
+    , fLength(strlen(chars)) {}
+
+    StringFragment(const char* chars, size_t length)
+    : fChars(chars)
+    , fLength(length) {}
+
+    char operator[](size_t idx) const {
+        return fChars[idx];
+    }
+
+    bool operator==(const char* s) const;
+    bool operator!=(const char* s) const;
+    bool operator==(StringFragment s) const;
+    bool operator!=(StringFragment s) const;
+
+    const char* fChars;
+    size_t fLength;
+};
+
 class String : public SKSL_STRING_BASE {
 public:
     String() = default;
@@ -41,6 +70,9 @@
     String(const char* s, size_t size)
     : INHERITED(s, size) {}
 
+    String(StringFragment s)
+    : INHERITED(s.fChars, s.fLength) {}
+
     static String printf(const char* fmt, ...);
 
 #ifdef SKSL_USE_STD_STRING
@@ -53,6 +85,11 @@
 
     String operator+(const char* s) const;
     String operator+(const String& s) const;
+    String operator+(StringFragment s) const;
+    String& operator+=(char c);
+    String& operator+=(const char* s);
+    String& operator+=(const String& s);
+    String& operator+=(StringFragment s);
     bool operator==(const char* s) const;
     bool operator!=(const char* s) const;
     bool operator==(const String& s) const;
@@ -86,6 +123,18 @@
 
 } // namespace
 
+namespace std {
+    template<> struct hash<SkSL::StringFragment> {
+        size_t operator()(const SkSL::StringFragment& s) const {
+            size_t result = 0;
+            for (size_t i = 0; i < s.fLength; ++i) {
+                result = result * 101 + s.fChars[i];
+            }
+            return result;
+        }
+    };
+} // namespace
+
 #ifdef SKSL_USE_STD_STRING
 namespace std {
     template<> struct hash<SkSL::String> {
diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h
deleted file mode 100644
index 2857a82..0000000
--- a/src/sksl/SkSLToken.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_TOKEN
-#define SKSL_TOKEN
-
-#include "SkSLPosition.h"
-#include "SkSLUtil.h"
-
-namespace SkSL {
-
-#undef IN
-#undef OUT
-#undef CONST
-
-/**
- * Represents a lexical analysis token. Token is generally only used during the parse process, but
- * Token::Kind is also used to represent operator kinds.
- */
-struct Token {
-    enum Kind {
-        END_OF_FILE,
-        WHITESPACE,
-        IDENTIFIER,
-        INT_LITERAL,
-        FLOAT_LITERAL,
-        TRUE_LITERAL,
-        FALSE_LITERAL,
-        LPAREN,
-        RPAREN,
-        LBRACE,
-        RBRACE,
-        LBRACKET,
-        RBRACKET,
-        DOT,
-        COMMA,
-        PLUSPLUS,
-        MINUSMINUS,
-        PLUS,
-        MINUS,
-        STAR,
-        SLASH,
-        PERCENT,
-        SHL,
-        SHR,
-        BITWISEOR,
-        BITWISEXOR,
-        BITWISEAND,
-        BITWISENOT,
-        LOGICALOR,
-        LOGICALXOR,
-        LOGICALAND,
-        LOGICALNOT,
-        QUESTION,
-        COLON,
-        EQ,
-        EQEQ,
-        NEQ,
-        GT,
-        LT,
-        GTEQ,
-        LTEQ,
-        PLUSEQ,
-        MINUSEQ,
-        STAREQ,
-        SLASHEQ,
-        PERCENTEQ,
-        SHLEQ,
-        SHREQ,
-        BITWISEOREQ,
-        BITWISEXOREQ,
-        BITWISEANDEQ,
-        LOGICALOREQ,
-        LOGICALXOREQ,
-        LOGICALANDEQ,
-        SEMICOLON,
-        ARROW,
-        COLONCOLON,
-        IF,
-        STATIC_IF,
-        ELSE,
-        FOR,
-        WHILE,
-        DO,
-        SWITCH,
-        STATIC_SWITCH,
-        CASE,
-        DEFAULT,
-        RETURN,
-        BREAK,
-        CONTINUE,
-        DISCARD,
-        IN,
-        OUT,
-        INOUT,
-        CONST,
-        LOWP,
-        MEDIUMP,
-        HIGHP,
-        UNIFORM,
-        FLAT,
-        NOPERSPECTIVE,
-        READONLY,
-        WRITEONLY,
-        COHERENT,
-        VOLATILE,
-        RESTRICT,
-        BUFFER,
-        HASSIDEEFFECTS,
-        STRUCT,
-        LAYOUT,
-        DIRECTIVE,
-        SECTION,
-        PRECISION,
-        LOCATION,
-        OFFSET,
-        BINDING,
-        INDEX,
-        SET,
-        BUILTIN,
-        INPUT_ATTACHMENT_INDEX,
-        ORIGIN_UPPER_LEFT,
-        OVERRIDE_COVERAGE,
-        BLEND_SUPPORT_ALL_EQUATIONS,
-        PUSH_CONSTANT,
-        POINTS,
-        LINES,
-        LINE_STRIP,
-        LINES_ADJACENCY,
-        TRIANGLES,
-        TRIANGLE_STRIP,
-        TRIANGLES_ADJACENCY,
-        MAX_VERTICES,
-        INVOCATIONS,
-        WHEN,
-        KEY,
-        INVALID_TOKEN
-    };
-
-    static String OperatorName(Kind kind) {
-        switch (kind) {
-            case Token::PLUS:         return String("+");
-            case Token::MINUS:        return String("-");
-            case Token::STAR:         return String("*");
-            case Token::SLASH:        return String("/");
-            case Token::PERCENT:      return String("%");
-            case Token::SHL:          return String("<<");
-            case Token::SHR:          return String(">>");
-            case Token::LOGICALNOT:   return String("!");
-            case Token::LOGICALAND:   return String("&&");
-            case Token::LOGICALOR:    return String("||");
-            case Token::LOGICALXOR:   return String("^^");
-            case Token::BITWISENOT:   return String("~");
-            case Token::BITWISEAND:   return String("&");
-            case Token::BITWISEOR:    return String("|");
-            case Token::BITWISEXOR:   return String("^");
-            case Token::EQ:           return String("=");
-            case Token::EQEQ:         return String("==");
-            case Token::NEQ:          return String("!=");
-            case Token::LT:           return String("<");
-            case Token::GT:           return String(">");
-            case Token::LTEQ:         return String("<=");
-            case Token::GTEQ:         return String(">=");
-            case Token::PLUSEQ:       return String("+=");
-            case Token::MINUSEQ:      return String("-=");
-            case Token::STAREQ:       return String("*=");
-            case Token::SLASHEQ:      return String("/=");
-            case Token::PERCENTEQ:    return String("%=");
-            case Token::SHLEQ:        return String("<<=");
-            case Token::SHREQ:        return String(">>=");
-            case Token::LOGICALANDEQ: return String("&&=");
-            case Token::LOGICALOREQ:  return String("||=");
-            case Token::LOGICALXOREQ: return String("^^=");
-            case Token::BITWISEANDEQ: return String("&=");
-            case Token::BITWISEOREQ:  return String("|=");
-            case Token::BITWISEXOREQ: return String("^=");
-            case Token::PLUSPLUS:     return String("++");
-            case Token::MINUSMINUS:   return String("--");
-            case Token::COMMA:        return String(",");
-            default:
-                ABORT("unsupported operator: %d\n", kind);
-        }
-    }
-
-    Token() {
-    }
-
-    Token(Position position, Kind kind, String text)
-    : fPosition(position)
-    , fKind(kind)
-    , fText(std::move(text)) {}
-
-    static bool IsAssignment(Token::Kind op) {
-        switch (op) {
-            case Token::EQ:           // fall through
-            case Token::PLUSEQ:       // fall through
-            case Token::MINUSEQ:      // fall through
-            case Token::STAREQ:       // fall through
-            case Token::SLASHEQ:      // fall through
-            case Token::PERCENTEQ:    // fall through
-            case Token::SHLEQ:        // fall through
-            case Token::SHREQ:        // fall through
-            case Token::BITWISEOREQ:  // fall through
-            case Token::BITWISEXOREQ: // fall through
-            case Token::BITWISEANDEQ: // fall through
-            case Token::LOGICALOREQ:  // fall through
-            case Token::LOGICALXOREQ: // fall through
-            case Token::LOGICALANDEQ:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    Position fPosition;
-    Kind fKind;
-    // will be the empty string unless the token has variable text content (identifiers, numeric
-    // literals, and directives)
-    String fText;
-};
-
-} // namespace
-#endif
diff --git a/src/sksl/ast/SkSLASTBinaryExpression.h b/src/sksl/ast/SkSLASTBinaryExpression.h
index 9a24970..c2f7b74 100644
--- a/src/sksl/ast/SkSLASTBinaryExpression.h
+++ b/src/sksl/ast/SkSLASTBinaryExpression.h
@@ -9,7 +9,8 @@
 #define SKSL_ASTBINARYEXPRESSION
 
 #include "SkSLASTExpression.h"
-#include "../SkSLToken.h"
+#include "../SkSLCompiler.h"
+#include "../SkSLLexer.h"
 
 namespace SkSL {
 
@@ -19,13 +20,13 @@
 struct ASTBinaryExpression : public ASTExpression {
     ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op,
                         std::unique_ptr<ASTExpression> right)
-    : INHERITED(op.fPosition, kBinary_Kind)
+    : INHERITED(op.fOffset, kBinary_Kind)
     , fLeft(std::move(left))
     , fOperator(op.fKind)
     , fRight(std::move(right)) {}
 
     String description() const override {
-        return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
+        return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
                fRight->description() + ")";
     }
 
diff --git a/src/sksl/ast/SkSLASTBlock.h b/src/sksl/ast/SkSLASTBlock.h
index 37c0e81..df01f62 100644
--- a/src/sksl/ast/SkSLASTBlock.h
+++ b/src/sksl/ast/SkSLASTBlock.h
@@ -16,8 +16,8 @@
  * Represents a curly-braced block of statements.
  */
 struct ASTBlock : public ASTStatement {
-    ASTBlock(Position position, std::vector<std::unique_ptr<ASTStatement>> statements)
-    : INHERITED(position, kBlock_Kind)
+    ASTBlock(int offset, std::vector<std::unique_ptr<ASTStatement>> statements)
+    : INHERITED(offset, kBlock_Kind)
     , fStatements(std::move(statements)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTBoolLiteral.h b/src/sksl/ast/SkSLASTBoolLiteral.h
index 48e916e..6782d36 100644
--- a/src/sksl/ast/SkSLASTBoolLiteral.h
+++ b/src/sksl/ast/SkSLASTBoolLiteral.h
@@ -16,8 +16,8 @@
  * Represents "true" or "false".
  */
 struct ASTBoolLiteral : public ASTExpression {
-    ASTBoolLiteral(Position position, bool value)
-    : INHERITED(position, kBool_Kind)
+    ASTBoolLiteral(int offset, bool value)
+    : INHERITED(offset, kBool_Kind)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTBreakStatement.h b/src/sksl/ast/SkSLASTBreakStatement.h
index 079ee76..2937dae 100644
--- a/src/sksl/ast/SkSLASTBreakStatement.h
+++ b/src/sksl/ast/SkSLASTBreakStatement.h
@@ -16,8 +16,8 @@
  * A 'break' statement.
  */
 struct ASTBreakStatement : public ASTStatement {
-    ASTBreakStatement(Position position)
-    : INHERITED(position, kBreak_Kind) {}
+    ASTBreakStatement(int offset)
+    : INHERITED(offset, kBreak_Kind) {}
 
     String description() const override {
         return String("break;");
diff --git a/src/sksl/ast/SkSLASTCallSuffix.h b/src/sksl/ast/SkSLASTCallSuffix.h
index 3ba3f0e..316a0ae 100644
--- a/src/sksl/ast/SkSLASTCallSuffix.h
+++ b/src/sksl/ast/SkSLASTCallSuffix.h
@@ -17,8 +17,8 @@
  * A parenthesized list of arguments following an expression, indicating a function call.
  */
 struct ASTCallSuffix : public ASTSuffix {
-    ASTCallSuffix(Position position, std::vector<std::unique_ptr<ASTExpression>> arguments)
-    : INHERITED(position, ASTSuffix::kCall_Kind)
+    ASTCallSuffix(int offset, std::vector<std::unique_ptr<ASTExpression>> arguments)
+    : INHERITED(offset, ASTSuffix::kCall_Kind)
     , fArguments(std::move(arguments)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTContinueStatement.h b/src/sksl/ast/SkSLASTContinueStatement.h
index fdfce85..30b2dae 100644
--- a/src/sksl/ast/SkSLASTContinueStatement.h
+++ b/src/sksl/ast/SkSLASTContinueStatement.h
@@ -16,8 +16,8 @@
  * A 'continue' statement.
  */
 struct ASTContinueStatement : public ASTStatement {
-    ASTContinueStatement(Position position)
-    : INHERITED(position, kContinue_Kind) {}
+    ASTContinueStatement(int offset)
+    : INHERITED(offset, kContinue_Kind) {}
 
     String description() const override {
         return String("continue;");
diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h
index 873c6b2..53aa65f 100644
--- a/src/sksl/ast/SkSLASTDeclaration.h
+++ b/src/sksl/ast/SkSLASTDeclaration.h
@@ -26,8 +26,8 @@
         kSection_Kind
     };
 
-    ASTDeclaration(Position position, Kind kind)
-    : INHERITED(position)
+    ASTDeclaration(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     Kind fKind;
diff --git a/src/sksl/ast/SkSLASTDiscardStatement.h b/src/sksl/ast/SkSLASTDiscardStatement.h
index dcf6b15..083c3f8 100644
--- a/src/sksl/ast/SkSLASTDiscardStatement.h
+++ b/src/sksl/ast/SkSLASTDiscardStatement.h
@@ -16,8 +16,8 @@
  * A 'discard' statement.
  */
 struct ASTDiscardStatement : public ASTStatement {
-    ASTDiscardStatement(Position position)
-    : INHERITED(position, kDiscard_Kind) {}
+    ASTDiscardStatement(int offset)
+    : INHERITED(offset, kDiscard_Kind) {}
 
     String description() const override {
         return String("discard;");
diff --git a/src/sksl/ast/SkSLASTDoStatement.h b/src/sksl/ast/SkSLASTDoStatement.h
index fc97d9e..36324e3 100644
--- a/src/sksl/ast/SkSLASTDoStatement.h
+++ b/src/sksl/ast/SkSLASTDoStatement.h
@@ -16,9 +16,9 @@
  * A 'do' loop.
  */
 struct ASTDoStatement : public ASTStatement {
-    ASTDoStatement(Position position, std::unique_ptr<ASTStatement> statement,
+    ASTDoStatement(int offset, std::unique_ptr<ASTStatement> statement,
                    std::unique_ptr<ASTExpression> test)
-    : INHERITED(position, kDo_Kind)
+    : INHERITED(offset, kDo_Kind)
     , fStatement(std::move(statement))
     , fTest(std::move(test)) {}
 
diff --git a/src/sksl/ast/SkSLASTExpression.h b/src/sksl/ast/SkSLASTExpression.h
index 11815ae..0d8ddc7 100644
--- a/src/sksl/ast/SkSLASTExpression.h
+++ b/src/sksl/ast/SkSLASTExpression.h
@@ -27,8 +27,8 @@
         kTernary_Kind
     };
 
-    ASTExpression(Position position, Kind kind)
-    : INHERITED(position)
+    ASTExpression(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     const Kind fKind;
diff --git a/src/sksl/ast/SkSLASTExpressionStatement.h b/src/sksl/ast/SkSLASTExpressionStatement.h
index 398a16a..14f087f 100644
--- a/src/sksl/ast/SkSLASTExpressionStatement.h
+++ b/src/sksl/ast/SkSLASTExpressionStatement.h
@@ -17,7 +17,7 @@
  */
 struct ASTExpressionStatement : public ASTStatement {
     ASTExpressionStatement(std::unique_ptr<ASTExpression> expression)
-    : INHERITED(expression->fPosition, kExpression_Kind)
+    : INHERITED(expression->fOffset, kExpression_Kind)
     , fExpression(std::move(expression)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTExtension.h b/src/sksl/ast/SkSLASTExtension.h
index a6fde06..c394b1d 100644
--- a/src/sksl/ast/SkSLASTExtension.h
+++ b/src/sksl/ast/SkSLASTExtension.h
@@ -16,8 +16,8 @@
  * An extension declaration.
  */
 struct ASTExtension : public ASTDeclaration {
-    ASTExtension(Position position, String name)
-    : INHERITED(position, kExtension_Kind)
+    ASTExtension(int offset, String name)
+    : INHERITED(offset, kExtension_Kind)
     , fName(std::move(name)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTFieldSuffix.h b/src/sksl/ast/SkSLASTFieldSuffix.h
index bde1e4a..b29ddf3 100644
--- a/src/sksl/ast/SkSLASTFieldSuffix.h
+++ b/src/sksl/ast/SkSLASTFieldSuffix.h
@@ -17,15 +17,15 @@
  * actually vector swizzle (which looks the same to the parser).
  */
 struct ASTFieldSuffix : public ASTSuffix {
-    ASTFieldSuffix(Position position, String field)
-    : INHERITED(position, ASTSuffix::kField_Kind)
-    , fField(std::move(field)) {}
+    ASTFieldSuffix(int offset, StringFragment field)
+    : INHERITED(offset, ASTSuffix::kField_Kind)
+    , fField(field) {}
 
     String description() const override {
         return "." + fField;
     }
 
-    String fField;
+    StringFragment fField;
 
     typedef ASTSuffix INHERITED;
 };
diff --git a/src/sksl/ast/SkSLASTFloatLiteral.h b/src/sksl/ast/SkSLASTFloatLiteral.h
index 15fe836..6e63b4e 100644
--- a/src/sksl/ast/SkSLASTFloatLiteral.h
+++ b/src/sksl/ast/SkSLASTFloatLiteral.h
@@ -16,8 +16,8 @@
  * A literal floating point number.
  */
 struct ASTFloatLiteral : public ASTExpression {
-    ASTFloatLiteral(Position position, double value)
-    : INHERITED(position, kFloat_Kind)
+    ASTFloatLiteral(int offset, double value)
+    : INHERITED(offset, kFloat_Kind)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTForStatement.h b/src/sksl/ast/SkSLASTForStatement.h
index 326713e..713f952 100644
--- a/src/sksl/ast/SkSLASTForStatement.h
+++ b/src/sksl/ast/SkSLASTForStatement.h
@@ -16,10 +16,10 @@
  * A 'for' loop.
  */
 struct ASTForStatement : public ASTStatement {
-    ASTForStatement(Position position, std::unique_ptr<ASTStatement> initializer,
+    ASTForStatement(int offset, std::unique_ptr<ASTStatement> initializer,
                    std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next,
                    std::unique_ptr<ASTStatement> statement)
-    : INHERITED(position, kFor_Kind)
+    : INHERITED(offset, kFor_Kind)
     , fInitializer(std::move(initializer))
     , fTest(std::move(test))
     , fNext(std::move(next))
diff --git a/src/sksl/ast/SkSLASTFunction.h b/src/sksl/ast/SkSLASTFunction.h
index 36d8a3a..4fa2482 100644
--- a/src/sksl/ast/SkSLASTFunction.h
+++ b/src/sksl/ast/SkSLASTFunction.h
@@ -19,13 +19,13 @@
  * A function declaration or definition. The fBody field will be null for declarations.
  */
 struct ASTFunction : public ASTDeclaration {
-    ASTFunction(Position position, Modifiers modifiers,  std::unique_ptr<ASTType> returnType,
-                String name, std::vector<std::unique_ptr<ASTParameter>> parameters,
+    ASTFunction(int offset, Modifiers modifiers,  std::unique_ptr<ASTType> returnType,
+                StringFragment name, std::vector<std::unique_ptr<ASTParameter>> parameters,
                 std::unique_ptr<ASTBlock> body)
-    : INHERITED(position, kFunction_Kind)
+    : INHERITED(offset, kFunction_Kind)
     , fModifiers(modifiers)
     , fReturnType(std::move(returnType))
-    , fName(std::move(name))
+    , fName(name)
     , fParameters(std::move(parameters))
     , fBody(std::move(body)) {}
 
@@ -47,7 +47,7 @@
 
     const Modifiers fModifiers;
     const std::unique_ptr<ASTType> fReturnType;
-    const String fName;
+    const StringFragment fName;
     const std::vector<std::unique_ptr<ASTParameter>> fParameters;
     const std::unique_ptr<ASTBlock> fBody;
 
diff --git a/src/sksl/ast/SkSLASTIdentifier.h b/src/sksl/ast/SkSLASTIdentifier.h
index 016123c..a84370e 100644
--- a/src/sksl/ast/SkSLASTIdentifier.h
+++ b/src/sksl/ast/SkSLASTIdentifier.h
@@ -16,15 +16,15 @@
  * An identifier in an expression context.
  */
 struct ASTIdentifier : public ASTExpression {
-    ASTIdentifier(Position position, String text)
-    : INHERITED(position, kIdentifier_Kind)
-    , fText(std::move(text)) {}
+    ASTIdentifier(int offset, StringFragment text)
+    : INHERITED(offset, kIdentifier_Kind)
+    , fText(text) {}
 
     String description() const override {
-        return fText;
+        return String(fText);
     }
 
-    const String fText;
+    const StringFragment fText;
 
     typedef ASTExpression INHERITED;
 };
diff --git a/src/sksl/ast/SkSLASTIfStatement.h b/src/sksl/ast/SkSLASTIfStatement.h
index 2752b2b..85b1239 100644
--- a/src/sksl/ast/SkSLASTIfStatement.h
+++ b/src/sksl/ast/SkSLASTIfStatement.h
@@ -16,9 +16,9 @@
  * An 'if' statement.
  */
 struct ASTIfStatement : public ASTStatement {
-    ASTIfStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> test,
+    ASTIfStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> test,
                    std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse)
-    : INHERITED(position, kIf_Kind)
+    : INHERITED(offset, kIf_Kind)
     , fIsStatic(isStatic)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h
index 31142e3..cb19e54 100644
--- a/src/sksl/ast/SkSLASTIndexSuffix.h
+++ b/src/sksl/ast/SkSLASTIndexSuffix.h
@@ -18,12 +18,12 @@
  * 'float[](5, 6)' are represented with a null fExpression.
  */
 struct ASTIndexSuffix : public ASTSuffix {
-    ASTIndexSuffix(Position position)
-    : INHERITED(position, ASTSuffix::kIndex_Kind)
+    ASTIndexSuffix(int offset)
+    : INHERITED(offset, ASTSuffix::kIndex_Kind)
     , fExpression(nullptr) {}
 
     ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
-    : INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind)
+    : INHERITED(expression ? expression->fOffset : -1, ASTSuffix::kIndex_Kind)
     , fExpression(std::move(expression)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTIntLiteral.h b/src/sksl/ast/SkSLASTIntLiteral.h
index fe04347..927537b 100644
--- a/src/sksl/ast/SkSLASTIntLiteral.h
+++ b/src/sksl/ast/SkSLASTIntLiteral.h
@@ -17,8 +17,8 @@
  * appear as a unary minus being applied to an integer literal.
  */
 struct ASTIntLiteral : public ASTExpression {
-    ASTIntLiteral(Position position, uint64_t value)
-    : INHERITED(position, kInt_Kind)
+    ASTIntLiteral(int offset, uint64_t value)
+    : INHERITED(offset, kInt_Kind)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h
index f111f73..d445ae0 100644
--- a/src/sksl/ast/SkSLASTInterfaceBlock.h
+++ b/src/sksl/ast/SkSLASTInterfaceBlock.h
@@ -23,17 +23,17 @@
  */
 struct ASTInterfaceBlock : public ASTDeclaration {
     // valueName is empty when it was not present in the source
-    ASTInterfaceBlock(Position position,
+    ASTInterfaceBlock(int offset,
                       Modifiers modifiers,
-                      String typeName,
+                      StringFragment typeName,
                       std::vector<std::unique_ptr<ASTVarDeclarations>> declarations,
-                      String instanceName,
+                      StringFragment instanceName,
                       std::vector<std::unique_ptr<ASTExpression>> sizes)
-    : INHERITED(position, kInterfaceBlock_Kind)
+    : INHERITED(offset, kInterfaceBlock_Kind)
     , fModifiers(modifiers)
-    , fTypeName(std::move(typeName))
+    , fTypeName(typeName)
     , fDeclarations(std::move(declarations))
-    , fInstanceName(std::move(instanceName))
+    , fInstanceName(instanceName)
     , fSizes(std::move(sizes)) {}
 
     String description() const override {
@@ -42,7 +42,7 @@
             result += fDeclarations[i]->description() + "\n";
         }
         result += "}";
-        if (fInstanceName.size()) {
+        if (fInstanceName.fLength) {
             result += " " + fInstanceName;
             for (const auto& size : fSizes) {
                 result += "[";
@@ -56,9 +56,9 @@
     }
 
     const Modifiers fModifiers;
-    const String fTypeName;
+    const StringFragment fTypeName;
     const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations;
-    const String fInstanceName;
+    const StringFragment fInstanceName;
     const std::vector<std::unique_ptr<ASTExpression>> fSizes;
 
     typedef ASTDeclaration INHERITED;
diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h
index ba07f16..5269cd5 100644
--- a/src/sksl/ast/SkSLASTModifiersDeclaration.h
+++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h
@@ -20,7 +20,7 @@
  */
 struct ASTModifiersDeclaration : public ASTDeclaration {
     ASTModifiersDeclaration(Modifiers modifiers)
-    : INHERITED(Position(), kModifiers_Kind)
+    : INHERITED(-1, kModifiers_Kind)
     , fModifiers(modifiers) {}
 
     String description() const {
diff --git a/src/sksl/ast/SkSLASTParameter.h b/src/sksl/ast/SkSLASTParameter.h
index 01227c6..965e374 100644
--- a/src/sksl/ast/SkSLASTParameter.h
+++ b/src/sksl/ast/SkSLASTParameter.h
@@ -20,12 +20,12 @@
 struct ASTParameter : public ASTPositionNode {
     // 'sizes' is a list of the array sizes appearing on a parameter, in source order.
     // e.g. int x[3][1] would have sizes [3, 1].
-    ASTParameter(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type,
-                 String name, std::vector<int> sizes)
-    : INHERITED(position)
+    ASTParameter(int offset, Modifiers modifiers, std::unique_ptr<ASTType> type,
+                 StringFragment name, std::vector<int> sizes)
+    : INHERITED(offset)
     , fModifiers(modifiers)
     , fType(std::move(type))
-    , fName(std::move(name))
+    , fName(name)
     , fSizes(std::move(sizes)) {}
 
     String description() const override {
@@ -38,7 +38,7 @@
 
     const Modifiers fModifiers;
     const std::unique_ptr<ASTType> fType;
-    const String fName;
+    const StringFragment fName;
     const std::vector<int> fSizes;
 
     typedef ASTPositionNode INHERITED;
diff --git a/src/sksl/ast/SkSLASTPositionNode.h b/src/sksl/ast/SkSLASTPositionNode.h
index cc435c4..b8f22a7 100644
--- a/src/sksl/ast/SkSLASTPositionNode.h
+++ b/src/sksl/ast/SkSLASTPositionNode.h
@@ -17,10 +17,12 @@
  * An AST node with an associated position in the source.
  */
 struct ASTPositionNode : public ASTNode {
-    ASTPositionNode(Position position)
-    : fPosition(position) {}
+    ASTPositionNode(int offset)
+    : fOffset(offset) {}
 
-    const Position fPosition;
+    // character offset of this element within the program being compiled, for error reporting
+    // purposes
+    const int fOffset;
 };
 
 } // namespace
diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h
index 4b50ed3..0b81ca3 100644
--- a/src/sksl/ast/SkSLASTPrecision.h
+++ b/src/sksl/ast/SkSLASTPrecision.h
@@ -18,8 +18,8 @@
  */
 struct ASTPrecision : public ASTDeclaration {
     // FIXME handle the type
-    ASTPrecision(Position position, Modifiers::Flag precision)
-    : INHERITED(position, kPrecision_Kind)
+    ASTPrecision(int offset, Modifiers::Flag precision)
+    : INHERITED(offset, kPrecision_Kind)
     , fPrecision(precision) {}
 
     String description() const {
diff --git a/src/sksl/ast/SkSLASTPrefixExpression.h b/src/sksl/ast/SkSLASTPrefixExpression.h
index 08e50f7..0403a2f 100644
--- a/src/sksl/ast/SkSLASTPrefixExpression.h
+++ b/src/sksl/ast/SkSLASTPrefixExpression.h
@@ -9,7 +9,8 @@
 #define SKSL_ASTPREFIXEXPRESSION
 
 #include "SkSLASTExpression.h"
-#include "../SkSLToken.h"
+#include "../SkSLCompiler.h"
+#include "../SkSLLexer.h"
 
 namespace SkSL {
 
@@ -18,12 +19,12 @@
  */
 struct ASTPrefixExpression : public ASTExpression {
     ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand)
-    : INHERITED(op.fPosition, kPrefix_Kind)
+    : INHERITED(op.fOffset, kPrefix_Kind)
     , fOperator(op.fKind)
     , fOperand(std::move(operand)) {}
 
     String description() const override {
-        return Token::OperatorName(fOperator) + fOperand->description();
+        return Compiler::OperatorName(fOperator) + fOperand->description();
     }
 
     const Token::Kind fOperator;
diff --git a/src/sksl/ast/SkSLASTReturnStatement.h b/src/sksl/ast/SkSLASTReturnStatement.h
index 6762eb3..489658a 100644
--- a/src/sksl/ast/SkSLASTReturnStatement.h
+++ b/src/sksl/ast/SkSLASTReturnStatement.h
@@ -17,8 +17,8 @@
  */
 struct ASTReturnStatement : public ASTStatement {
     // expression may be null
-    ASTReturnStatement(Position position, std::unique_ptr<ASTExpression> expression)
-    : INHERITED(position, kReturn_Kind)
+    ASTReturnStatement(int offset, std::unique_ptr<ASTExpression> expression)
+    : INHERITED(offset, kReturn_Kind)
     , fExpression(std::move(expression)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTSection.h b/src/sksl/ast/SkSLASTSection.h
index d0887e2..6c1f8ee 100644
--- a/src/sksl/ast/SkSLASTSection.h
+++ b/src/sksl/ast/SkSLASTSection.h
@@ -16,8 +16,8 @@
  * A section declaration (e.g. @body { body code here })..
  */
 struct ASTSection : public ASTDeclaration {
-    ASTSection(Position position, String name, String arg, String text)
-    : INHERITED(position, kSection_Kind)
+    ASTSection(int offset, String name, String arg, String text)
+    : INHERITED(offset, kSection_Kind)
     , fName(std::move(name))
     , fArgument(std::move(arg))
     , fText(std::move(text)) {}
diff --git a/src/sksl/ast/SkSLASTStatement.h b/src/sksl/ast/SkSLASTStatement.h
index 1989a1f..c22a2fb 100644
--- a/src/sksl/ast/SkSLASTStatement.h
+++ b/src/sksl/ast/SkSLASTStatement.h
@@ -33,8 +33,8 @@
         kDiscard_Kind
     };
 
-    ASTStatement(Position position, Kind kind)
-    : INHERITED(position)
+    ASTStatement(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     Kind fKind;
diff --git a/src/sksl/ast/SkSLASTSuffix.h b/src/sksl/ast/SkSLASTSuffix.h
index f06c6fd..898855c 100644
--- a/src/sksl/ast/SkSLASTSuffix.h
+++ b/src/sksl/ast/SkSLASTSuffix.h
@@ -26,8 +26,8 @@
         kPostDecrement_Kind
     };
 
-    ASTSuffix(Position position, Kind kind)
-    : INHERITED(position)
+    ASTSuffix(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTSuffixExpression.h b/src/sksl/ast/SkSLASTSuffixExpression.h
index 2cff9a8..31cddb2 100644
--- a/src/sksl/ast/SkSLASTSuffixExpression.h
+++ b/src/sksl/ast/SkSLASTSuffixExpression.h
@@ -18,7 +18,7 @@
  */
 struct ASTSuffixExpression : public ASTExpression {
     ASTSuffixExpression(std::unique_ptr<ASTExpression> base, std::unique_ptr<ASTSuffix> suffix)
-    : INHERITED(base->fPosition, kSuffix_Kind)
+    : INHERITED(base->fOffset, kSuffix_Kind)
     , fBase(std::move(base))
     , fSuffix(std::move(suffix)) {}
 
diff --git a/src/sksl/ast/SkSLASTSwitchCase.h b/src/sksl/ast/SkSLASTSwitchCase.h
index 405013a..221e212 100644
--- a/src/sksl/ast/SkSLASTSwitchCase.h
+++ b/src/sksl/ast/SkSLASTSwitchCase.h
@@ -17,9 +17,9 @@
  */
 struct ASTSwitchCase : public ASTStatement {
     // a null value means "default:"
-    ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value,
+    ASTSwitchCase(int offset, std::unique_ptr<ASTExpression> value,
                   std::vector<std::unique_ptr<ASTStatement>> statements)
-    : INHERITED(position, kSwitch_Kind)
+    : INHERITED(offset, kSwitch_Kind)
     , fValue(std::move(value))
     , fStatements(std::move(statements)) {}
 
diff --git a/src/sksl/ast/SkSLASTSwitchStatement.h b/src/sksl/ast/SkSLASTSwitchStatement.h
index ecd0a67..3bee0a4 100644
--- a/src/sksl/ast/SkSLASTSwitchStatement.h
+++ b/src/sksl/ast/SkSLASTSwitchStatement.h
@@ -17,9 +17,9 @@
  * A 'switch' statement.
  */
 struct ASTSwitchStatement : public ASTStatement {
-    ASTSwitchStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> value,
+    ASTSwitchStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> value,
                        std::vector<std::unique_ptr<ASTSwitchCase>> cases)
-    : INHERITED(position, kSwitch_Kind)
+    : INHERITED(offset, kSwitch_Kind)
     , fIsStatic(isStatic)
     , fValue(std::move(value))
     , fCases(std::move(cases)) {}
diff --git a/src/sksl/ast/SkSLASTTernaryExpression.h b/src/sksl/ast/SkSLASTTernaryExpression.h
index 07c9297..35795e9 100644
--- a/src/sksl/ast/SkSLASTTernaryExpression.h
+++ b/src/sksl/ast/SkSLASTTernaryExpression.h
@@ -19,7 +19,7 @@
     ASTTernaryExpression(std::unique_ptr<ASTExpression> test,
                          std::unique_ptr<ASTExpression> ifTrue,
                          std::unique_ptr<ASTExpression> ifFalse)
-    : INHERITED(test->fPosition, kTernary_Kind)
+    : INHERITED(test->fOffset, kTernary_Kind)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
     , fIfFalse(std::move(ifFalse)) {}
diff --git a/src/sksl/ast/SkSLASTType.h b/src/sksl/ast/SkSLASTType.h
index 57a8025..44fd95b 100644
--- a/src/sksl/ast/SkSLASTType.h
+++ b/src/sksl/ast/SkSLASTType.h
@@ -21,9 +21,9 @@
         kStruct_Kind
     };
 
-    ASTType(Position position, String name, Kind kind, std::vector<int> sizes)
-    : INHERITED(position)
-    , fName(std::move(name))
+    ASTType(int offset, StringFragment name, Kind kind, std::vector<int> sizes)
+    : INHERITED(offset)
+    , fName(name)
     , fKind(kind)
     , fSizes(std::move(sizes)) {}
 
@@ -31,7 +31,7 @@
         return fName;
     }
 
-    const String fName;
+    const StringFragment fName;
 
     const Kind fKind;
 
diff --git a/src/sksl/ast/SkSLASTVarDeclaration.h b/src/sksl/ast/SkSLASTVarDeclaration.h
index 2dcb978..38c9104 100644
--- a/src/sksl/ast/SkSLASTVarDeclaration.h
+++ b/src/sksl/ast/SkSLASTVarDeclaration.h
@@ -22,7 +22,7 @@
  * instances.
  */
 struct ASTVarDeclaration {
-    ASTVarDeclaration(const String name,
+    ASTVarDeclaration(StringFragment name,
                       std::vector<std::unique_ptr<ASTExpression>> sizes,
                       std::unique_ptr<ASTExpression> value)
     : fName(name)
@@ -30,7 +30,7 @@
     , fValue(std::move(value)) {}
 
     String description() const {
-        String result = fName;
+        String result(fName);
         for (const auto& size : fSizes) {
             if (size) {
                 result += "[" + size->description() + "]";
@@ -44,7 +44,7 @@
         return result;
     }
 
-    String fName;
+    StringFragment fName;
 
     // array sizes, if any. e.g. 'foo[3][]' has sizes [3, null]
     std::vector<std::unique_ptr<ASTExpression>> fSizes;
@@ -60,7 +60,7 @@
     ASTVarDeclarations(Modifiers modifiers,
                        std::unique_ptr<ASTType> type,
                        std::vector<ASTVarDeclaration> vars)
-    : INHERITED(type->fPosition, kVar_Kind)
+    : INHERITED(type->fOffset, kVar_Kind)
     , fModifiers(modifiers)
     , fType(std::move(type))
     , fVars(std::move(vars)) {}
diff --git a/src/sksl/ast/SkSLASTVarDeclarationStatement.h b/src/sksl/ast/SkSLASTVarDeclarationStatement.h
index c3a4069..8ec5bf6 100644
--- a/src/sksl/ast/SkSLASTVarDeclarationStatement.h
+++ b/src/sksl/ast/SkSLASTVarDeclarationStatement.h
@@ -18,7 +18,7 @@
  */
 struct ASTVarDeclarationStatement : public ASTStatement {
     ASTVarDeclarationStatement(std::unique_ptr<ASTVarDeclarations> decl)
-    : INHERITED(decl->fPosition, kVarDeclaration_Kind)
+    : INHERITED(decl->fOffset, kVarDeclaration_Kind)
     , fDeclarations(std::move(decl)) {}
 
     String description() const override {
diff --git a/src/sksl/ast/SkSLASTWhileStatement.h b/src/sksl/ast/SkSLASTWhileStatement.h
index e63c502..c0da0af 100644
--- a/src/sksl/ast/SkSLASTWhileStatement.h
+++ b/src/sksl/ast/SkSLASTWhileStatement.h
@@ -16,9 +16,9 @@
  * A 'while' statement.
  */
 struct ASTWhileStatement : public ASTStatement {
-    ASTWhileStatement(Position position, std::unique_ptr<ASTExpression> test,
+    ASTWhileStatement(int offset, std::unique_ptr<ASTExpression> test,
                       std::unique_ptr<ASTStatement> statement)
-    : INHERITED(position, kWhile_Kind)
+    : INHERITED(offset, kWhile_Kind)
     , fTest(std::move(test))
     , fStatement(std::move(statement)) {}
 
diff --git a/src/sksl/disable_flex_warnings.h b/src/sksl/disable_flex_warnings.h
deleted file mode 100644
index ad73b63..0000000
--- a/src/sksl/disable_flex_warnings.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// useless include to avoid "#if before #include" complaint from Skia presubmit
-#include "SkSLUtil.h"
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
-#pragma clang diagnostic ignored "-Wnull-conversion"
-#pragma clang diagnostic ignored "-Wsign-compare"
-#pragma clang diagnostic ignored "-Wunused-function"
-#pragma clang diagnostic ignored "-Wdeprecated-register"
-#endif
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4018)
-#endif
-
-#define YY_NO_UNPUT
diff --git a/src/sksl/ir/SkSLBinaryExpression.h b/src/sksl/ir/SkSLBinaryExpression.h
index 789db57..c26994e 100644
--- a/src/sksl/ir/SkSLBinaryExpression.h
+++ b/src/sksl/ir/SkSLBinaryExpression.h
@@ -11,7 +11,7 @@
 #include "SkSLExpression.h"
 #include "SkSLExpression.h"
 #include "../SkSLIRGenerator.h"
-#include "../SkSLToken.h"
+#include "../SkSLLexer.h"
 
 namespace SkSL {
 
@@ -19,9 +19,9 @@
  * A binary operation.
  */
 struct BinaryExpression : public Expression {
-    BinaryExpression(Position position, std::unique_ptr<Expression> left, Token::Kind op,
+    BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
                      std::unique_ptr<Expression> right, const Type& type)
-    : INHERITED(position, kBinary_Kind, type)
+    : INHERITED(offset, kBinary_Kind, type)
     , fLeft(std::move(left))
     , fOperator(op)
     , fRight(std::move(right)) {}
@@ -34,12 +34,12 @@
     }
 
     bool hasSideEffects() const override {
-        return Token::IsAssignment(fOperator) || fLeft->hasSideEffects() ||
+        return Compiler::IsAssignment(fOperator) || fLeft->hasSideEffects() ||
                fRight->hasSideEffects();
     }
 
     String description() const override {
-        return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
+        return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
                fRight->description() + ")";
     }
 
diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h
index bcd4bb1..af19753 100644
--- a/src/sksl/ir/SkSLBlock.h
+++ b/src/sksl/ir/SkSLBlock.h
@@ -17,9 +17,9 @@
  * A block of multiple statements functioning as a single statement.
  */
 struct Block : public Statement {
-    Block(Position position, std::vector<std::unique_ptr<Statement>> statements,
+    Block(int offset, std::vector<std::unique_ptr<Statement>> statements,
           const std::shared_ptr<SymbolTable> symbols = nullptr)
-    : INHERITED(position, kBlock_Kind)
+    : INHERITED(offset, kBlock_Kind)
     , fSymbols(std::move(symbols))
     , fStatements(std::move(statements)) {}
 
diff --git a/src/sksl/ir/SkSLBoolLiteral.h b/src/sksl/ir/SkSLBoolLiteral.h
index a4151b8..9a69f0f 100644
--- a/src/sksl/ir/SkSLBoolLiteral.h
+++ b/src/sksl/ir/SkSLBoolLiteral.h
@@ -17,8 +17,8 @@
  * Represents 'true' or 'false'.
  */
 struct BoolLiteral : public Expression {
-    BoolLiteral(const Context& context, Position position, bool value)
-    : INHERITED(position, kBoolLiteral_Kind, *context.fBool_Type)
+    BoolLiteral(const Context& context, int offset, bool value)
+    : INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLBreakStatement.h b/src/sksl/ir/SkSLBreakStatement.h
index f6edc55..da392f5 100644
--- a/src/sksl/ir/SkSLBreakStatement.h
+++ b/src/sksl/ir/SkSLBreakStatement.h
@@ -17,8 +17,8 @@
  * A 'break' statement.
  */
 struct BreakStatement : public Statement {
-    BreakStatement(Position position)
-    : INHERITED(position, kBreak_Kind) {}
+    BreakStatement(int offset)
+    : INHERITED(offset, kBreak_Kind) {}
 
     String description() const override {
         return String("break;");
diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h
index beed0f7..32fc0fb 100644
--- a/src/sksl/ir/SkSLConstructor.h
+++ b/src/sksl/ir/SkSLConstructor.h
@@ -16,7 +16,7 @@
 namespace SkSL {
 
 /**
- * Represents the construction of a compound type, such as "float2x, y)".
+ * Represents the construction of a compound type, such as "float2(x, y)".
  *
  * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors
  * and scalars totalling exactly the right number of scalar components.
@@ -25,9 +25,8 @@
  * collection of vectors and scalars totalling exactly the right number of scalar components.
  */
 struct Constructor : public Expression {
-    Constructor(Position position, const Type& type,
-                std::vector<std::unique_ptr<Expression>> arguments)
-    : INHERITED(position, kConstructor_Kind, type)
+    Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
+    : INHERITED(offset, kConstructor_Kind, type)
     , fArguments(std::move(arguments)) {}
 
     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
@@ -37,13 +36,13 @@
                 // promote float(1) to 1.0
                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
-                                                                    fPosition,
+                                                                    fOffset,
                                                                     intValue));
             } else if (fType == *irGenerator.fContext.fUInt_Type) {
                 // promote uint(1) to 1u
                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
-                                                                  fPosition,
+                                                                  fOffset,
                                                                   intValue,
                                                                   &fType));
             }
@@ -96,8 +95,8 @@
         // a constant scalar constructor should have been collapsed down to the appropriate
         // literal
         ASSERT(fType.kind() == Type::kMatrix_Kind);
-        const FloatLiteral fzero(context, Position(), 0);
-        const IntLiteral izero(context, Position(), 0);
+        const FloatLiteral fzero(context, -1, 0);
+        const IntLiteral izero(context, -1, 0);
         const Expression* zero;
         if (fType.componentType() == *context.fFloat_Type) {
             zero = &fzero;
diff --git a/src/sksl/ir/SkSLContinueStatement.h b/src/sksl/ir/SkSLContinueStatement.h
index 3f5bc1d..6ed40c4 100644
--- a/src/sksl/ir/SkSLContinueStatement.h
+++ b/src/sksl/ir/SkSLContinueStatement.h
@@ -17,8 +17,8 @@
  * A 'continue' statement.
  */
 struct ContinueStatement : public Statement {
-    ContinueStatement(Position position)
-    : INHERITED(position, kContinue_Kind) {}
+    ContinueStatement(int offset)
+    : INHERITED(offset, kContinue_Kind) {}
 
     String description() const override {
         return String("continue;");
diff --git a/src/sksl/ir/SkSLDiscardStatement.h b/src/sksl/ir/SkSLDiscardStatement.h
index 6212466..b62530e 100644
--- a/src/sksl/ir/SkSLDiscardStatement.h
+++ b/src/sksl/ir/SkSLDiscardStatement.h
@@ -17,8 +17,8 @@
  * A 'discard' statement.
  */
 struct DiscardStatement : public Statement {
-    DiscardStatement(Position position)
-    : INHERITED(position, kDiscard_Kind) {}
+    DiscardStatement(int offset)
+    : INHERITED(offset, kDiscard_Kind) {}
 
     String description() const override {
         return String("discard;");
diff --git a/src/sksl/ir/SkSLDoStatement.h b/src/sksl/ir/SkSLDoStatement.h
index f1ecd9a..3abec55 100644
--- a/src/sksl/ir/SkSLDoStatement.h
+++ b/src/sksl/ir/SkSLDoStatement.h
@@ -17,9 +17,9 @@
  * A 'do' statement.
  */
 struct DoStatement : public Statement {
-    DoStatement(Position position, std::unique_ptr<Statement> statement,
+    DoStatement(int offset, std::unique_ptr<Statement> statement,
                 std::unique_ptr<Expression> test)
-    : INHERITED(position, kDo_Kind)
+    : INHERITED(offset, kDo_Kind)
     , fStatement(std::move(statement))
     , fTest(std::move(test)) {}
 
diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h
index 286610f..555e660 100644
--- a/src/sksl/ir/SkSLExpression.h
+++ b/src/sksl/ir/SkSLExpression.h
@@ -44,8 +44,8 @@
         kDefined_Kind
     };
 
-    Expression(Position position, Kind kind, const Type& type)
-    : INHERITED(position)
+    Expression(int offset, Kind kind, const Type& type)
+    : INHERITED(offset)
     , fKind(kind)
     , fType(std::move(type)) {}
 
diff --git a/src/sksl/ir/SkSLExpressionStatement.h b/src/sksl/ir/SkSLExpressionStatement.h
index d1ab8e9..215763b 100644
--- a/src/sksl/ir/SkSLExpressionStatement.h
+++ b/src/sksl/ir/SkSLExpressionStatement.h
@@ -18,7 +18,7 @@
  */
 struct ExpressionStatement : public Statement {
     ExpressionStatement(std::unique_ptr<Expression> expression)
-    : INHERITED(expression->fPosition, kExpression_Kind)
+    : INHERITED(expression->fOffset, kExpression_Kind)
     , fExpression(std::move(expression)) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLExtension.h b/src/sksl/ir/SkSLExtension.h
index 70dc6b3..b5a48b9 100644
--- a/src/sksl/ir/SkSLExtension.h
+++ b/src/sksl/ir/SkSLExtension.h
@@ -16,8 +16,8 @@
  * An extension declaration.
  */
 struct Extension : public ProgramElement {
-    Extension(Position position, String name)
-    : INHERITED(position, kExtension_Kind)
+    Extension(int offset, String name)
+    : INHERITED(offset, kExtension_Kind)
     , fName(std::move(name)) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLField.h b/src/sksl/ir/SkSLField.h
index abea730..fe2af7f 100644
--- a/src/sksl/ir/SkSLField.h
+++ b/src/sksl/ir/SkSLField.h
@@ -22,8 +22,8 @@
  * result of declaring anonymous interface blocks.
  */
 struct Field : public Symbol {
-    Field(Position position, const Variable& owner, int fieldIndex)
-    : INHERITED(position, kField_Kind, owner.fType.fields()[fieldIndex].fName)
+    Field(int offset, const Variable& owner, int fieldIndex)
+    : INHERITED(offset, kField_Kind, owner.fType.fields()[fieldIndex].fName)
     , fOwner(owner)
     , fFieldIndex(fieldIndex) {}
 
diff --git a/src/sksl/ir/SkSLFieldAccess.h b/src/sksl/ir/SkSLFieldAccess.h
index e0a335f..0f66dec 100644
--- a/src/sksl/ir/SkSLFieldAccess.h
+++ b/src/sksl/ir/SkSLFieldAccess.h
@@ -26,7 +26,7 @@
 
     FieldAccess(std::unique_ptr<Expression> base, int fieldIndex,
                 OwnerKind ownerKind = kDefault_OwnerKind)
-    : INHERITED(base->fPosition, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType)
+    : INHERITED(base->fOffset, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType)
     , fBase(std::move(base))
     , fFieldIndex(fieldIndex)
     , fOwnerKind(ownerKind) {}
diff --git a/src/sksl/ir/SkSLFloatLiteral.h b/src/sksl/ir/SkSLFloatLiteral.h
index 21a485f..e6a3062 100644
--- a/src/sksl/ir/SkSLFloatLiteral.h
+++ b/src/sksl/ir/SkSLFloatLiteral.h
@@ -17,9 +17,9 @@
  * A literal floating point number.
  */
 struct FloatLiteral : public Expression {
-    FloatLiteral(const Context& context, Position position, double value,
+    FloatLiteral(const Context& context, int offset, double value,
                  const Type* type = nullptr)
-    : INHERITED(position, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type)
+    : INHERITED(offset, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLForStatement.h b/src/sksl/ir/SkSLForStatement.h
index ca3e6cf..6896ceb 100644
--- a/src/sksl/ir/SkSLForStatement.h
+++ b/src/sksl/ir/SkSLForStatement.h
@@ -18,10 +18,10 @@
  * A 'for' statement.
  */
 struct ForStatement : public Statement {
-    ForStatement(Position position, std::unique_ptr<Statement> initializer,
+    ForStatement(int offset, std::unique_ptr<Statement> initializer,
                  std::unique_ptr<Expression> test, std::unique_ptr<Expression> next,
                  std::unique_ptr<Statement> statement, std::shared_ptr<SymbolTable> symbols)
-    : INHERITED(position, kFor_Kind)
+    : INHERITED(offset, kFor_Kind)
     , fSymbols(symbols)
     , fInitializer(std::move(initializer))
     , fTest(std::move(test))
diff --git a/src/sksl/ir/SkSLFunctionCall.h b/src/sksl/ir/SkSLFunctionCall.h
index 44f8c7e..115281d 100644
--- a/src/sksl/ir/SkSLFunctionCall.h
+++ b/src/sksl/ir/SkSLFunctionCall.h
@@ -17,9 +17,9 @@
  * A function invocation.
  */
 struct FunctionCall : public Expression {
-    FunctionCall(Position position, const Type& type, const FunctionDeclaration& function,
+    FunctionCall(int offset, const Type& type, const FunctionDeclaration& function,
                  std::vector<std::unique_ptr<Expression>> arguments)
-    : INHERITED(position, kFunctionCall_Kind, type)
+    : INHERITED(offset, kFunctionCall_Kind, type)
     , fFunction(std::move(function))
     , fArguments(std::move(arguments)) {}
 
@@ -33,7 +33,7 @@
     }
 
     String description() const override {
-        String result = fFunction.fName + "(";
+        String result = String(fFunction.fName) + "(";
         String separator;
         for (size_t i = 0; i < fArguments.size(); i++) {
             result += separator;
diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h
index 64236d3..d0f9d24 100644
--- a/src/sksl/ir/SkSLFunctionDeclaration.h
+++ b/src/sksl/ir/SkSLFunctionDeclaration.h
@@ -21,9 +21,9 @@
  * A function declaration (not a definition -- does not contain a body).
  */
 struct FunctionDeclaration : public Symbol {
-    FunctionDeclaration(Position position, Modifiers modifiers, String name,
+    FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
                         std::vector<const Variable*> parameters, const Type& returnType)
-    : INHERITED(position, kFunctionDeclaration_Kind, std::move(name))
+    : INHERITED(offset, kFunctionDeclaration_Kind, std::move(name))
     , fDefined(false)
     , fBuiltin(false)
     , fModifiers(modifiers)
diff --git a/src/sksl/ir/SkSLFunctionDefinition.h b/src/sksl/ir/SkSLFunctionDefinition.h
index 0277db1..e0dabc5 100644
--- a/src/sksl/ir/SkSLFunctionDefinition.h
+++ b/src/sksl/ir/SkSLFunctionDefinition.h
@@ -18,9 +18,9 @@
  * A function definition (a declaration plus an associated block of code).
  */
 struct FunctionDefinition : public ProgramElement {
-    FunctionDefinition(Position position, const FunctionDeclaration& declaration,
+    FunctionDefinition(int offset, const FunctionDeclaration& declaration,
                        std::unique_ptr<Statement> body)
-    : INHERITED(position, kFunction_Kind)
+    : INHERITED(offset, kFunction_Kind)
     , fDeclaration(declaration)
     , fBody(std::move(body)) {}
 
diff --git a/src/sksl/ir/SkSLFunctionReference.h b/src/sksl/ir/SkSLFunctionReference.h
index ee761c2..58831c5 100644
--- a/src/sksl/ir/SkSLFunctionReference.h
+++ b/src/sksl/ir/SkSLFunctionReference.h
@@ -19,9 +19,9 @@
  * always eventually replaced by FunctionCalls in valid programs.
  */
 struct FunctionReference : public Expression {
-    FunctionReference(const Context& context, Position position,
+    FunctionReference(const Context& context, int offset,
                       std::vector<const FunctionDeclaration*> function)
-    : INHERITED(position, kFunctionReference_Kind, *context.fInvalid_Type)
+    : INHERITED(offset, kFunctionReference_Kind, *context.fInvalid_Type)
     , fFunctions(function) {}
 
     bool hasSideEffects() const override {
diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h
index 139be32..5ada506 100644
--- a/src/sksl/ir/SkSLIRNode.h
+++ b/src/sksl/ir/SkSLIRNode.h
@@ -8,7 +8,7 @@
 #ifndef SKSL_IRNODE
 #define SKSL_IRNODE
 
-#include "../SkSLPosition.h"
+#include "../SkSLLexer.h"
 
 namespace SkSL {
 
@@ -17,14 +17,16 @@
  * version of the program (all types determined, everything validated), ready for code generation.
  */
 struct IRNode {
-    IRNode(Position position)
-    : fPosition(position) {}
+    IRNode(int offset)
+    : fOffset(offset) {}
 
     virtual ~IRNode() {}
 
     virtual String description() const = 0;
 
-    const Position fPosition;
+    // character offset of this element within the program being compiled, for error reporting
+    // purposes
+    const int fOffset;
 };
 
 } // namespace
diff --git a/src/sksl/ir/SkSLIfStatement.h b/src/sksl/ir/SkSLIfStatement.h
index b09c10e..4c2ca0b 100644
--- a/src/sksl/ir/SkSLIfStatement.h
+++ b/src/sksl/ir/SkSLIfStatement.h
@@ -17,9 +17,9 @@
  * An 'if' statement.
  */
 struct IfStatement : public Statement {
-    IfStatement(Position position, bool isStatic, std::unique_ptr<Expression> test,
+    IfStatement(int offset, bool isStatic, std::unique_ptr<Expression> test,
                 std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)
-    : INHERITED(position, kIf_Kind)
+    : INHERITED(offset, kIf_Kind)
     , fIsStatic(isStatic)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h
index c305365..2daf1b5 100644
--- a/src/sksl/ir/SkSLIndexExpression.h
+++ b/src/sksl/ir/SkSLIndexExpression.h
@@ -45,7 +45,7 @@
 struct IndexExpression : public Expression {
     IndexExpression(const Context& context, std::unique_ptr<Expression> base,
                     std::unique_ptr<Expression> index)
-    : INHERITED(base->fPosition, kIndex_Kind, index_type(context, base->fType))
+    : INHERITED(base->fOffset, kIndex_Kind, index_type(context, base->fType))
     , fBase(std::move(base))
     , fIndex(std::move(index)) {
         ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type);
diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h
index 6199f96..da2b408 100644
--- a/src/sksl/ir/SkSLIntLiteral.h
+++ b/src/sksl/ir/SkSLIntLiteral.h
@@ -19,8 +19,8 @@
 struct IntLiteral : public Expression {
     // FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
     // 64-bit integers, but for right now an int64_t will hold every value we care about
-    IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr)
-    : INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
+    IntLiteral(const Context& context, int offset, int64_t value, const Type* type = nullptr)
+    : INHERITED(offset, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
     , fValue(value) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h
index a28a6a1..03986b8 100644
--- a/src/sksl/ir/SkSLInterfaceBlock.h
+++ b/src/sksl/ir/SkSLInterfaceBlock.h
@@ -25,10 +25,10 @@
  * At the IR level, this is represented by a single variable of struct type.
  */
 struct InterfaceBlock : public ProgramElement {
-    InterfaceBlock(Position position, const Variable* var, String typeName, String instanceName,
+    InterfaceBlock(int offset, const Variable* var, String typeName, String instanceName,
                    std::vector<std::unique_ptr<Expression>> sizes,
                    std::shared_ptr<SymbolTable> typeOwner)
-    : INHERITED(position, kInterfaceBlock_Kind)
+    : INHERITED(offset, kInterfaceBlock_Kind)
     , fVariable(*var)
     , fTypeName(std::move(typeName))
     , fInstanceName(std::move(instanceName))
diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h
index a0ce748..5c9608f 100644
--- a/src/sksl/ir/SkSLModifiersDeclaration.h
+++ b/src/sksl/ir/SkSLModifiersDeclaration.h
@@ -20,7 +20,7 @@
  */
 struct ModifiersDeclaration : public ProgramElement {
     ModifiersDeclaration(Modifiers modifiers)
-    : INHERITED(Position(), kModifiers_Kind)
+    : INHERITED(-1, kModifiers_Kind)
     , fModifiers(modifiers) {}
 
     String description() const {
diff --git a/src/sksl/ir/SkSLNop.h b/src/sksl/ir/SkSLNop.h
index 5ebea40..e7aae9b 100644
--- a/src/sksl/ir/SkSLNop.h
+++ b/src/sksl/ir/SkSLNop.h
@@ -18,7 +18,7 @@
  */
 struct Nop : public Statement {
     Nop()
-    : INHERITED(Position(), kNop_Kind) {}
+    : INHERITED(-1, kNop_Kind) {}
 
     virtual bool isEmpty() const override {
         return true;
diff --git a/src/sksl/ir/SkSLPostfixExpression.h b/src/sksl/ir/SkSLPostfixExpression.h
index e02555d..c53f1de 100644
--- a/src/sksl/ir/SkSLPostfixExpression.h
+++ b/src/sksl/ir/SkSLPostfixExpression.h
@@ -9,7 +9,7 @@
 #define SKSL_POSTFIXEXPRESSION
 
 #include "SkSLExpression.h"
-#include "SkSLToken.h"
+#include "SkSLLexer.h"
 
 namespace SkSL {
 
@@ -18,7 +18,7 @@
  */
 struct PostfixExpression : public Expression {
     PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
-    : INHERITED(operand->fPosition, kPostfix_Kind, operand->fType)
+    : INHERITED(operand->fOffset, kPostfix_Kind, operand->fType)
     , fOperand(std::move(operand))
     , fOperator(op) {}
 
@@ -27,7 +27,7 @@
     }
 
     String description() const override {
-        return fOperand->description() + Token::OperatorName(fOperator);
+        return fOperand->description() + Compiler::OperatorName(fOperator);
     }
 
     std::unique_ptr<Expression> fOperand;
diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h
index 5ac84c6..d5d97b2 100644
--- a/src/sksl/ir/SkSLPrefixExpression.h
+++ b/src/sksl/ir/SkSLPrefixExpression.h
@@ -11,7 +11,7 @@
 #include "SkSLExpression.h"
 #include "SkSLFloatLiteral.h"
 #include "SkSLIRGenerator.h"
-#include "SkSLToken.h"
+#include "SkSLLexer.h"
 
 namespace SkSL {
 
@@ -20,7 +20,7 @@
  */
 struct PrefixExpression : public Expression {
     PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
-    : INHERITED(operand->fPosition, kPrefix_Kind, operand->fType)
+    : INHERITED(operand->fOffset, kPrefix_Kind, operand->fType)
     , fOperand(std::move(operand))
     , fOperator(op) {}
 
@@ -38,7 +38,7 @@
         if (fOperand->fKind == Expression::kFloatLiteral_Kind) {
             return std::unique_ptr<Expression>(new FloatLiteral(
                                                               irGenerator.fContext,
-                                                              Position(),
+                                                              fOffset,
                                                               -((FloatLiteral&) *fOperand).fValue));
 
         }
@@ -46,7 +46,7 @@
     }
 
     String description() const override {
-        return Token::OperatorName(fOperator) + fOperand->description();
+        return Compiler::OperatorName(fOperator) + fOperand->description();
     }
 
     std::unique_ptr<Expression> fOperand;
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index a3eeaa3..639e09b 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -39,15 +39,15 @@
             : fKind(kInt_Kind)
             , fValue(i) {}
 
-            std::unique_ptr<Expression> literal(const Context& context, Position position) const {
+            std::unique_ptr<Expression> literal(const Context& context, int offset) const {
                 switch (fKind) {
                     case Program::Settings::Value::kBool_Kind:
                         return std::unique_ptr<Expression>(new BoolLiteral(context,
-                                                                           position,
+                                                                           offset,
                                                                            fValue));
                     case Program::Settings::Value::kInt_Kind:
                         return std::unique_ptr<Expression>(new IntLiteral(context,
-                                                                          position,
+                                                                          offset,
                                                                           fValue));
                     default:
                         ASSERT(false);
@@ -103,6 +103,7 @@
     };
 
     Program(Kind kind,
+            std::unique_ptr<String> source,
             Settings settings,
             Modifiers::Flag defaultPrecision,
             Context* context,
@@ -110,6 +111,7 @@
             std::shared_ptr<SymbolTable> symbols,
             Inputs inputs)
     : fKind(kind)
+    , fSource(std::move(source))
     , fSettings(settings)
     , fDefaultPrecision(defaultPrecision)
     , fContext(context)
@@ -118,6 +120,7 @@
     , fInputs(inputs) {}
 
     Kind fKind;
+    std::unique_ptr<String> fSource;
     Settings fSettings;
     // FIXME handle different types; currently it assumes this is for floats
     Modifiers::Flag fDefaultPrecision;
diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h
index 1e2bb48..4a3566d 100644
--- a/src/sksl/ir/SkSLProgramElement.h
+++ b/src/sksl/ir/SkSLProgramElement.h
@@ -25,8 +25,8 @@
         kSection_Kind
     };
 
-    ProgramElement(Position position, Kind kind)
-    : INHERITED(position)
+    ProgramElement(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     Kind fKind;
diff --git a/src/sksl/ir/SkSLReturnStatement.h b/src/sksl/ir/SkSLReturnStatement.h
index 841db94..1b479b8 100644
--- a/src/sksl/ir/SkSLReturnStatement.h
+++ b/src/sksl/ir/SkSLReturnStatement.h
@@ -17,11 +17,11 @@
  * A 'return' statement.
  */
 struct ReturnStatement : public Statement {
-    ReturnStatement(Position position)
-    : INHERITED(position, kReturn_Kind) {}
+    ReturnStatement(int offset)
+    : INHERITED(offset, kReturn_Kind) {}
 
     ReturnStatement(std::unique_ptr<Expression> expression)
-    : INHERITED(expression->fPosition, kReturn_Kind)
+    : INHERITED(expression->fOffset, kReturn_Kind)
     , fExpression(std::move(expression)) {}
 
     String description() const override {
diff --git a/src/sksl/ir/SkSLSection.h b/src/sksl/ir/SkSLSection.h
index f9815b1..96c257b 100644
--- a/src/sksl/ir/SkSLSection.h
+++ b/src/sksl/ir/SkSLSection.h
@@ -16,8 +16,8 @@
  * A section declaration (e.g. @body { body code here })..
  */
 struct Section : public ProgramElement {
-    Section(Position position, String name, String arg, String text)
-    : INHERITED(position, kSection_Kind)
+    Section(int offset, String name, String arg, String text)
+    : INHERITED(offset, kSection_Kind)
     , fName(std::move(name))
     , fArgument(std::move(arg))
     , fText(std::move(text)) {}
diff --git a/src/sksl/ir/SkSLSetting.h b/src/sksl/ir/SkSLSetting.h
index 995fcf5..f479ad1 100644
--- a/src/sksl/ir/SkSLSetting.h
+++ b/src/sksl/ir/SkSLSetting.h
@@ -18,8 +18,8 @@
  * collapsed down to their constant representations during the compilation process.
  */
 struct Setting : public Expression {
-    Setting(Position position, String name, std::unique_ptr<Expression> value)
-    : INHERITED(position, kSetting_Kind, value->fType)
+    Setting(int offset, String name, std::unique_ptr<Expression> value)
+    : INHERITED(offset, kSetting_Kind, value->fType)
     , fName(std::move(name))
     , fValue(std::move(value)) {
         ASSERT(fValue->isConstant());
diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h
index 1bc5244..a116cc1 100644
--- a/src/sksl/ir/SkSLStatement.h
+++ b/src/sksl/ir/SkSLStatement.h
@@ -35,8 +35,8 @@
         kWhile_Kind
     };
 
-    Statement(Position position, Kind kind)
-    : INHERITED(position)
+    Statement(int offset, Kind kind)
+    : INHERITED(offset)
     , fKind(kind) {}
 
     virtual bool isEmpty() const {
diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h
index 8043f2e..c33224b 100644
--- a/src/sksl/ir/SkSLSwitchCase.h
+++ b/src/sksl/ir/SkSLSwitchCase.h
@@ -17,9 +17,9 @@
  * A single case of a 'switch' statement.
  */
 struct SwitchCase : public Statement {
-    SwitchCase(Position position, std::unique_ptr<Expression> value,
+    SwitchCase(int offset, std::unique_ptr<Expression> value,
                std::vector<std::unique_ptr<Statement>> statements)
-    : INHERITED(position, kSwitch_Kind)
+    : INHERITED(offset, kSwitch_Kind)
     , fValue(std::move(value))
     , fStatements(std::move(statements)) {}
 
diff --git a/src/sksl/ir/SkSLSwitchStatement.h b/src/sksl/ir/SkSLSwitchStatement.h
index dec5b74..68d0ef0 100644
--- a/src/sksl/ir/SkSLSwitchStatement.h
+++ b/src/sksl/ir/SkSLSwitchStatement.h
@@ -17,10 +17,10 @@
  * A 'switch' statement.
  */
 struct SwitchStatement : public Statement {
-    SwitchStatement(Position position, bool isStatic, std::unique_ptr<Expression> value,
+    SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value,
                     std::vector<std::unique_ptr<SwitchCase>> cases,
                     const std::shared_ptr<SymbolTable> symbols)
-    : INHERITED(position, kSwitch_Kind)
+    : INHERITED(offset, kSwitch_Kind)
     , fIsStatic(isStatic)
     , fValue(std::move(value))
     , fSymbols(std::move(symbols))
diff --git a/src/sksl/ir/SkSLSwizzle.h b/src/sksl/ir/SkSLSwizzle.h
index 9d7ca37..3256ef2 100644
--- a/src/sksl/ir/SkSLSwizzle.h
+++ b/src/sksl/ir/SkSLSwizzle.h
@@ -65,7 +65,7 @@
  */
 struct Swizzle : public Expression {
     Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components)
-    : INHERITED(base->fPosition, kSwizzle_Kind, get_type(context, *base, components.size()))
+    : INHERITED(base->fOffset, kSwizzle_Kind, get_type(context, *base, components.size()))
     , fBase(std::move(base))
     , fComponents(std::move(components)) {
         ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4);
@@ -80,13 +80,13 @@
                 ASSERT(fComponents.size() == 1);
                 int64_t value = ((Constructor&) *fBase).getIVecComponent(fComponents[0]);
                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
-                                                                    Position(),
-                                                                    value));
+                                                                  -1,
+                                                                  value));
             } else if (fType == *irGenerator.fContext.fFloat_Type) {
                 ASSERT(fComponents.size() == 1);
                 double value = ((Constructor&) *fBase).getFVecComponent(fComponents[0]);
                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
-                                                                    Position(),
+                                                                    -1,
                                                                     value));
             }
         }
diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h
index e883ea7..f4c6753 100644
--- a/src/sksl/ir/SkSLSymbol.h
+++ b/src/sksl/ir/SkSLSymbol.h
@@ -24,13 +24,13 @@
         kField_Kind
     };
 
-    Symbol(Position position, Kind kind, String name)
-    : INHERITED(position)
+    Symbol(int offset, Kind kind, StringFragment name)
+    : INHERITED(offset)
     , fKind(kind)
-    , fName(std::move(name)) {}
+    , fName(name) {}
 
     const Kind fKind;
-    const String fName;
+    StringFragment fName;
 
     typedef IRNode INHERITED;
 };
diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp
index 4d39e8b..40e8e66 100644
--- a/src/sksl/ir/SkSLSymbolTable.cpp
+++ b/src/sksl/ir/SkSLSymbolTable.cpp
@@ -21,7 +21,7 @@
     }
 }
 
-const Symbol* SymbolTable::operator[](const String& name) {
+const Symbol* SymbolTable::operator[](StringFragment name) {
     const auto& entry = fSymbols.find(name);
     if (entry == fSymbols.end()) {
         if (fParent) {
@@ -64,12 +64,12 @@
     return s;
 }
 
-void SymbolTable::add(const String& name, std::unique_ptr<Symbol> symbol) {
+void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) {
     this->addWithoutOwnership(name, symbol.get());
     fOwnedPointers.push_back(std::move(symbol));
 }
 
-void SymbolTable::addWithoutOwnership(const String& name, const Symbol* symbol) {
+void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
     const auto& existing = fSymbols.find(name);
     if (existing == fSymbols.end()) {
         fSymbols[name] = symbol;
@@ -93,7 +93,7 @@
             this->takeOwnership(u);
         }
     } else {
-        fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined");
+        fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined");
     }
 }
 
diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h
index 6bafef2..241631d 100644
--- a/src/sksl/ir/SkSLSymbolTable.h
+++ b/src/sksl/ir/SkSLSymbolTable.h
@@ -31,11 +31,11 @@
     : fParent(parent)
     , fErrorReporter(*errorReporter) {}
 
-    const Symbol* operator[](const String& name);
+    const Symbol* operator[](StringFragment name);
 
-    void add(const String& name, std::unique_ptr<Symbol> symbol);
+    void add(StringFragment name, std::unique_ptr<Symbol> symbol);
 
-    void addWithoutOwnership(const String& name, const Symbol* symbol);
+    void addWithoutOwnership(StringFragment name, const Symbol* symbol);
 
     Symbol* takeOwnership(Symbol* s);
 
@@ -48,7 +48,7 @@
 
     std::vector<std::unique_ptr<Symbol>> fOwnedPointers;
 
-    std::unordered_map<String, const Symbol*> fSymbols;
+    std::unordered_map<StringFragment, const Symbol*> fSymbols;
 
     ErrorReporter& fErrorReporter;
 };
diff --git a/src/sksl/ir/SkSLTernaryExpression.h b/src/sksl/ir/SkSLTernaryExpression.h
index 567af56..282a322 100644
--- a/src/sksl/ir/SkSLTernaryExpression.h
+++ b/src/sksl/ir/SkSLTernaryExpression.h
@@ -17,9 +17,9 @@
  * A ternary expression (test ? ifTrue : ifFalse).
  */
 struct TernaryExpression : public Expression {
-    TernaryExpression(Position position, std::unique_ptr<Expression> test,
+    TernaryExpression(int offset, std::unique_ptr<Expression> test,
                       std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse)
-    : INHERITED(position, kTernary_Kind, ifTrue->fType)
+    : INHERITED(offset, kTernary_Kind, ifTrue->fType)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
     , fIfFalse(std::move(ifFalse)) {
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index 6ea4c56..b047421 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -27,9 +27,9 @@
 class Type : public Symbol {
 public:
     struct Field {
-        Field(Modifiers modifiers, String name, const Type* type)
+        Field(Modifiers modifiers, StringFragment name, const Type* type)
         : fModifiers(modifiers)
-        , fName(std::move(name))
+        , fName(name)
         , fType(std::move(type)) {}
 
         const String description() const {
@@ -37,7 +37,7 @@
         }
 
         Modifiers fModifiers;
-        String fName;
+        StringFragment fName;
         const Type* fType;
     };
 
@@ -62,40 +62,60 @@
     // Create an "other" (special) type with the given name. These types cannot be directly
     // referenced from user code.
     Type(String name)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kOther_Kind)
-    , fNumberKind(kNonnumeric_NumberKind) {}
+    , fNumberKind(kNonnumeric_NumberKind) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a generic type which maps to the listed types.
     Type(String name, std::vector<const Type*> types)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kGeneric_Kind)
     , fNumberKind(kNonnumeric_NumberKind)
-    , fCoercibleTypes(std::move(types)) {}
+    , fCoercibleTypes(std::move(types)) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a struct type with the given fields.
-    Type(Position position, String name, std::vector<Field> fields)
-    : INHERITED(position, kType_Kind, std::move(name))
+    Type(int offset, String name, std::vector<Field> fields)
+    : INHERITED(offset, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kStruct_Kind)
     , fNumberKind(kNonnumeric_NumberKind)
-    , fFields(std::move(fields)) {}
+    , fFields(std::move(fields)) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a scalar type.
     Type(String name, NumberKind numberKind)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kScalar_Kind)
     , fNumberKind(numberKind)
     , fColumns(1)
-    , fRows(1) {}
+    , fRows(1) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a scalar type which can be coerced to the listed types.
     Type(String name, NumberKind numberKind, std::vector<const Type*> coercibleTypes)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kScalar_Kind)
     , fNumberKind(numberKind)
     , fCoercibleTypes(std::move(coercibleTypes))
     , fColumns(1)
-    , fRows(1) {}
+    , fRows(1) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a vector type.
     Type(String name, const Type& componentType, int columns)
@@ -103,42 +123,54 @@
 
     // Create a vector or array type.
     Type(String name, Kind kind, const Type& componentType, int columns)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kind)
     , fNumberKind(kNonnumeric_NumberKind)
     , fComponentType(&componentType)
     , fColumns(columns)
     , fRows(1)
-    , fDimensions(SpvDim1D) {}
+    , fDimensions(SpvDim1D) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a matrix type.
     Type(String name, const Type& componentType, int columns, int rows)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kMatrix_Kind)
     , fNumberKind(kNonnumeric_NumberKind)
     , fComponentType(&componentType)
     , fColumns(columns)
     , fRows(rows)
-    , fDimensions(SpvDim1D) {}
+    , fDimensions(SpvDim1D) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     // Create a sampler type.
     Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
          bool isSampled)
-    : INHERITED(Position(), kType_Kind, std::move(name))
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(std::move(name))
     , fTypeKind(kSampler_Kind)
     , fNumberKind(kNonnumeric_NumberKind)
     , fDimensions(dimensions)
     , fIsDepth(isDepth)
     , fIsArrayed(isArrayed)
     , fIsMultisampled(isMultisampled)
-    , fIsSampled(isSampled) {}
+    , fIsSampled(isSampled) {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
 
     const String& name() const {
-        return fName;
+        return fNameString;
     }
 
     String description() const override {
-        return fName;
+        return fNameString;
     }
 
     bool operator==(const Type& other) const {
@@ -283,6 +315,7 @@
 private:
     typedef Symbol INHERITED;
 
+    const String fNameString;
     const Kind fTypeKind;
     // always kNonnumeric_NumberKind for non-scalar values
     const NumberKind fNumberKind;
diff --git a/src/sksl/ir/SkSLTypeReference.h b/src/sksl/ir/SkSLTypeReference.h
index eae1989..f7065b7 100644
--- a/src/sksl/ir/SkSLTypeReference.h
+++ b/src/sksl/ir/SkSLTypeReference.h
@@ -18,8 +18,8 @@
  * always eventually replaced by Constructors in valid programs.
  */
 struct TypeReference : public Expression {
-    TypeReference(const Context& context, Position position, const Type& type)
-    : INHERITED(position, kTypeReference_Kind, *context.fInvalid_Type)
+    TypeReference(const Context& context, int offset, const Type& type)
+    : INHERITED(offset, kTypeReference_Kind, *context.fInvalid_Type)
     , fValue(type) {}
 
     bool hasSideEffects() const override {
@@ -27,7 +27,7 @@
     }
 
     String description() const override {
-        return fValue.name();
+        return String(fValue.fName);
     }
 
     const Type& fValue;
diff --git a/src/sksl/ir/SkSLUnresolvedFunction.h b/src/sksl/ir/SkSLUnresolvedFunction.h
index b222bc3..62035da 100644
--- a/src/sksl/ir/SkSLUnresolvedFunction.h
+++ b/src/sksl/ir/SkSLUnresolvedFunction.h
@@ -17,7 +17,7 @@
  */
 struct UnresolvedFunction : public Symbol {
     UnresolvedFunction(std::vector<const FunctionDeclaration*> funcs)
-    : INHERITED(Position(), kUnresolvedFunction_Kind, funcs[0]->fName)
+    : INHERITED(-1, kUnresolvedFunction_Kind, funcs[0]->fName)
     , fFunctions(std::move(funcs)) {
 #ifdef DEBUG
         for (auto func : funcs) {
diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h
index 1eda87e..707715f 100644
--- a/src/sksl/ir/SkSLVarDeclarations.h
+++ b/src/sksl/ir/SkSLVarDeclarations.h
@@ -24,7 +24,7 @@
     VarDeclaration(const Variable* var,
                    std::vector<std::unique_ptr<Expression>> sizes,
                    std::unique_ptr<Expression> value)
-    : INHERITED(var->fPosition, Statement::kVarDeclaration_Kind)
+    : INHERITED(var->fOffset, Statement::kVarDeclaration_Kind)
     , fVar(var)
     , fSizes(std::move(sizes))
     , fValue(std::move(value)) {}
@@ -55,9 +55,9 @@
  * A variable declaration statement, which may consist of one or more individual variables.
  */
 struct VarDeclarations : public ProgramElement {
-    VarDeclarations(Position position, const Type* baseType,
+    VarDeclarations(int offset, const Type* baseType,
                     std::vector<std::unique_ptr<VarDeclaration>> vars)
-    : INHERITED(position, kVar_Kind)
+    : INHERITED(offset, kVar_Kind)
     , fBaseType(*baseType) {
         for (auto& var : vars) {
             fVars.push_back(std::unique_ptr<Statement>(var.release()));
diff --git a/src/sksl/ir/SkSLVarDeclarationsStatement.h b/src/sksl/ir/SkSLVarDeclarationsStatement.h
index a6a95a9..0258e66 100644
--- a/src/sksl/ir/SkSLVarDeclarationsStatement.h
+++ b/src/sksl/ir/SkSLVarDeclarationsStatement.h
@@ -18,7 +18,7 @@
  */
 struct VarDeclarationsStatement : public Statement {
     VarDeclarationsStatement(std::unique_ptr<VarDeclarations> decl)
-    : INHERITED(decl->fPosition, kVarDeclarations_Kind)
+    : INHERITED(decl->fOffset, kVarDeclarations_Kind)
     , fDeclaration(std::move(decl)) {}
 
     bool isEmpty() const override {
diff --git a/src/sksl/ir/SkSLVariable.h b/src/sksl/ir/SkSLVariable.h
index 05bba20..536d1e6 100644
--- a/src/sksl/ir/SkSLVariable.h
+++ b/src/sksl/ir/SkSLVariable.h
@@ -27,9 +27,9 @@
         kParameter_Storage
     };
 
-    Variable(Position position, Modifiers modifiers, String name, const Type& type,
+    Variable(int offset, Modifiers modifiers, StringFragment name, const Type& type,
              Storage storage)
-    : INHERITED(position, kVariable_Kind, std::move(name))
+    : INHERITED(offset, kVariable_Kind, name)
     , fModifiers(modifiers)
     , fType(type)
     , fStorage(storage)
diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h
index ba17437..54917b0 100644
--- a/src/sksl/ir/SkSLVariableReference.h
+++ b/src/sksl/ir/SkSLVariableReference.h
@@ -32,8 +32,8 @@
         kReadWrite_RefKind
     };
 
-    VariableReference(Position position, const Variable& variable, RefKind refKind = kRead_RefKind)
-    : INHERITED(position, kVariableReference_Kind, variable.fType)
+    VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind)
+    : INHERITED(offset, kVariableReference_Kind, variable.fType)
     , fVariable(variable)
     , fRefKind(refKind) {
         if (refKind != kRead_RefKind) {
@@ -83,18 +83,17 @@
         ASSERT(expr->isConstant());
         switch (expr->fKind) {
             case Expression::kIntLiteral_Kind:
-                return std::unique_ptr<Expression>(new IntLiteral(
-                                                                 irGenerator.fContext,
-                                                                 Position(),
-                                                                 ((IntLiteral*) expr)->fValue));
+                return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
+                                                                  -1,
+                                                                  ((IntLiteral*) expr)->fValue));
             case Expression::kFloatLiteral_Kind:
                 return std::unique_ptr<Expression>(new FloatLiteral(
-                                                               irGenerator.fContext,
-                                                               Position(),
-                                                               ((FloatLiteral*) expr)->fValue));
+                                                                   irGenerator.fContext,
+                                                                   -1,
+                                                                   ((FloatLiteral*) expr)->fValue));
             case Expression::kBoolLiteral_Kind:
                 return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
-                                                                   Position(),
+                                                                   -1,
                                                                    ((BoolLiteral*) expr)->fValue));
             case Expression::kConstructor_Kind: {
                 const Constructor* c = (const Constructor*) expr;
@@ -102,12 +101,12 @@
                 for (const auto& arg : c->fArguments) {
                     args.push_back(copy_constant(irGenerator, arg.get()));
                 }
-                return std::unique_ptr<Expression>(new Constructor(Position(), c->fType,
+                return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
                                                                    std::move(args)));
             }
             case Expression::kSetting_Kind: {
                 const Setting* s = (const Setting*) expr;
-                return std::unique_ptr<Expression>(new Setting(Position(), s->fName,
+                return std::unique_ptr<Expression>(new Setting(-1, s->fName,
                                                                copy_constant(irGenerator,
                                                                              s->fValue.get())));
             }
diff --git a/src/sksl/ir/SkSLWhileStatement.h b/src/sksl/ir/SkSLWhileStatement.h
index 6df1619..aed6494 100644
--- a/src/sksl/ir/SkSLWhileStatement.h
+++ b/src/sksl/ir/SkSLWhileStatement.h
@@ -17,9 +17,9 @@
  * A 'while' loop.
  */
 struct WhileStatement : public Statement {
-    WhileStatement(Position position, std::unique_ptr<Expression> test,
+    WhileStatement(int offset, std::unique_ptr<Expression> test,
                    std::unique_ptr<Statement> statement)
-    : INHERITED(position, kWhile_Kind)
+    : INHERITED(offset, kWhile_Kind)
     , fTest(std::move(test))
     , fStatement(std::move(statement)) {}
 
diff --git a/src/sksl/layout.flex b/src/sksl/layout.flex
deleted file mode 100644
index 4e6695c..0000000
--- a/src/sksl/layout.flex
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
-
-    This file is IGNORED during the build process!
-
-    As this file is updated so infrequently and flex is not universally present on build machines,
-    the lex.layout.c file must be manually regenerated if you make any changes to this file. Just
-    run:
-
-        flex layout.flex
-
-    You will have to manually add a copyright notice to the top of lex.layout.c.
-
-*/
-
-%option prefix="layout"
-%option reentrant
-%option yylineno
-%option never-interactive
-%option nounistd
-
-%{
-#include "SkSLToken.h"
-%}
-
-%%
-
-"location"                    { return SkSL::Token::LOCATION; }
-"offset"                      { return SkSL::Token::OFFSET; }
-"binding"                     { return SkSL::Token::BINDING; }
-"index"                       { return SkSL::Token::INDEX; }
-"set"                         { return SkSL::Token::SET; }
-"builtin"                     { return SkSL::Token::BUILTIN; }
-"input_attachment_index"      { return SkSL::Token::INPUT_ATTACHMENT_INDEX; }
-"origin_upper_left"           { return SkSL::Token::ORIGIN_UPPER_LEFT; }
-"override_coverage"           { return SkSL::Token::OVERRIDE_COVERAGE; }
-"blend_support_all_equations" { return SkSL::Token::BLEND_SUPPORT_ALL_EQUATIONS; }
-"push_constant"               { return SkSL::Token::PUSH_CONSTANT; }
-"points"                      { return SkSL::Token::POINTS; }
-"lines"                       { return SkSL::Token::LINES; }
-"line_strip"                  { return SkSL::Token::LINE_STRIP; }
-"lines_adjacency"             { return SkSL::Token::LINES_ADJACENCY; }
-"triangles"                   { return SkSL::Token::TRIANGLES; }
-"triangle_strip"              { return SkSL::Token::TRIANGLE_STRIP; }
-"triangles_adjacency"         { return SkSL::Token::TRIANGLES_ADJACENCY; }
-"max_vertices"                { return SkSL::Token::MAX_VERTICES; }
-"invocations"                 { return SkSL::Token::INVOCATIONS; }
-"when"                        { return SkSL::Token::WHEN; }
-"key"                         { return SkSL::Token::KEY; }
-
-. { return SkSL::Token::INVALID_TOKEN; }
-
-%%
-
-int layoutwrap(yyscan_t scanner) {
-    return 1; // terminate
-}
diff --git a/src/sksl/lex.layout.c b/src/sksl/lex.layout.c
deleted file mode 100644
index 63369fe..0000000
--- a/src/sksl/lex.layout.c
+++ /dev/null
@@ -1,2239 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#line 3 "lex.layout.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-/* TODO: this is always defined, so inline it */
-#define yyconst const
-
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define yynoreturn __attribute__((__noreturn__))
-#else
-#define yynoreturn
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE layoutrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
-     *       access to the local variable yy_act. Since yyless() is a macro, it would break
-     *       existing scanners that call yyless() from OUTSIDE layoutlex. 
-     *       One obvious solution it to make yy_act a global. I tried that, and saw
-     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
-     *       normally declared as a register variable-- so it is not worth it.
-     */
-    #define  YY_LESS_LINENO(n) \
-            do { \
-                int yyl;\
-                for ( yyl = n; yyl < yyleng; ++yyl )\
-                    if ( yytext[yyl] == '\n' )\
-                        --yylineno;\
-            }while(0)
-    #define YY_LINENO_REWIND_TO(dst) \
-            do {\
-                const char *p;\
-                for ( p = yy_cp-1; p >= (dst); --p)\
-                    if ( *p == '\n' )\
-                        --yylineno;\
-            }while(0)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	int yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via layoutrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void layoutrestart (FILE *input_file ,yyscan_t yyscanner );
-void layout_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE layout_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void layout_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void layout_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void layoutpop_buffer_state (yyscan_t yyscanner );
-
-static void layoutensure_buffer_stack (yyscan_t yyscanner );
-static void layout_load_buffer_state (yyscan_t yyscanner );
-static void layout_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER layout_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE layout_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE layout_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE layout_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *layoutalloc (yy_size_t ,yyscan_t yyscanner );
-void *layoutrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void layoutfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer layout_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        layoutensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        layoutensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (int) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 24
-#define YY_END_OF_BUFFER 25
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[211] =
-    {   0,
-        0,    0,   25,   23,   24,   23,   23,   23,   23,   23,
-       23,   23,   23,   23,   23,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,   22,    0,    0,
-        0,    0,    0,    0,    0,    0,    5,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,   21,    0,    0,    0,    4,    0,
-        0,    0,   13,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        2,    0,    0,   12,    0,    0,    3,    0,    6,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    1,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       16,    0,    0,    0,   14,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,   20,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,   19,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   11,    0,    0,    0,
-        0,    0,    0,    0,   17,    0,    0,    0,   15,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    8,
-        9,    0,    0,    0,    0,    0,    0,   18,    0,    0,
-
-        0,    0,    0,    7,    0,    0,    0,    0,   10,    0
-    } ;
-
-static yyconst YY_CHAR yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    3,    1,    4,    5,    6,    7,
-
-        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
-       18,   19,   20,   21,   22,   23,   24,   25,   26,   27,
-       28,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst YY_CHAR yy_meta[29] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_uint16_t yy_base[212] =
-    {   0,
-        0,   25,  227,  228,  228,    5,  209,  217,   13,  220,
-       24,   10,  215,  201,  210,  203,  211,  206,   17,  189,
-      199,  209,  187,  204,  200,  203,  198,  187,  185,  195,
-      198,  198,  187,  188,  194,  177,  182,  228,  191,  194,
-      194,  174,  185,  173,  176,  181,  228,  187,  173,  177,
-      181,  164,  159,  162,  178,   10,  160,  157,  173,  168,
-      158,  155,  174,  159,  228,  158,  171,  161,  228,  169,
-      167,  148,  166,  156,  159,  143,  148,  152,  141,  156,
-      151,  150,  137,  141,  153,  133,  132,  150,  135,  131,
-      228,  148,  143,  228,  131,  133,  228,  123,  228,  123,
-
-      133,  123,  136,  125,  118,  116,  131,  121,  129,  117,
-      112,  116,  121,  119,  228,  119,  111,  126,  106,   32,
-      108,  122,  108,  105,  119,  116,  102,  114,   96,   96,
-      114,   98,  109,   92,  228,  107,  104,  103,   92,  105,
-       85,  103,   85,   94,  228,   96,   81,   81,   76,   83,
-       78,   91,   74,   80,   78,  228,   91,   85,   69,   79,
-       77,   86,   80,   81,   71,   64,  228,   65,   79,   78,
-       64,   52,   71,   74,  228,   71,   61,   52,  228,   65,
-       63,   64,   56,   67,   46,   60,   50,   63,   53,  228,
-      228,   58,   55,   45,   33,   40,   52,  228,   34,   49,
-
-       52,   28,   30,  228,   40,   32,   29,   16,  228,  228,
-        0
-    } ;
-
-static yyconst flex_int16_t yy_def[212] =
-    {   0,
-      211,  211,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-
-      210,  210,  210,  210,  210,  210,  210,  210,  210,    0,
-      210
-    } ;
-
-static yyconst flex_uint16_t yy_nxt[257] =
-    {   0,
-        4,    5,  210,  210,    6,  210,  210,  210,  210,  210,
-      210,    7,   72,    8,    9,   10,   16,   11,   12,   17,
-      210,   13,   14,   35,   21,   15,    5,   27,   18,    6,
-       22,   73,   24,   28,  130,   36,    7,  209,    8,    9,
-       10,   37,   11,   12,   25,  208,   13,   14,   26,  207,
-       15,  206,  205,  131,  204,  203,  202,  201,  200,  199,
-      198,  197,  196,  195,  194,  193,  192,  191,  190,  189,
-      188,  187,  186,  185,  184,  183,  182,  181,  180,  179,
-      178,  177,  176,  175,  174,  173,  172,  171,  170,  169,
-      168,  167,  166,  165,  164,  163,  162,  161,  160,  159,
-
-      158,  157,  156,  155,  154,  153,  152,  151,  150,  149,
-      148,  147,  146,  145,  144,  143,  142,  141,  140,  139,
-      138,  137,  136,  135,  134,  133,  132,  129,  128,  127,
-      126,  125,  124,  123,  122,  121,  120,  119,  118,  117,
-      116,  115,  114,  113,  112,  111,  110,  109,  108,  107,
-      106,  105,  104,  103,  102,  101,  100,   99,   98,   97,
-       96,   95,   94,   93,   92,   91,   90,   89,   88,   87,
-       86,   85,   84,   83,   82,   81,   80,   79,   78,   77,
-       76,   75,   74,   71,   70,   69,   68,   67,   66,   65,
-       64,   63,   62,   61,   60,   59,   58,   57,   56,   55,
-
-       54,   53,   52,   51,   50,   49,   48,   47,   46,   45,
-       44,   43,   42,   41,   40,   39,   38,   34,   33,   32,
-       31,   30,   29,   23,   20,   19,  210,    3,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210
-    } ;
-
-static yyconst flex_int16_t yy_chk[257] =
-    {   0,
-      211,    1,    0,    0,    1,    0,    0,    0,    0,    0,
-        0,    1,   56,    1,    1,    1,    6,    1,    1,    6,
-        0,    1,    1,   19,    9,    1,    2,   12,    6,    2,
-        9,   56,   11,   12,  120,   19,    2,  208,    2,    2,
-        2,   19,    2,    2,   11,  207,    2,    2,   11,  206,
-        2,  205,  203,  120,  202,  201,  200,  199,  197,  196,
-      195,  194,  193,  192,  189,  188,  187,  186,  185,  184,
-      183,  182,  181,  180,  178,  177,  176,  174,  173,  172,
-      171,  170,  169,  168,  166,  165,  164,  163,  162,  161,
-      160,  159,  158,  157,  155,  154,  153,  152,  151,  150,
-
-      149,  148,  147,  146,  144,  143,  142,  141,  140,  139,
-      138,  137,  136,  134,  133,  132,  131,  130,  129,  128,
-      127,  126,  125,  124,  123,  122,  121,  119,  118,  117,
-      116,  114,  113,  112,  111,  110,  109,  108,  107,  106,
-      105,  104,  103,  102,  101,  100,   98,   96,   95,   93,
-       92,   90,   89,   88,   87,   86,   85,   84,   83,   82,
-       81,   80,   79,   78,   77,   76,   75,   74,   73,   72,
-       71,   70,   68,   67,   66,   64,   63,   62,   61,   60,
-       59,   58,   57,   55,   54,   53,   52,   51,   50,   49,
-       48,   46,   45,   44,   43,   42,   41,   40,   39,   37,
-
-       36,   35,   34,   33,   32,   31,   30,   29,   28,   27,
-       26,   25,   24,   23,   22,   21,   20,   18,   17,   16,
-       15,   14,   13,   10,    8,    7,    3,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210,  210,  210,  210,  210,
-      210,  210,  210,  210,  210,  210
-    } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[25] =
-    {   0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0,     };
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "layout.flex"
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-/*
-
-    This file is IGNORED during the build process!
-
-    As this file is updated so infrequently and flex is not universally present on build machines,
-    the lex.layout.c file must be manually regenerated if you make any changes to this file. Just
-    run:
-
-        flex layout.flex
-
-    You will have to manually add a copyright notice to the top of lex.layout.c.
-
-*/
-#define YY_NO_UNISTD_H 1
-#line 29 "layout.flex"
-#include "SkSLToken.h"
-#line 597 "lex.layout.c"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    int yy_n_chars;
-    int yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-int layoutlex_init (yyscan_t* scanner);
-
-int layoutlex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int layoutlex_destroy (yyscan_t yyscanner );
-
-int layoutget_debug (yyscan_t yyscanner );
-
-void layoutset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner );
-
-void layoutset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *layoutget_in (yyscan_t yyscanner );
-
-void layoutset_in  (FILE * _in_str ,yyscan_t yyscanner );
-
-FILE *layoutget_out (yyscan_t yyscanner );
-
-void layoutset_out  (FILE * _out_str ,yyscan_t yyscanner );
-
-			int layoutget_leng (yyscan_t yyscanner );
-
-char *layoutget_text (yyscan_t yyscanner );
-
-int layoutget_lineno (yyscan_t yyscanner );
-
-void layoutset_lineno (int _line_number ,yyscan_t yyscanner );
-
-int layoutget_column  (yyscan_t yyscanner );
-
-void layoutset_column (int _column_no ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int layoutwrap (yyscan_t yyscanner );
-#else
-extern int layoutwrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-    
-    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
-    
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int layoutlex (yyscan_t yyscanner);
-
-#define YY_DECL int layoutlex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK /*LINTED*/break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	yy_state_type yy_current_state;
-	char *yy_cp, *yy_bp;
-	int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( !yyg->yy_init )
-		{
-		yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yyg->yy_start )
-			yyg->yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			layoutensure_buffer_stack (yyscanner);
-			YY_CURRENT_BUFFER_LVALUE =
-				layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-		}
-
-		layout_load_buffer_state(yyscanner );
-		}
-
-	{
-#line 32 "layout.flex"
-
-
-#line 861 "lex.layout.c"
-
-	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yyg->yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yyg->yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yyg->yy_start;
-yy_match:
-		do
-			{
-			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
-			if ( yy_accept[yy_current_state] )
-				{
-				yyg->yy_last_accepting_state = yy_current_state;
-				yyg->yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 211 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-			++yy_cp;
-			}
-		while ( yy_current_state != 210 );
-		yy_cp = yyg->yy_last_accepting_cpos;
-		yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
-			{
-			yy_size_t yyl;
-			for ( yyl = 0; yyl < yyleng; ++yyl )
-				if ( yytext[yyl] == '\n' )
-					   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-			}
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yyg->yy_hold_char;
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 34 "layout.flex"
-{ return SkSL::Token::LOCATION; }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 35 "layout.flex"
-{ return SkSL::Token::OFFSET; }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 36 "layout.flex"
-{ return SkSL::Token::BINDING; }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 37 "layout.flex"
-{ return SkSL::Token::INDEX; }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 38 "layout.flex"
-{ return SkSL::Token::SET; }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 39 "layout.flex"
-{ return SkSL::Token::BUILTIN; }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 40 "layout.flex"
-{ return SkSL::Token::INPUT_ATTACHMENT_INDEX; }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 41 "layout.flex"
-{ return SkSL::Token::ORIGIN_UPPER_LEFT; }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 42 "layout.flex"
-{ return SkSL::Token::OVERRIDE_COVERAGE; }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 43 "layout.flex"
-{ return SkSL::Token::BLEND_SUPPORT_ALL_EQUATIONS; }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 44 "layout.flex"
-{ return SkSL::Token::PUSH_CONSTANT; }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 45 "layout.flex"
-{ return SkSL::Token::POINTS; }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 46 "layout.flex"
-{ return SkSL::Token::LINES; }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 47 "layout.flex"
-{ return SkSL::Token::LINE_STRIP; }
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 48 "layout.flex"
-{ return SkSL::Token::LINES_ADJACENCY; }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 49 "layout.flex"
-{ return SkSL::Token::TRIANGLES; }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 50 "layout.flex"
-{ return SkSL::Token::TRIANGLE_STRIP; }
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 51 "layout.flex"
-{ return SkSL::Token::TRIANGLES_ADJACENCY; }
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 52 "layout.flex"
-{ return SkSL::Token::MAX_VERTICES; }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 53 "layout.flex"
-{ return SkSL::Token::INVOCATIONS; }
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 54 "layout.flex"
-{ return SkSL::Token::WHEN; }
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 55 "layout.flex"
-{ return SkSL::Token::KEY; }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 57 "layout.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 59 "layout.flex"
-ECHO;
-	YY_BREAK
-#line 1046 "lex.layout.c"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yyg->yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * layoutlex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state( yyscanner );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yyg->yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yyg->yy_last_accepting_cpos;
-				yy_current_state = yyg->yy_last_accepting_state;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer( yyscanner ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yyg->yy_did_buffer_switch_on_eof = 0;
-
-				if ( layoutwrap(yyscanner ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yyg->yy_c_buf_p =
-					yyg->yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yyg->yy_c_buf_p =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-	} /* end of user's declarations */
-} /* end of layoutlex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	char *source = yyg->yytext_ptr;
-	yy_size_t number_to_move, i;
-	int ret_val;
-
-	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
-
-			int yy_c_buf_p_offset =
-				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					layoutrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = NULL;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	if ( yyg->yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			layoutrestart(yyin  ,yyscanner);
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	yyg->yy_n_chars += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-	yy_state_type yy_current_state;
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_current_state = yyg->yy_start;
-
-	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-		{
-		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yyg->yy_last_accepting_state = yy_current_state;
-			yyg->yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 211 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-	int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	char *yy_cp = yyg->yy_c_buf_p;
-
-	YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yyg->yy_last_accepting_state = yy_current_state;
-		yyg->yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 211 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-	yy_is_jam = (yy_current_state == 210);
-
-	(void)yyg;
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_UNPUT
-
-    static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
-{
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yy_cp = yyg->yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yyg->yy_hold_char;
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		int number_to_move = yyg->yy_n_chars + 2;
-		char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-    if ( c == '\n' ){
-        --yylineno;
-    }
-
-	yyg->yytext_ptr = yy_bp;
-	yyg->yy_hold_char = *yy_cp;
-	yyg->yy_c_buf_p = yy_cp;
-}
-
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-	int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	*yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			/* This was really a NUL. */
-			*yyg->yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-			++yyg->yy_c_buf_p;
-
-			switch ( yy_get_next_buffer( yyscanner ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					layoutrestart(yyin ,yyscanner);
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( layoutwrap(yyscanner ) )
-						return 0;
-
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput(yyscanner);
-#else
-					return input(yyscanner);
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
-	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
-	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-	if ( c == '\n' )
-		   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void layoutrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! YY_CURRENT_BUFFER ){
-        layoutensure_buffer_stack (yyscanner);
-		YY_CURRENT_BUFFER_LVALUE =
-            layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-	}
-
-	layout_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	layout_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void layout_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		layoutpop_buffer_state();
-	 *		layoutpush_buffer_state(new_buffer);
-     */
-	layoutensure_buffer_stack (yyscanner);
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	layout_load_buffer_state(yyscanner );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (layoutwrap()) processing, but the only time this flag
-	 * is looked at is after layoutwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void layout_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE layout_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) layoutalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" );
-
-	b->yy_buf_size = (yy_size_t)size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) layoutalloc(b->yy_buf_size + 2 ,yyscanner );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	layout_init_buffer(b,file ,yyscanner);
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with layout_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void layout_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		layoutfree((void *) b->yy_ch_buf ,yyscanner );
-
-	layoutfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a layoutrestart() or at EOF.
- */
-    static void layout_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-	int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	layout_flush_buffer(b ,yyscanner);
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then layout_init_buffer was _probably_
-     * called from layoutrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void layout_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		layout_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (new_buffer == NULL)
-		return;
-
-	layoutensure_buffer_stack(yyscanner);
-
-	/* This block is copied from layout_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		yyg->yy_buffer_stack_top++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from layout_switch_to_buffer. */
-	layout_load_buffer_state(yyscanner );
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void layoutpop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (!YY_CURRENT_BUFFER)
-		return;
-
-	layout_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if (yyg->yy_buffer_stack_top > 0)
-		--yyg->yy_buffer_stack_top;
-
-	if (YY_CURRENT_BUFFER) {
-		layout_load_buffer_state(yyscanner );
-		yyg->yy_did_buffer_switch_on_eof = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void layoutensure_buffer_stack (yyscan_t yyscanner)
-{
-	int num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if (!yyg->yy_buffer_stack) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)layoutalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" );
-								  
-		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		yyg->yy_buffer_stack_max = num_to_alloc;
-		yyg->yy_buffer_stack_top = 0;
-		return;
-	}
-
-	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		yy_size_t grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)layoutrealloc
-								(yyg->yy_buffer_stack,
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-		yyg->yy_buffer_stack_max = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE layout_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return NULL;
-
-	b = (YY_BUFFER_STATE) layoutalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in layout_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = NULL;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	layout_switch_to_buffer(b ,yyscanner );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to layoutlex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       layout_scan_bytes() instead.
- */
-YY_BUFFER_STATE layout_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-    
-	return layout_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to layoutlex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE layout_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	yy_size_t i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = (yy_size_t) _yybytes_len + 2;
-	buf = (char *) layoutalloc(n ,yyscanner );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in layout_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = layout_scan_buffer(buf,n ,yyscanner);
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in layout_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE layoutget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int layoutget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int layoutget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *layoutget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *layoutget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int layoutget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *layoutget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void layoutset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param _line_number line number
- * @param yyscanner The scanner object.
- */
-void layoutset_lineno (int  _line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "layoutset_lineno called with no buffer" );
-    
-    yylineno = _line_number;
-}
-
-/** Set the current column.
- * @param _column_no column number
- * @param yyscanner The scanner object.
- */
-void layoutset_column (int  _column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "layoutset_column called with no buffer" );
-    
-    yycolumn = _column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param _in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see layout_switch_to_buffer
- */
-void layoutset_in (FILE *  _in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = _in_str ;
-}
-
-void layoutset_out (FILE *  _out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = _out_str ;
-}
-
-int layoutget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void layoutset_debug (int  _bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = _bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* layoutlex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int layoutlex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* layoutlex_init_extra has the same functionality as layoutlex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to layoutalloc in
- * the yyextra field.
- */
-
-int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    layoutset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-	
-    *ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-    
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    layoutset_extra (yy_user_defined, *ptr_yy_globals);
-    
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from layoutlex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = NULL;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = NULL;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = NULL;
-    yyout = NULL;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * layoutlex_init()
-     */
-    return 0;
-}
-
-/* layoutlex_destroy is for both reentrant and non-reentrant scanners. */
-int layoutlex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		layout_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		layoutpop_buffer_state(yyscanner);
-	}
-
-	/* Destroy the stack itself. */
-	layoutfree(yyg->yy_buffer_stack ,yyscanner);
-	yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        layoutfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * layoutlex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    layoutfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-	int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *layoutalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	return malloc(size);
-}
-
-void *layoutrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return realloc(ptr, size);
-}
-
-void layoutfree (void * ptr , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	free( (char *) ptr );	/* see layoutrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 59 "layout.flex"
-
-
-
-int layoutwrap(yyscan_t scanner) {
-    return 1; // terminate
-}
-
diff --git a/src/sksl/lex.layout.cpp b/src/sksl/lex.layout.cpp
deleted file mode 100644
index 937c931..0000000
--- a/src/sksl/lex.layout.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "disable_flex_warnings.h"
-#include "lex.layout.c"
-static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 +
-              YY_FLEX_SUBMINOR_VERSION >= 20601,
-              "we require Flex 2.6.1 or better for security reasons");
diff --git a/src/sksl/lex.layout.h b/src/sksl/lex.layout.h
deleted file mode 100644
index 345b336..0000000
--- a/src/sksl/lex.layout.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-int layoutlex_init(yyscan_t* ptr_yy_globals);
-int layoutlex_destroy(void* scanner);
-YY_BUFFER_STATE layout_scan_string(const char* s, void* scanner);
-int layoutlex(void* yyscanner);
-void layout_delete_buffer(YY_BUFFER_STATE b, void* yyscanner);
diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c
deleted file mode 100644
index 6e44f5a..0000000
--- a/src/sksl/lex.sksl.c
+++ /dev/null
@@ -1,2682 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#line 3 "lex.sksl.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-/* TODO: this is always defined, so inline it */
-#define yyconst const
-
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define yynoreturn __attribute__((__noreturn__))
-#else
-#define yynoreturn
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE skslrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
-     *       access to the local variable yy_act. Since yyless() is a macro, it would break
-     *       existing scanners that call yyless() from OUTSIDE sksllex. 
-     *       One obvious solution it to make yy_act a global. I tried that, and saw
-     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
-     *       normally declared as a register variable-- so it is not worth it.
-     */
-    #define  YY_LESS_LINENO(n) \
-            do { \
-                int yyl;\
-                for ( yyl = n; yyl < yyleng; ++yyl )\
-                    if ( yytext[yyl] == '\n' )\
-                        --yylineno;\
-            }while(0)
-    #define YY_LINENO_REWIND_TO(dst) \
-            do {\
-                const char *p;\
-                for ( p = yy_cp-1; p >= (dst); --p)\
-                    if ( *p == '\n' )\
-                        --yylineno;\
-            }while(0)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	int yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via skslrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void skslrestart (FILE *input_file ,yyscan_t yyscanner );
-void sksl_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE sksl_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void sksl_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void sksl_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void skslpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void skslpop_buffer_state (yyscan_t yyscanner );
-
-static void skslensure_buffer_stack (yyscan_t yyscanner );
-static void sksl_load_buffer_state (yyscan_t yyscanner );
-static void sksl_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER sksl_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE sksl_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE sksl_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE sksl_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *skslalloc (yy_size_t ,yyscan_t yyscanner );
-void *skslrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void skslfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer sksl_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        skslensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        skslensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (int) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 99
-#define YY_END_OF_BUFFER 100
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[289] =
-    {   0,
-        0,    0,  100,   98,   95,   95,   69,   98,   42,   59,
-       64,   45,   46,   57,   55,   52,   56,   51,   58,    4,
-        4,   71,   92,   76,   72,   75,   70,   98,   49,   50,
-       63,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,   42,   47,
-       62,   48,   65,   95,   74,   43,   42,   83,   68,   88,
-       81,   53,   79,   54,   80,   93,    1,    0,   96,   82,
-        2,    4,    0,    0,   94,   60,   78,   73,   77,   61,
-       44,   44,   44,   87,   67,   42,   42,   42,   42,   42,
-       42,   13,   42,   42,   42,   42,   42,    8,   22,   42,
-
-       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   86,   66,   43,   91,    0,    0,
-        0,   96,    1,    0,    0,    3,    5,   84,   85,   44,
-        9,   44,   90,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   11,   42,   42,   42,   42,   42,   42,
-       23,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   89,    0,    1,   97,    0,    0,    2,
-       44,   42,   42,   16,   42,   42,   42,   42,   42,   10,
-       42,   30,   42,   42,   42,   27,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,    6,   42,   42,   42,   42,
-
-        0,    1,   44,   18,   42,   42,   26,   42,   42,   42,
-        7,   29,   24,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   12,   42,   44,   37,   42,
-       42,   42,   42,   40,   42,   42,   42,   42,   42,   21,
-       42,   39,   14,   42,   42,   42,   15,   42,   42,   17,
-       20,   28,   42,   42,   42,   42,   42,   25,   42,   42,
-       34,   19,   42,   42,   32,   36,   42,   35,   42,   42,
-       41,   42,   33,   42,   42,   42,   42,   42,   42,   31,
-       42,   42,   42,   42,   42,   42,   38,    0
-    } ;
-
-static yyconst YY_CHAR yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    1,    5,    6,    7,    8,    1,    9,
-       10,   11,   12,   13,   14,   15,   16,   17,   18,   18,
-       18,   18,   18,   18,   18,   18,   18,   19,   20,   21,
-       22,   23,   24,   25,   26,   26,   26,   26,   27,   26,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    6,    6,    6,
-       28,    1,   29,   30,   31,    1,   32,   33,   34,   35,
-
-       36,   37,   38,   39,   40,    6,   41,   42,   43,   44,
-       45,   46,    6,   47,   48,   49,   50,   51,   52,   53,
-       54,    6,   55,   56,   57,   58,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst YY_CHAR yy_meta[59] =
-    {   0,
-        1,    1,    2,    1,    1,    3,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    4,    4,    1,    1,
-        1,    1,    1,    1,    1,    5,    5,    1,    1,    1,
-        3,    5,    5,    5,    5,    5,    5,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_uint16_t yy_base[297] =
-    {   0,
-        0,    0,  360,  361,   57,   59,  337,    0,    0,  336,
-       55,  361,  361,  335,   52,  361,   53,   48,   57,   54,
-       65,  337,  361,   63,  333,   64,  361,   30,  361,  361,
-       66,   44,   57,   59,  312,   61,  313,   61,   65,  316,
-      306,  300,  302,  312,   59,  300,  302,  300,   70,  361,
-       90,  361,  361,  111,  361,    0,    0,  361,  322,  361,
-      361,  361,  361,  361,  361,  361,   98,  332,    0,  361,
-      101,  105,  112,    0,  361,  320,  361,  361,  361,  319,
-        0,  303,  287,  361,  316,  301,  299,  287,   92,  297,
-      285,    0,  284,  289,  298,  282,  290,    0,  282,  272,
-
-      273,  289,  277,  273,  285,   95,  289,  272,  278,  267,
-      276,  273,  274,  273,  361,  290,    0,  361,  121,  300,
-      294,    0,  130,  137,  135,  141,    0,  361,  361,    0,
-        0,  269,  361,  276,  270,  270,  269,  112,  272,  269,
-      266,  253,  251,    0,  260,  248,  252,  250,  255,  258,
-        0,  259,  257,  242,  240,  250,  238,  238,  250,  248,
-      252,  241,  233,  361,  145,  147,  361,  155,  153,  157,
-      232,  239,  243,    0,  231,  228,  236,  225,  242,    0,
-      237,    0,  226,  222,  220,    0,  219,  221,  227,  221,
-      218,  217,  231,  228,  227,    0,  215,  210,  222,  221,
-
-      159,  161,  222,    0,  208,  218,    0,  209,  210,  204,
-        0,    0,    0,  201,  206,  200,  199,  202,  205,  200,
-      195,  193,  202,  193,  199,    0,  193,  198,    0,  192,
-      185,  185,  198,    0,  186,  185,  190,  187,  194,    0,
-      196,    0,    0,  183,  183,  180,    0,  174,  186,    0,
-        0,    0,  185,  175,  165,  169,  169,    0,  180,  173,
-        0,    0,  180,  169,    0,    0,  172,    0,  157,  161,
-        0,  174,    0,  168,  171,  147,  156,  145,  132,    0,
-      119,  113,  109,  108,   91,   73,    0,  361,  177,  180,
-      183,  186,  191,  196,  198,  201
-
-    } ;
-
-static yyconst flex_int16_t yy_def[297] =
-    {   0,
-      288,    1,  288,  288,  288,  288,  288,  289,  290,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  291,  288,  288,
-      288,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  288,
-      288,  288,  288,  288,  288,  292,  290,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  293,  294,  288,
-      288,  288,  288,  295,  288,  288,  288,  288,  288,  288,
-      296,  296,  296,  288,  288,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  288,  288,  292,  288,  288,  293,
-      293,  294,  288,  288,  288,  288,  295,  288,  288,  296,
-      296,  296,  288,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  288,  288,  288,  288,  288,  288,  288,
-      296,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-
-      288,  288,  296,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  296,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  296,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,  290,  290,  290,
-      290,  290,  290,  290,  290,  290,  290,    0,  288,  288,
-      288,  288,  288,  288,  288,  288
-
-    } ;
-
-static yyconst flex_uint16_t yy_nxt[420] =
-    {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   15,   16,   17,   18,   19,   20,   21,   22,   23,
-       24,   25,   26,   27,   28,    9,    9,   29,   30,   31,
-        9,    9,   32,   33,   34,   35,   36,    9,   37,   38,
-        9,   39,   40,   41,   42,   43,   44,   45,   46,   47,
-       48,   49,    9,    9,   50,   51,   52,   53,   54,   54,
-       54,   54,   59,   62,   67,   67,   64,   68,   71,   82,
-       72,   72,   69,   63,   65,   66,   60,   83,   70,   71,
-       73,   72,   72,   76,   77,   79,   80,   84,   88,   73,
-       86,   73,   94,   87,   90,   85,  100,   98,   91,  107,
-
-       73,   89,   95,   92,   99,   96,   74,  108,  113,  101,
-      109,  115,   54,   54,   67,   67,  114,  123,  123,   71,
-      287,   72,   72,  125,  119,  125,  153,  124,  126,  126,
-      137,   73,  165,  119,  165,  138,  124,  166,  166,  286,
-       73,  285,  154,  155,  284,  116,  123,  123,  169,  283,
-      169,  126,  126,  170,  170,  282,  168,  126,  126,  176,
-      177,  166,  166,  166,  166,  168,  201,  281,  201,  170,
-      170,  202,  202,  170,  170,  202,  202,  202,  202,   56,
-      280,   56,   57,   57,   57,   81,  279,   81,  117,  117,
-      117,  120,  120,  120,  120,  120,  122,  278,  122,  122,
-
-      122,  127,  127,  130,  130,  130,  277,  276,  275,  274,
-      273,  272,  271,  270,  269,  268,  267,  266,  265,  264,
-      263,  262,  261,  260,  259,  258,  257,  256,  255,  254,
-      253,  252,  251,  250,  249,  248,  247,  246,  245,  244,
-      243,  242,  241,  240,  239,  238,  237,  236,  235,  234,
-      233,  232,  231,  230,  229,  228,  227,  226,  225,  224,
-      223,  222,  221,  220,  219,  218,  217,  216,  215,  214,
-      213,  212,  211,  210,  209,  208,  207,  206,  205,  204,
-      203,  200,  199,  198,  197,  196,  195,  194,  193,  192,
-      191,  190,  189,  188,  187,  186,  185,  184,  183,  182,
-
-      181,  180,  179,  178,  175,  174,  173,  172,  171,  167,
-      121,  164,  163,  162,  161,  160,  159,  158,  157,  156,
-      152,  151,  150,  149,  148,  147,  146,  145,  144,  143,
-      142,  141,  140,  139,  136,  135,  134,  133,  132,  131,
-      129,  128,  121,  118,  112,  111,  110,  106,  105,  104,
-      103,  102,   97,   93,   78,   75,   61,   58,   55,  288,
-        3,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288
-    } ;
-
-static yyconst flex_int16_t yy_chk[420] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    5,    5,
-        6,    6,   11,   15,   18,   18,   17,   19,   20,   28,
-       20,   20,   19,   15,   17,   17,   11,   28,   19,   21,
-       20,   21,   21,   24,   24,   26,   26,   31,   33,   20,
-       32,   21,   36,   32,   34,   31,   39,   38,   34,   45,
-
-       21,   33,   36,   34,   38,   36,   20,   45,   49,   39,
-       45,   51,   54,   54,   67,   67,   49,   71,   71,   72,
-      286,   72,   72,   73,   67,   73,  106,   71,   73,   73,
-       89,   72,  119,   67,  119,   89,   71,  119,  119,  285,
-       72,  284,  106,  106,  283,   51,  123,  123,  124,  282,
-      124,  125,  125,  124,  124,  281,  123,  126,  126,  138,
-      138,  165,  165,  166,  166,  123,  168,  279,  168,  169,
-      169,  168,  168,  170,  170,  201,  201,  202,  202,  289,
-      278,  289,  290,  290,  290,  291,  277,  291,  292,  292,
-      292,  293,  293,  293,  293,  293,  294,  276,  294,  294,
-
-      294,  295,  295,  296,  296,  296,  275,  274,  272,  270,
-      269,  267,  264,  263,  260,  259,  257,  256,  255,  254,
-      253,  249,  248,  246,  245,  244,  241,  239,  238,  237,
-      236,  235,  233,  232,  231,  230,  228,  227,  225,  224,
-      223,  222,  221,  220,  219,  218,  217,  216,  215,  214,
-      210,  209,  208,  206,  205,  203,  200,  199,  198,  197,
-      195,  194,  193,  192,  191,  190,  189,  188,  187,  185,
-      184,  183,  181,  179,  178,  177,  176,  175,  173,  172,
-      171,  163,  162,  161,  160,  159,  158,  157,  156,  155,
-      154,  153,  152,  150,  149,  148,  147,  146,  145,  143,
-
-      142,  141,  140,  139,  137,  136,  135,  134,  132,  121,
-      120,  116,  114,  113,  112,  111,  110,  109,  108,  107,
-      105,  104,  103,  102,  101,  100,   99,   97,   96,   95,
-       94,   93,   91,   90,   88,   87,   86,   85,   83,   82,
-       80,   76,   68,   59,   48,   47,   46,   44,   43,   42,
-       41,   40,   37,   35,   25,   22,   14,   10,    7,    3,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-
-      288,  288,  288,  288,  288,  288,  288,  288,  288,  288,
-      288,  288,  288,  288,  288,  288,  288,  288,  288
-    } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[100] =
-    {   0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 
-        };
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "sksl.flex"
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-/*
-
-    This file is IGNORED during the build process!
-
-    As this file is updated so infrequently and flex is not universally present on build machines,
-    the lex.sksl.c file must be manually regenerated if you make any changes to this file. Just run:
-
-        flex sksl.flex
-
-    You will have to manually add a copyright notice to the top of lex.sksl.c.
-
-*/
-#define YY_NO_UNISTD_H 1
-#line 663 "lex.sksl.c"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    int yy_n_chars;
-    int yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-int sksllex_init (yyscan_t* scanner);
-
-int sksllex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int sksllex_destroy (yyscan_t yyscanner );
-
-int skslget_debug (yyscan_t yyscanner );
-
-void skslset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE skslget_extra (yyscan_t yyscanner );
-
-void skslset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *skslget_in (yyscan_t yyscanner );
-
-void skslset_in  (FILE * _in_str ,yyscan_t yyscanner );
-
-FILE *skslget_out (yyscan_t yyscanner );
-
-void skslset_out  (FILE * _out_str ,yyscan_t yyscanner );
-
-			int skslget_leng (yyscan_t yyscanner );
-
-char *skslget_text (yyscan_t yyscanner );
-
-int skslget_lineno (yyscan_t yyscanner );
-
-void skslset_lineno (int _line_number ,yyscan_t yyscanner );
-
-int skslget_column  (yyscan_t yyscanner );
-
-void skslset_column (int _column_no ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int skslwrap (yyscan_t yyscanner );
-#else
-extern int skslwrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-    
-    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
-    
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int sksllex (yyscan_t yyscanner);
-
-#define YY_DECL int sksllex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK /*LINTED*/break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	yy_state_type yy_current_state;
-	char *yy_cp, *yy_bp;
-	int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( !yyg->yy_init )
-		{
-		yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yyg->yy_start )
-			yyg->yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			skslensure_buffer_stack (yyscanner);
-			YY_CURRENT_BUFFER_LVALUE =
-				sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-		}
-
-		sksl_load_buffer_state(yyscanner );
-		}
-
-	{
-#line 30 "sksl.flex"
-
-
-#line 927 "lex.sksl.c"
-
-	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yyg->yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yyg->yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yyg->yy_start;
-yy_match:
-		do
-			{
-			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
-			if ( yy_accept[yy_current_state] )
-				{
-				yyg->yy_last_accepting_state = yy_current_state;
-				yyg->yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 289 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-			++yy_cp;
-			}
-		while ( yy_current_state != 288 );
-		yy_cp = yyg->yy_last_accepting_cpos;
-		yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
-			{
-			yy_size_t yyl;
-			for ( yyl = 0; yyl < yyleng; ++yyl )
-				if ( yytext[yyl] == '\n' )
-					   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-			}
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yyg->yy_hold_char;
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 32 "sksl.flex"
-{ return SkSL::Token::FLOAT_LITERAL; }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 34 "sksl.flex"
-{ return SkSL::Token::FLOAT_LITERAL; }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 36 "sksl.flex"
-{ return SkSL::Token::FLOAT_LITERAL; }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 38 "sksl.flex"
-{ return SkSL::Token::INT_LITERAL; }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 40 "sksl.flex"
-{ return SkSL::Token::INT_LITERAL; }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 42 "sksl.flex"
-{ return SkSL::Token::TRUE_LITERAL; }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 44 "sksl.flex"
-{ return SkSL::Token::FALSE_LITERAL; }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 46 "sksl.flex"
-{ return SkSL::Token::IF; }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 48 "sksl.flex"
-{ return SkSL::Token::STATIC_IF; }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 50 "sksl.flex"
-{ return SkSL::Token::ELSE; }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 52 "sksl.flex"
-{ return SkSL::Token::FOR; }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 54 "sksl.flex"
-{ return SkSL::Token::WHILE; }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 56 "sksl.flex"
-{ return SkSL::Token::DO; }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 58 "sksl.flex"
-{ return SkSL::Token::SWITCH; }
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 60 "sksl.flex"
-{ return SkSL::Token::STATIC_SWITCH; }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 62 "sksl.flex"
-{ return SkSL::Token::CASE; }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 64 "sksl.flex"
-{ return SkSL::Token::DEFAULT; }
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 66 "sksl.flex"
-{ return SkSL::Token::BREAK; }
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 68 "sksl.flex"
-{ return SkSL::Token::CONTINUE; }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 70 "sksl.flex"
-{ return SkSL::Token::DISCARD; }
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 72 "sksl.flex"
-{ return SkSL::Token::RETURN; }
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 74 "sksl.flex"
-{ return SkSL::Token::IN; }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 76 "sksl.flex"
-{ return SkSL::Token::OUT; }
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 78 "sksl.flex"
-{ return SkSL::Token::INOUT; }
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 80 "sksl.flex"
-{ return SkSL::Token::UNIFORM; }
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 82 "sksl.flex"
-{ return SkSL::Token::CONST; }
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 84 "sksl.flex"
-{ return SkSL::Token::LOWP; }
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 86 "sksl.flex"
-{ return SkSL::Token::MEDIUMP; }
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 88 "sksl.flex"
-{ return SkSL::Token::HIGHP; }
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 90 "sksl.flex"
-{ return SkSL::Token::FLAT; }
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 92 "sksl.flex"
-{ return SkSL::Token::NOPERSPECTIVE; }
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 94 "sksl.flex"
-{ return SkSL::Token::READONLY; }
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 96 "sksl.flex"
-{ return SkSL::Token::WRITEONLY; }
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 98 "sksl.flex"
-{ return SkSL::Token::COHERENT; }
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 100 "sksl.flex"
-{ return SkSL::Token::VOLATILE; }
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 102 "sksl.flex"
-{ return SkSL::Token::RESTRICT; }
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 104 "sksl.flex"
-{ return SkSL::Token::BUFFER; }
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 106 "sksl.flex"
-{ return SkSL::Token::HASSIDEEFFECTS; }
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 108 "sksl.flex"
-{ return SkSL::Token::STRUCT; }
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 110 "sksl.flex"
-{ return SkSL::Token::LAYOUT; }
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 112 "sksl.flex"
-{ return SkSL::Token::PRECISION; }
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 114 "sksl.flex"
-{ return SkSL::Token::IDENTIFIER; }
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 116 "sksl.flex"
-{ return SkSL::Token::DIRECTIVE; }
-	YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 118 "sksl.flex"
-{ return SkSL::Token::SECTION; }
-	YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 120 "sksl.flex"
-{ return SkSL::Token::LPAREN; }
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 122 "sksl.flex"
-{ return SkSL::Token::RPAREN; }
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 124 "sksl.flex"
-{ return SkSL::Token::LBRACE; }
-	YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 126 "sksl.flex"
-{ return SkSL::Token::RBRACE; }
-	YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 128 "sksl.flex"
-{ return SkSL::Token::LBRACKET; }
-	YY_BREAK
-case 50:
-YY_RULE_SETUP
-#line 130 "sksl.flex"
-{ return SkSL::Token::RBRACKET; }
-	YY_BREAK
-case 51:
-YY_RULE_SETUP
-#line 132 "sksl.flex"
-{ return SkSL::Token::DOT; }
-	YY_BREAK
-case 52:
-YY_RULE_SETUP
-#line 134 "sksl.flex"
-{ return SkSL::Token::COMMA; }
-	YY_BREAK
-case 53:
-YY_RULE_SETUP
-#line 136 "sksl.flex"
-{ return SkSL::Token::PLUSPLUS; }
-	YY_BREAK
-case 54:
-YY_RULE_SETUP
-#line 138 "sksl.flex"
-{ return SkSL::Token::MINUSMINUS; }
-	YY_BREAK
-case 55:
-YY_RULE_SETUP
-#line 140 "sksl.flex"
-{ return SkSL::Token::PLUS; }
-	YY_BREAK
-case 56:
-YY_RULE_SETUP
-#line 142 "sksl.flex"
-{ return SkSL::Token::MINUS; }
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 144 "sksl.flex"
-{ return SkSL::Token::STAR; }
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 146 "sksl.flex"
-{ return SkSL::Token::SLASH; }
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 148 "sksl.flex"
-{ return SkSL::Token::PERCENT; }
-	YY_BREAK
-case 60:
-YY_RULE_SETUP
-#line 150 "sksl.flex"
-{ return SkSL::Token::SHL; }
-	YY_BREAK
-case 61:
-YY_RULE_SETUP
-#line 152 "sksl.flex"
-{ return SkSL::Token::SHR; }
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 154 "sksl.flex"
-{ return SkSL::Token::BITWISEOR; }
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 156 "sksl.flex"
-{ return SkSL::Token::BITWISEXOR; }
-	YY_BREAK
-case 64:
-YY_RULE_SETUP
-#line 158 "sksl.flex"
-{ return SkSL::Token::BITWISEAND; }
-	YY_BREAK
-case 65:
-YY_RULE_SETUP
-#line 160 "sksl.flex"
-{ return SkSL::Token::BITWISENOT; }
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 162 "sksl.flex"
-{ return SkSL::Token::LOGICALOR; }
-	YY_BREAK
-case 67:
-YY_RULE_SETUP
-#line 164 "sksl.flex"
-{ return SkSL::Token::LOGICALXOR; }
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 166 "sksl.flex"
-{ return SkSL::Token::LOGICALAND; }
-	YY_BREAK
-case 69:
-YY_RULE_SETUP
-#line 168 "sksl.flex"
-{ return SkSL::Token::LOGICALNOT; }
-	YY_BREAK
-case 70:
-YY_RULE_SETUP
-#line 170 "sksl.flex"
-{ return SkSL::Token::QUESTION; }
-	YY_BREAK
-case 71:
-YY_RULE_SETUP
-#line 172 "sksl.flex"
-{ return SkSL::Token::COLON; }
-	YY_BREAK
-case 72:
-YY_RULE_SETUP
-#line 174 "sksl.flex"
-{ return SkSL::Token::EQ; }
-	YY_BREAK
-case 73:
-YY_RULE_SETUP
-#line 176 "sksl.flex"
-{ return SkSL::Token::EQEQ; }
-	YY_BREAK
-case 74:
-YY_RULE_SETUP
-#line 178 "sksl.flex"
-{ return SkSL::Token::NEQ; }
-	YY_BREAK
-case 75:
-YY_RULE_SETUP
-#line 180 "sksl.flex"
-{ return SkSL::Token::GT; }
-	YY_BREAK
-case 76:
-YY_RULE_SETUP
-#line 182 "sksl.flex"
-{ return SkSL::Token::LT; }
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 184 "sksl.flex"
-{ return SkSL::Token::GTEQ; }
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 186 "sksl.flex"
-{ return SkSL::Token::LTEQ; }
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 188 "sksl.flex"
-{ return SkSL::Token::PLUSEQ; }
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 190 "sksl.flex"
-{ return SkSL::Token::MINUSEQ; }
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 192 "sksl.flex"
-{ return SkSL::Token::STAREQ; }
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 194 "sksl.flex"
-{ return SkSL::Token::SLASHEQ; }
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 196 "sksl.flex"
-{ return SkSL::Token::PERCENTEQ; }
-	YY_BREAK
-case 84:
-YY_RULE_SETUP
-#line 198 "sksl.flex"
-{ return SkSL::Token::SHLEQ; }
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 200 "sksl.flex"
-{ return SkSL::Token::SHREQ; }
-	YY_BREAK
-case 86:
-YY_RULE_SETUP
-#line 202 "sksl.flex"
-{ return SkSL::Token::BITWISEOREQ; }
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 204 "sksl.flex"
-{ return SkSL::Token::BITWISEXOREQ; }
-	YY_BREAK
-case 88:
-YY_RULE_SETUP
-#line 206 "sksl.flex"
-{ return SkSL::Token::BITWISEANDEQ; }
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 208 "sksl.flex"
-{ return SkSL::Token::LOGICALOREQ; }
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 210 "sksl.flex"
-{ return SkSL::Token::LOGICALXOREQ; }
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 212 "sksl.flex"
-{ return SkSL::Token::LOGICALANDEQ; }
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 214 "sksl.flex"
-{ return SkSL::Token::SEMICOLON; }
-	YY_BREAK
-case 93:
-YY_RULE_SETUP
-#line 216 "sksl.flex"
-{ return SkSL::Token::ARROW; }
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 218 "sksl.flex"
-{ return SkSL::Token::COLONCOLON; }
-	YY_BREAK
-case 95:
-/* rule 95 can match eol */
-YY_RULE_SETUP
-#line 220 "sksl.flex"
-{ return SkSL::Token::WHITESPACE; }
-	YY_BREAK
-case 96:
-YY_RULE_SETUP
-#line 222 "sksl.flex"
-/* line comment */
-	YY_BREAK
-case 97:
-/* rule 97 can match eol */
-YY_RULE_SETUP
-#line 224 "sksl.flex"
-/* block comment */
-	YY_BREAK
-case 98:
-YY_RULE_SETUP
-#line 226 "sksl.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
-	YY_BREAK
-case 99:
-YY_RULE_SETUP
-#line 228 "sksl.flex"
-ECHO;
-	YY_BREAK
-#line 1489 "lex.sksl.c"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yyg->yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * sksllex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state( yyscanner );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yyg->yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yyg->yy_last_accepting_cpos;
-				yy_current_state = yyg->yy_last_accepting_state;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer( yyscanner ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yyg->yy_did_buffer_switch_on_eof = 0;
-
-				if ( skslwrap(yyscanner ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yyg->yy_c_buf_p =
-					yyg->yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yyg->yy_c_buf_p =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-	} /* end of user's declarations */
-} /* end of sksllex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	char *source = yyg->yytext_ptr;
-	yy_size_t number_to_move, i;
-	int ret_val;
-
-	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
-
-			int yy_c_buf_p_offset =
-				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					skslrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = NULL;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	if ( yyg->yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			skslrestart(yyin  ,yyscanner);
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) skslrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	yyg->yy_n_chars += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-	yy_state_type yy_current_state;
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_current_state = yyg->yy_start;
-
-	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-		{
-		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yyg->yy_last_accepting_state = yy_current_state;
-			yyg->yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 289 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-	int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	char *yy_cp = yyg->yy_c_buf_p;
-
-	YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yyg->yy_last_accepting_state = yy_current_state;
-		yyg->yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 289 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-	yy_is_jam = (yy_current_state == 288);
-
-	(void)yyg;
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_UNPUT
-
-    static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
-{
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yy_cp = yyg->yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yyg->yy_hold_char;
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		int number_to_move = yyg->yy_n_chars + 2;
-		char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-    if ( c == '\n' ){
-        --yylineno;
-    }
-
-	yyg->yytext_ptr = yy_bp;
-	yyg->yy_hold_char = *yy_cp;
-	yyg->yy_c_buf_p = yy_cp;
-}
-
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-	int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	*yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			/* This was really a NUL. */
-			*yyg->yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-			++yyg->yy_c_buf_p;
-
-			switch ( yy_get_next_buffer( yyscanner ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					skslrestart(yyin ,yyscanner);
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( skslwrap(yyscanner ) )
-						return 0;
-
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput(yyscanner);
-#else
-					return input(yyscanner);
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
-	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
-	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-	if ( c == '\n' )
-		   
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void skslrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! YY_CURRENT_BUFFER ){
-        skslensure_buffer_stack (yyscanner);
-		YY_CURRENT_BUFFER_LVALUE =
-            sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-	}
-
-	sksl_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	sksl_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void sksl_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		skslpop_buffer_state();
-	 *		skslpush_buffer_state(new_buffer);
-     */
-	skslensure_buffer_stack (yyscanner);
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	sksl_load_buffer_state(yyscanner );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (skslwrap()) processing, but the only time this flag
-	 * is looked at is after skslwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void sksl_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE sksl_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) skslalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in sksl_create_buffer()" );
-
-	b->yy_buf_size = (yy_size_t)size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) skslalloc(b->yy_buf_size + 2 ,yyscanner );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in sksl_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	sksl_init_buffer(b,file ,yyscanner);
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with sksl_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void sksl_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		skslfree((void *) b->yy_ch_buf ,yyscanner );
-
-	skslfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a skslrestart() or at EOF.
- */
-    static void sksl_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-	int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	sksl_flush_buffer(b ,yyscanner);
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then sksl_init_buffer was _probably_
-     * called from skslrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void sksl_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		sksl_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void skslpush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (new_buffer == NULL)
-		return;
-
-	skslensure_buffer_stack(yyscanner);
-
-	/* This block is copied from sksl_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		yyg->yy_buffer_stack_top++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from sksl_switch_to_buffer. */
-	sksl_load_buffer_state(yyscanner );
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void skslpop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (!YY_CURRENT_BUFFER)
-		return;
-
-	sksl_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if (yyg->yy_buffer_stack_top > 0)
-		--yyg->yy_buffer_stack_top;
-
-	if (YY_CURRENT_BUFFER) {
-		sksl_load_buffer_state(yyscanner );
-		yyg->yy_did_buffer_switch_on_eof = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void skslensure_buffer_stack (yyscan_t yyscanner)
-{
-	int num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if (!yyg->yy_buffer_stack) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)skslalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in skslensure_buffer_stack()" );
-								  
-		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		yyg->yy_buffer_stack_max = num_to_alloc;
-		yyg->yy_buffer_stack_top = 0;
-		return;
-	}
-
-	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		yy_size_t grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)skslrealloc
-								(yyg->yy_buffer_stack,
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in skslensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-		yyg->yy_buffer_stack_max = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE sksl_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return NULL;
-
-	b = (YY_BUFFER_STATE) skslalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in sksl_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = NULL;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	sksl_switch_to_buffer(b ,yyscanner );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to sksllex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       sksl_scan_bytes() instead.
- */
-YY_BUFFER_STATE sksl_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-    
-	return sksl_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to sksllex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE sksl_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	yy_size_t i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = (yy_size_t) _yybytes_len + 2;
-	buf = (char *) skslalloc(n ,yyscanner );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in sksl_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = sksl_scan_buffer(buf,n ,yyscanner);
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in sksl_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE skslget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int skslget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int skslget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *skslget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *skslget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int skslget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *skslget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void skslset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param _line_number line number
- * @param yyscanner The scanner object.
- */
-void skslset_lineno (int  _line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "skslset_lineno called with no buffer" );
-    
-    yylineno = _line_number;
-}
-
-/** Set the current column.
- * @param _column_no column number
- * @param yyscanner The scanner object.
- */
-void skslset_column (int  _column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "skslset_column called with no buffer" );
-    
-    yycolumn = _column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param _in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see sksl_switch_to_buffer
- */
-void skslset_in (FILE *  _in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = _in_str ;
-}
-
-void skslset_out (FILE *  _out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = _out_str ;
-}
-
-int skslget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void skslset_debug (int  _bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = _bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* sksllex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int sksllex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) skslalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* sksllex_init_extra has the same functionality as sksllex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to skslalloc in
- * the yyextra field.
- */
-
-int sksllex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    skslset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-	
-    *ptr_yy_globals = (yyscan_t) skslalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-    
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    skslset_extra (yy_user_defined, *ptr_yy_globals);
-    
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from sksllex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = NULL;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = NULL;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = NULL;
-    yyout = NULL;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * sksllex_init()
-     */
-    return 0;
-}
-
-/* sksllex_destroy is for both reentrant and non-reentrant scanners. */
-int sksllex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		sksl_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		skslpop_buffer_state(yyscanner);
-	}
-
-	/* Destroy the stack itself. */
-	skslfree(yyg->yy_buffer_stack ,yyscanner);
-	yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        skslfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * sksllex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    skslfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-	int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *skslalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	return malloc(size);
-}
-
-void *skslrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return realloc(ptr, size);
-}
-
-void skslfree (void * ptr , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	free( (char *) ptr );	/* see skslrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 228 "sksl.flex"
-
-
-
-int skslwrap(yyscan_t scanner) {
-    return 1; // terminate
-}
-
diff --git a/src/sksl/lex/layout.lex b/src/sksl/lex/layout.lex
new file mode 100644
index 0000000..66d3088
--- /dev/null
+++ b/src/sksl/lex/layout.lex
@@ -0,0 +1,23 @@
+LOCATION                    = "location"
+OFFSET                      = "offset"
+BINDING                     = "binding"
+INDEX                       = "index"
+SET                         = "set"
+BUILTIN                     = "builtin"
+INPUT_ATTACHMENT_INDEX      = "input_attachment_index"
+ORIGIN_UPPER_LEFT           = "origin_upper_left"
+OVERRIDE_COVERAGE           = "override_coverage"
+BLEND_SUPPORT_ALL_EQUATIONS = "blend_support_all_equations"
+PUSH_CONSTANT               = "push_constant"
+POINTS                      = "points"
+LINES                       = "lines"
+LINE_STRIP                  = "line_strip"
+LINES_ADJACENCY             = "lines_adjacency"
+TRIANGLES                   = "triangles"
+TRIANGLE_STRIP              = "triangle_strip"
+TRIANGLES_ADJACENCY         = "triangles_adjacency"
+MAX_VERTICES                = "max_vertices"
+INVOCATIONS                 = "invocations"
+WHEN                        = "when"
+KEY                         = "key"
+INVALID                     = .
diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex
deleted file mode 100644
index 275a4e6..0000000
--- a/src/sksl/sksl.flex
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
-
-    This file is IGNORED during the build process!
-
-    As this file is updated so infrequently and flex is not universally present on build machines,
-    the lex.sksl.c file must be manually regenerated if you make any changes to this file. Just run:
-
-        flex sksl.flex
-
-    You will have to manually add a copyright notice to the top of lex.sksl.c.
-
-*/
-
-%option prefix="sksl"
-%option reentrant
-%option yylineno
-%option never-interactive
-%option nounistd
-
-DIGIT  [0-9]
-LETTER [a-zA-Z_$]
-
-%%
-
-{DIGIT}*"."{DIGIT}+([eE][+-]?{DIGIT}+)? { return SkSL::Token::FLOAT_LITERAL; }
-
-{DIGIT}+"."{DIGIT}*([eE][+-]?{DIGIT}+)? { return SkSL::Token::FLOAT_LITERAL; }
-
-{DIGIT}+([eE][+-]?{DIGIT}+) { return SkSL::Token::FLOAT_LITERAL; }
-
-{DIGIT}+ { return SkSL::Token::INT_LITERAL; }
-
-"0x"[0-9a-fA-F]+ { return SkSL::Token::INT_LITERAL; }
-
-true { return SkSL::Token::TRUE_LITERAL; }
-
-false { return SkSL::Token::FALSE_LITERAL; }
-
-if { return SkSL::Token::IF; }
-
-@if { return SkSL::Token::STATIC_IF; }
-
-else { return SkSL::Token::ELSE; }
-
-for { return SkSL::Token::FOR; }
-
-while { return SkSL::Token::WHILE; }
-
-do { return SkSL::Token::DO; }
-
-switch { return SkSL::Token::SWITCH; }
-
-@switch { return SkSL::Token::STATIC_SWITCH; }
-
-case { return SkSL::Token::CASE; }
-
-default { return SkSL::Token::DEFAULT; }
-
-break { return SkSL::Token::BREAK; }
-
-continue { return SkSL::Token::CONTINUE; }
-
-discard { return SkSL::Token::DISCARD; }
-
-return { return SkSL::Token::RETURN; }
-
-in { return SkSL::Token::IN; }
-
-out { return SkSL::Token::OUT; }
-
-inout { return SkSL::Token::INOUT; }
-
-uniform { return SkSL::Token::UNIFORM; }
-
-const { return SkSL::Token::CONST; }
-
-lowp { return SkSL::Token::LOWP; }
-
-mediump { return SkSL::Token::MEDIUMP; }
-
-highp { return SkSL::Token::HIGHP; }
-
-flat { return SkSL::Token::FLAT; }
-
-noperspective { return SkSL::Token::NOPERSPECTIVE; }
-
-readonly { return SkSL::Token::READONLY; }
-
-writeonly { return SkSL::Token::WRITEONLY; }
-
-coherent { return SkSL::Token::COHERENT; }
-
-volatile { return SkSL::Token::VOLATILE; }
-
-restrict { return SkSL::Token::RESTRICT; }
-
-buffer { return SkSL::Token::BUFFER; }
-
-sk_has_side_effects { return SkSL::Token::HASSIDEEFFECTS; }
-
-struct { return SkSL::Token::STRUCT; }
-
-layout { return SkSL::Token::LAYOUT; }
-
-precision { return SkSL::Token::PRECISION; }
-
-{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::IDENTIFIER; }
-
-"#"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::DIRECTIVE; }
-
-"@"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::SECTION; }
-
-"(" { return SkSL::Token::LPAREN; }
-
-")" { return SkSL::Token::RPAREN; }
-
-"{" { return SkSL::Token::LBRACE; }
-
-"}" { return SkSL::Token::RBRACE; }
-
-"[" { return SkSL::Token::LBRACKET; }
-
-"]" { return SkSL::Token::RBRACKET; }
-
-"." { return SkSL::Token::DOT; }
-
-"," { return SkSL::Token::COMMA; }
-
-"++" { return SkSL::Token::PLUSPLUS; }
-
-"--" { return SkSL::Token::MINUSMINUS; }
-
-"+" { return SkSL::Token::PLUS; }
-
-"-" { return SkSL::Token::MINUS; }
-
-"*" { return SkSL::Token::STAR; }
-
-"/" { return SkSL::Token::SLASH; }
-
-"%" { return SkSL::Token::PERCENT; }
-
-"<<" { return SkSL::Token::SHL; }
-
-">>" { return SkSL::Token::SHR; }
-
-"|" { return SkSL::Token::BITWISEOR; }
-
-"^" { return SkSL::Token::BITWISEXOR; }
-
-"&" { return SkSL::Token::BITWISEAND; }
-
-"~" { return SkSL::Token::BITWISENOT; }
-
-"||" { return SkSL::Token::LOGICALOR; }
-
-"^^" { return SkSL::Token::LOGICALXOR; }
-
-"&&" { return SkSL::Token::LOGICALAND; }
-
-"!" { return SkSL::Token::LOGICALNOT; }
-
-"?" { return SkSL::Token::QUESTION; }
-
-":" { return SkSL::Token::COLON; }
-
-"=" { return SkSL::Token::EQ; }
-
-"==" { return SkSL::Token::EQEQ; }
-
-"!=" { return SkSL::Token::NEQ; }
-
-">" { return SkSL::Token::GT; }
-
-"<" { return SkSL::Token::LT; }
-
-">=" { return SkSL::Token::GTEQ; }
-
-"<=" { return SkSL::Token::LTEQ; }
-
-"+=" { return SkSL::Token::PLUSEQ; }
-
-"-=" { return SkSL::Token::MINUSEQ; }
-
-"*=" { return SkSL::Token::STAREQ; }
-
-"/=" { return SkSL::Token::SLASHEQ; }
-
-"%=" { return SkSL::Token::PERCENTEQ; }
-
-"<<=" { return SkSL::Token::SHLEQ; }
-
-">>=" { return SkSL::Token::SHREQ; }
-
-"|=" { return SkSL::Token::BITWISEOREQ; }
-
-"^=" { return SkSL::Token::BITWISEXOREQ; }
-
-"&=" { return SkSL::Token::BITWISEANDEQ; }
-
-"||=" { return SkSL::Token::LOGICALOREQ; }
-
-"^^=" { return SkSL::Token::LOGICALXOREQ; }
-
-"&&=" { return SkSL::Token::LOGICALANDEQ; }
-
-";" { return SkSL::Token::SEMICOLON; }
-
-"->" { return SkSL::Token::ARROW; }
-
-"::" { return SkSL::Token::COLONCOLON; }
-
-[ \t\r\n]+ { return SkSL::Token::WHITESPACE; }
-
-"//".* /* line comment */
-
-"/*"([^*]|"*"[^/])*"*/" /* block comment */
-
-.    { return SkSL::Token::INVALID_TOKEN; }
-
-%%
-
-int skslwrap(yyscan_t scanner) {
-    return 1; // terminate
-}
diff --git a/tests/SkSLMemoryLayoutTest.cpp b/tests/SkSLMemoryLayoutTest.cpp
index 80188e6..ef13835 100644
--- a/tests/SkSLMemoryLayoutTest.cpp
+++ b/tests/SkSLMemoryLayoutTest.cpp
@@ -54,30 +54,30 @@
 
     // struct 1
     std::vector<SkSL::Type::Field> fields1;
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fFloat3_Type.get());
-    SkSL::Type s1(SkSL::Position(), SkSL::String("s1"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fFloat3_Type.get());
+    SkSL::Type s1(-1, SkSL::String("s1"), fields1);
     REPORTER_ASSERT(r, 16 == layout.size(s1));
     REPORTER_ASSERT(r, 16 == layout.alignment(s1));
 
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat_Type.get());
-    SkSL::Type s2(SkSL::Position(), SkSL::String("s2"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat_Type.get());
+    SkSL::Type s2(-1, SkSL::String("s2"), fields1);
     REPORTER_ASSERT(r, 16 == layout.size(s2));
     REPORTER_ASSERT(r, 16 == layout.alignment(s2));
 
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("c"), context.fBool_Type.get());
-    SkSL::Type s3(SkSL::Position(), SkSL::String("s3"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("c"), context.fBool_Type.get());
+    SkSL::Type s3(-1, SkSL::String("s3"), fields1);
     REPORTER_ASSERT(r, 32 == layout.size(s3));
     REPORTER_ASSERT(r, 16 == layout.alignment(s3));
 
     // struct 2
     std::vector<SkSL::Type::Field> fields2;
-    fields2.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fInt_Type.get());
-    SkSL::Type s4(SkSL::Position(), SkSL::String("s4"), fields2);
+    fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fInt_Type.get());
+    SkSL::Type s4(-1, SkSL::String("s4"), fields2);
     REPORTER_ASSERT(r, 16 == layout.size(s4));
     REPORTER_ASSERT(r, 16 == layout.alignment(s4));
 
-    fields2.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat3_Type.get());
-    SkSL::Type s5(SkSL::Position(), SkSL::String("s5"), fields2);
+    fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat3_Type.get());
+    SkSL::Type s5(-1, SkSL::String("s5"), fields2);
     REPORTER_ASSERT(r, 32 == layout.size(s5));
     REPORTER_ASSERT(r, 16 == layout.alignment(s5));
 
@@ -135,30 +135,30 @@
 
     // struct 1
     std::vector<SkSL::Type::Field> fields1;
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fFloat3_Type.get());
-    SkSL::Type s1(SkSL::Position(), SkSL::String("s1"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fFloat3_Type.get());
+    SkSL::Type s1(-1, SkSL::String("s1"), fields1);
     REPORTER_ASSERT(r, 16 == layout.size(s1));
     REPORTER_ASSERT(r, 16 == layout.alignment(s1));
 
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat_Type.get());
-    SkSL::Type s2(SkSL::Position(), SkSL::String("s2"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat_Type.get());
+    SkSL::Type s2(-1, SkSL::String("s2"), fields1);
     REPORTER_ASSERT(r, 16 == layout.size(s2));
     REPORTER_ASSERT(r, 16 == layout.alignment(s2));
 
-    fields1.emplace_back(SkSL::Modifiers(), SkSL::String("c"), context.fBool_Type.get());
-    SkSL::Type s3(SkSL::Position(), SkSL::String("s3"), fields1);
+    fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("c"), context.fBool_Type.get());
+    SkSL::Type s3(-1, SkSL::String("s3"), fields1);
     REPORTER_ASSERT(r, 32 == layout.size(s3));
     REPORTER_ASSERT(r, 16 == layout.alignment(s3));
 
     // struct 2
     std::vector<SkSL::Type::Field> fields2;
-    fields2.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fInt_Type.get());
-    SkSL::Type s4(SkSL::Position(), SkSL::String("s4"), fields2);
+    fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fInt_Type.get());
+    SkSL::Type s4(-1, SkSL::String("s4"), fields2);
     REPORTER_ASSERT(r, 4 == layout.size(s4));
     REPORTER_ASSERT(r, 4 == layout.alignment(s4));
 
-    fields2.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat3_Type.get());
-    SkSL::Type s5(SkSL::Position(), SkSL::String("s5"), fields2);
+    fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat3_Type.get());
+    SkSL::Type s5(-1, SkSL::String("s5"), fields2);
     REPORTER_ASSERT(r, 32 == layout.size(s5));
     REPORTER_ASSERT(r, 16 == layout.alignment(s5));