diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-09-11 16:33:48 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-11 16:34:02 +0000 |
commit | 358515491a0d6891e6a709688a30ad087df1beb1 (patch) | |
tree | ce64223230053df7db85c94b848ad526e64269cd | |
parent | c576e93d174f3106e072a2f506bca3990b541265 (diff) |
Revert "Switch to the new SkSL lexer."
This reverts commit c576e93d174f3106e072a2f506bca3990b541265.
Reason for revert: ASAN failures
Original change's description:
> Switch to the new SkSL lexer.
>
> This completely replaces flex with a new in-house lexical analyzer generator,
> which we have done for performance and memory usage reasons. Flex requires us
> to copy strings every time we need the text of a token, whereas this new lexer
> allows us to handle strings as a (non-null-terminated) pointer and length
> everywhere, eliminating most string copies.
>
> Bug: skia:
> Change-Id: I2add26efc9e20cb699520e82abcf713af3968aca
> Reviewed-on: https://skia-review.googlesource.com/39780
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
TBR=bsalomon@google.com,ethannicholas@google.com
Change-Id: If27b750a5f696d06a6bcffed12fe9f0598e084a6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/44881
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
126 files changed, 6492 insertions, 4967 deletions
@@ -45,7 +45,6 @@ declare_args() { 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 = "" @@ -412,7 +411,7 @@ optional("fontmgr_fuchsia") { ] } -if (skia_lex) { +if (skia_compile_processors) { executable("sksllex") { sources = [ "src/sksl/lex/Main.cpp", @@ -423,38 +422,6 @@ if (skia_lex) { 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 = [ @@ -515,7 +482,6 @@ optional("gpu") { enabled = skia_enable_gpu deps = [ ":compile_processors", - ":run_sksllex", ] public_defines = [] diff --git a/gn/run_sksllex.py b/gn/run_sksllex.py deleted file mode 100644 index 0377283b5a..0000000000 --- a/gn/run_sksllex.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/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 65913e3417..c1b6abaf02 100644 --- a/gn/sksl.gni +++ b/gn/sksl.gni @@ -9,16 +9,15 @@ _src = get_path_info("../src", "abspath") skia_sksl_sources = [ "$_src/sksl/SkSLCFGGenerator.cpp", "$_src/sksl/SkSLCompiler.cpp", - "$_src/sksl/SkSLCPPCodeGenerator.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/SkSLCPPCodeGenerator.cpp", + "$_src/sksl/SkSLHCodeGenerator.cpp", + "$_src/sksl/SkSLGLSLCodeGenerator.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 aebb7d35e8..96961cf6e5 100644 --- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp +++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp @@ -130,7 +130,7 @@ std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCrea 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 75d73bdbd0..7cec3cc431 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -13,13 +13,11 @@ #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); @@ -30,11 +28,8 @@ static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize 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) { @@ -44,8 +39,6 @@ static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHa } } -// 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; @@ -55,8 +48,7 @@ void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR 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); @@ -72,10 +64,6 @@ void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR } } -// 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; @@ -95,28 +83,18 @@ static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int 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); @@ -132,36 +110,34 @@ static uint8_t* create_circle_profile(float sigma, float circleR, int profileTex 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; } @@ -170,13 +146,9 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource 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; @@ -187,10 +159,8 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource *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; @@ -218,7 +188,6 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource 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 30391450d8..e9443a8d00 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -72,9 +72,7 @@ private: 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 6e8fa28efc..8d3fba12bb 100644 --- a/src/gpu/effects/GrSimpleTextureEffect.h +++ b/src/gpu/effects/GrSimpleTextureEffect.h @@ -30,7 +30,6 @@ public: 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 5fd4229457..e8964db0bc 100644 --- a/src/sksl/SkSLCFGGenerator.cpp +++ b/src/sksl/SkSLCFGGenerator.cpp @@ -319,7 +319,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool break; } default: - this->addExpression(cfg, &b->fLeft, !Compiler::IsAssignment(b->fOperator)); + this->addExpression(cfg, &b->fLeft, !Token::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 e84954ee85..17bcf0d11f 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -14,7 +14,7 @@ namespace SkSL { static bool needs_uniform_var(const Variable& var) { return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) && - var.fType.fName != "colorSpaceXform"; + strcmp(var.fType.fName.c_str(), "colorSpaceXform"); } CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program, @@ -58,7 +58,7 @@ void CPPCodeGenerator::writeType(const Type& type) { if (type.kind() == Type::kStruct_Kind) { INHERITED::writeType(type); } else { - this->write(type.fName); + this->write(type.name()); } } void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b, @@ -87,7 +87,7 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) { if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) { this->write("%s"); if (i.fIndex->fKind != Expression::kIntLiteral_Kind) { - fErrors.error(i.fIndex->fOffset, + fErrors.error(i.fIndex->fPosition, "index into sk_TransformedCoords2D must be an integer literal"); return; } @@ -104,7 +104,7 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) { } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) { this->write("%s"); if (i.fIndex->fKind != Expression::kIntLiteral_Kind) { - fErrors.error(i.fIndex->fOffset, + fErrors.error(i.fIndex->fPosition, "index into sk_TextureSamplers must be an integer literal"); return; } @@ -118,15 +118,16 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) { } static const char* default_value(const Type& type) { - if (type.fName == "float") { + const char* name = type.name().c_str(); + if (!strcmp(name, "float")) { return "0.0"; - } else if (type.fName == "float2") { + } else if (!strcmp(name, "float2")) { return "float2(0.0)"; - } else if (type.fName == "float3") { + } else if (!strcmp(name, "float3")) { return "float30.0)"; - } else if (type.fName == "float4") { + } else if (!strcmp(name, "float4")) { return "float4(0.0)"; - } else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") { + } else if (!strcmp(name, "floatt4x4") || !strcmp(name, "colorSpaceXform")) { return "float4x4(1.0)"; } ABORT("unsupported default_value type\n"); @@ -154,8 +155,7 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode fFormatArgs.push_back(cppCode + ".fX"); fFormatArgs.push_back(cppCode + ".fY"); } else { - this->write(type.fName); - this->write("\n"); + printf("%s\n", type.name().c_str()); ABORT("unsupported runtime value type\n"); } } @@ -227,11 +227,11 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) { } fFormatArgs.push_back(code); } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) { - String name(ref.fVariable.fName); + const char* name = ref.fVariable.fName.c_str(); this->writeRuntimeValue(ref.fVariable.fType, - String::printf("_outer.%s()", name.c_str()).c_str()); + String::printf("_outer.%s()", name).c_str()); } else { - this->write(ref.fVariable.fName); + this->write(ref.fVariable.fName.c_str()); } } } @@ -358,16 +358,14 @@ void CPPCodeGenerator::addUniform(const Variable& var) { var.fType == *fContext.fColorSpaceXform_Type) { type = "kMat44f_GrSLType"; } else { - ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(), - String(var.fName).c_str()); + ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str()); } if (var.fModifiers.fLayout.fWhen.size()) { this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str()); } - String name(var.fName); + const char* name = var.fName.c_str(); this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, " - "%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision, - name.c_str()); + "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name); if (var.fModifiers.fLayout.fWhen.size()) { this->write(" }\n"); } @@ -382,7 +380,7 @@ void CPPCodeGenerator::writePrivateVars() { if (is_private(*decl.fVar)) { this->writef("%s %s;\n", HCodeGenerator::FieldType(decl.fVar->fType).c_str(), - String(decl.fVar->fName).c_str()); + decl.fVar->fName.c_str()); } } } @@ -397,7 +395,7 @@ void CPPCodeGenerator::writePrivateVarValues() { VarDeclaration& decl = (VarDeclaration&) *raw; if (is_private(*decl.fVar) && decl.fValue) { this->writef("%s = %s;\n", - String(decl.fVar->fName).c_str(), + decl.fVar->fName.c_str(), decl.fValue->description().c_str()); } } @@ -416,12 +414,12 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) { this->addUniform(*u); if (u->fType == *fContext.fColorSpaceXform_Type) { if (fNeedColorSpaceHelper) { - fErrors.error(u->fOffset, "only a single ColorSpaceXform is supported"); + fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported"); } fNeedColorSpaceHelper = true; this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, " "_outer.%s().get());\n", - String(u->fName).c_str()); + u->fName.c_str()); } } this->writeSection(EMIT_CODE_SECTION); @@ -455,8 +453,7 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { wroteProcessor = true; this->writef(" {\n"); } - String nameString(u->fName); - const char* name = nameString.c_str(); + const char* name = u->fName.c_str(); if (u->fType == *fContext.fFloat4_Type) { this->writef(" const SkRect %sValue = _outer.%s();\n" " %s.set4fv(%sVar, 1, (float*) &%sValue);\n", @@ -488,13 +485,13 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { 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); @@ -515,14 +512,14 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { void CPPCodeGenerator::writeClone() { if (!this->writeSection(CLONE_SECTION)) { if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) { - fErrors.error(0, "fragment processors with custom @fields must also have a custom" - "@clone"); + fErrors.error(Position(1, 1), "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(String(param->fName).c_str()); + String fieldName = HCodeGenerator::FieldName(param->fName.c_str()); this->writef("\n, %s(%s)", fieldName.c_str(), ("src." + fieldName).c_str()); @@ -538,7 +535,7 @@ void CPPCodeGenerator::writeClone() { for (const auto& param : fSectionAndParameterHelper.getParameters()) { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", - HCodeGenerator::FieldName(String(param->fName).c_str()).c_str()); + HCodeGenerator::FieldName(param->fName.c_str()).c_str()); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -575,8 +572,7 @@ void CPPCodeGenerator::writeGetKey() { "GrProcessorKeyBuilder* b) const {\n", fFullName.c_str()); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - String nameString(param->fName); - const char* name = nameString.c_str(); + const char* name = param->fName.c_str(); if (param->fType == *fContext.fColorSpaceXform_Type) { this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n", HCodeGenerator::FieldName(name).c_str()); @@ -584,7 +580,7 @@ void CPPCodeGenerator::writeGetKey() { } if (param->fModifiers.fLayout.fKey != Layout::kNo_Key && (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) { - fErrors.error(param->fOffset, + fErrors.error(param->fPosition, "layout(key) may not be specified on uniforms"); } switch (param->fModifiers.fLayout.fKey) { @@ -612,7 +608,7 @@ void CPPCodeGenerator::writeGetKey() { break; case Layout::kIdentity_Key: if (param->fType.kind() != Type::kMatrix_Kind) { - fErrors.error(param->fOffset, + fErrors.error(param->fPosition, "layout(key=identity) requires matrix type"); } this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n", @@ -660,15 +656,15 @@ bool CPPCodeGenerator::generateCode() { 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(String(u->fName).c_str()).c_str()); + this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).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(String(param->fName).c_str()).c_str()); + this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str()); } } if (fNeedColorSpaceHelper) { @@ -685,8 +681,7 @@ bool CPPCodeGenerator::generateCode() { " (void) that;\n", fullName, fullName, fullName); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - String nameString(param->fName); - const char* name = nameString.c_str(); + const char* name = param->fName.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 638e4d64bf..4ea956ce0f 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -51,6 +51,7 @@ static const char* SKSL_FP_INCLUDE = #include "sksl_fp.include" ; + namespace SkSL { Compiler::Compiler(Flags flags) @@ -186,23 +187,20 @@ Compiler::Compiler(Flags flags) ADD_TYPE(GSamplerCubeArrayShadow); ADD_TYPE(ColorSpaceXform); - StringFragment skCapsName("sk_Caps"); - Variable* skCaps = new Variable(-1, Modifiers(), skCapsName, + String skCapsName("sk_Caps"); + Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName, *fContext.fSkCaps_Type, Variable::kGlobal_Storage); fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); - StringFragment skArgsName("sk_Args"); - Variable* skArgs = new Variable(-1, Modifiers(), skArgsName, + String skArgsName("sk_Args"); + Variable* skArgs = new Variable(Position(), 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(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); + fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); - if (fErrorCount) { - printf("Unexpected errors: %s\n", fErrorText.c_str()); - } ASSERT(!fErrorCount); } @@ -262,7 +260,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node, BinaryExpression* b = (BinaryExpression*) expr; if (b->fOperator == Token::EQ) { this->addDefinition(b->fLeft.get(), &b->fRight, definitions); - } else if (Compiler::IsAssignment(b->fOperator)) { + } else if (Token::IsAssignment(b->fOperator)) { this->addDefinition( b->fLeft.get(), (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, @@ -403,7 +401,7 @@ static bool is_dead(const Expression& lvalue) { * to a dead target and lack of side effects on the left hand side. */ static bool dead_assignment(const BinaryExpression& b) { - if (!Compiler::IsAssignment(b.fOperator)) { + if (!Token::IsAssignment(b.fOperator)) { return false; } return is_dead(*b.fLeft); @@ -542,7 +540,7 @@ void delete_right(BasicBlock* b, 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(-1, type, std::move(args))); + auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); return result; } @@ -644,7 +642,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions, if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] && (*undefinedVariables).find(&var) == (*undefinedVariables).end()) { (*undefinedVariables).insert(&var); - this->error(expr->fOffset, + this->error(expr->fPosition, "'" + var.fName + "' has not been assigned"); } break; @@ -879,7 +877,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* for (const auto& s : statementPtrs) { statements.push_back(std::move(*s)); } - return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols)); + return std::unique_ptr<Statement>(new Block(Position(), std::move(statements), s->fSymbols)); } void Compiler::simplifyStatement(DefinitionMap& definitions, @@ -966,7 +964,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions, break; } else { if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fOffset, + this->error(s.fPosition, "static switch contains non-static conditional break"); s.fIsStatic = false; } @@ -982,7 +980,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions, (*iter)->setStatement(std::move(newBlock)); } else { if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fOffset, + this->error(s.fPosition, "static switch contains non-static conditional break"); s.fIsStatic = false; } @@ -1024,16 +1022,16 @@ void Compiler::scanCFG(FunctionDefinition& f) { for (size_t i = 0; i < cfg.fBlocks.size(); i++) { if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() && cfg.fBlocks[i].fNodes.size()) { - int offset; + Position p; switch (cfg.fBlocks[i].fNodes[0].fKind) { case BasicBlock::Node::kStatement_Kind: - offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset; + p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition; break; case BasicBlock::Node::kExpression_Kind: - offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset; + p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition; break; } - this->error(offset, String("unreachable")); + this->error(p, String("unreachable")); } } if (fErrorCount) { @@ -1083,14 +1081,14 @@ void Compiler::scanCFG(FunctionDefinition& f) { case Statement::kIf_Kind: if (((const IfStatement&) s).fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fOffset, "static if has non-static test"); + this->error(s.fPosition, "static if has non-static test"); } ++iter; break; case Statement::kSwitch_Kind: if (((const SwitchStatement&) s).fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fOffset, "static switch has non-static test"); + this->error(s.fPosition, "static switch has non-static test"); } ++iter; break; @@ -1123,7 +1121,7 @@ void Compiler::scanCFG(FunctionDefinition& f) { // check for missing return if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) { if (cfg.fBlocks[cfg.fExit].fEntrances.size()) { - this->error(f.fOffset, String("function can exit without returning a value")); + this->error(f.fPosition, String("function can exit without returning a value")); } } } @@ -1137,28 +1135,21 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex Modifiers::Flag ignored; switch (kind) { case Program::kVertex_Kind: - fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes, - &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements); break; case Program::kFragment_Kind: - fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes, - &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements); break; case Program::kGeometry_Kind: - fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes, - &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements); break; case Program::kFragmentProcessor_Kind: - fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, - &ignored, &elements); + fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements); break; } fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); Modifiers::Flag defaultPrecision; - std::unique_ptr<String> textPtr(new String(std::move(text))); - fSource = textPtr.get(); - fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &defaultPrecision, - &elements); + fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements); if (!fErrorCount) { for (auto& element : elements) { if (element->fKind == ProgramElement::kFunction_Kind) { @@ -1166,13 +1157,11 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex } } } - auto result = std::unique_ptr<Program>(new Program(kind, std::move(textPtr), settings, - defaultPrecision, &fContext, + auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext, std::move(elements), fIRGenerator->fSymbolTable, fIRGenerator->fInputs)); fIRGenerator->finish(); - fSource = nullptr; this->writeErrorCount(); if (fErrorCount) { return nullptr; @@ -1183,10 +1172,8 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex 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(); @@ -1201,10 +1188,8 @@ bool Compiler::toSPIRV(const Program& program, OutputStream& out) { 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; @@ -1220,10 +1205,8 @@ bool Compiler::toSPIRV(const Program& program, String* out) { } 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; } @@ -1238,111 +1221,22 @@ bool Compiler::toGLSL(const Program& program, String* out) { } 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; } -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) { +void Compiler::error(Position position, String msg) { fErrorCount++; - Position pos = this->position(offset); - fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n"; + fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n"; } String Compiler::errorText() { diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 894ac41092..38f63e542c 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -16,6 +16,7 @@ #include "SkSLCFGGenerator.h" #include "SkSLContext.h" #include "SkSLErrorReporter.h" +#include "SkSLIRGenerator.h" #define SK_FRAGCOLOR_BUILTIN 10001 #define SK_IN_BUILTIN 10002 @@ -69,7 +70,7 @@ public: bool toH(const Program& program, String name, OutputStream& out); - void error(int offset, String msg) override; + void error(Position position, String msg) override; String errorText(); @@ -79,10 +80,6 @@ public: 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); @@ -117,14 +114,11 @@ private: 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 e421695f11..b132cec33d 100644 --- a/src/sksl/SkSLContext.h +++ b/src/sksl/SkSLContext.h @@ -19,172 +19,172 @@ namespace SkSL { class Context { public: Context() - : 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, + : 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, false, true)) - , 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, + , 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, true)) - , 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")) + , 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"))) // Related to below FIXME, gsampler*s don't currently expand to cover integer case. - , fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true)) + , fISampler2D_Type(new Type(String("isampler2D"), SpvDim2D, false, false, false, true)) // FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D. - , fImage2D_Type(new Type("image2D", SpvDim2D, false, false, false, true)) - , fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true)) + , fImage2D_Type(new Type(String("image2D"), SpvDim2D, false, false, false, true)) + , fIImage2D_Type(new Type(String("iimage2D"), SpvDim2D, false, false, false, true)) // FIXME express these as "gsubpassInput" that expand to subpassInput, isubpassInput, // and usubpassInput. - , fSubpassInput_Type(new Type("subpassInput", SpvDimSubpassData, false, false, - false, false)) - , fSubpassInputMS_Type(new Type("subpassInputMS", SpvDimSubpassData, false, false, - true, false)) + , fSubpassInput_Type(new Type(String("subpassInput"), SpvDimSubpassData, false, false, + false, false)) + , fSubpassInputMS_Type(new Type(String("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("$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", + , 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"), static_type(*fSampler1DArray_Type))) - , fGSampler2DArray_Type(new Type("$gsampler2DArray", + , fGSampler2DArray_Type(new Type(String("$gsampler2DArray"), static_type(*fSampler2DArray_Type))) - , fGSamplerCubeArray_Type(new Type("$gsamplerCubeArray", + , fGSamplerCubeArray_Type(new Type(String("$gsamplerCubeArray"), static_type(*fSamplerCubeArray_Type))) - , fGSamplerBuffer_Type(new Type("$gsamplerBuffer", static_type(*fSamplerBuffer_Type))) - , fGSampler2DMS_Type(new Type("$gsampler2DMS", static_type(*fSampler2DMS_Type))) - , fGSampler2DMSArray_Type(new Type("$gsampler2DMSArray", + , 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"), static_type(*fSampler2DMSArray_Type))) - , fGSampler2DArrayShadow_Type(new Type("$gsampler2DArrayShadow", + , fGSampler2DArrayShadow_Type(new Type(String("$gsampler2DArrayShadow"), static_type(*fSampler2DArrayShadow_Type))) - , fGSamplerCubeArrayShadow_Type(new Type("$gsamplerCubeArrayShadow", + , fGSamplerCubeArrayShadow_Type(new Type(String("$gsamplerCubeArrayShadow"), static_type(*fSamplerCubeArrayShadow_Type))) - , fGenType_Type(new Type("$genType", { fFloat_Type.get(), fFloat2_Type.get(), + , 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(), fFloat3_Type.get(), fFloat4_Type.get() })) - , fGenHType_Type(new Type("$genHType", { fHalf_Type.get(), fHalf2_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(), fHalf3_Type.get(), fHalf4_Type.get() })) - , fGenDType_Type(new Type("$genDType", { fDouble_Type.get(), fDouble2_Type.get(), + , fDVec_Type(new Type(String("$dvec"), { fInvalid_Type.get(), fDouble2_Type.get(), fDouble3_Type.get(), fDouble4_Type.get() })) - , fGenIType_Type(new Type("$genIType", { fInt_Type.get(), fInt2_Type.get(), + , fIVec_Type(new Type(String("$ivec"), { fInvalid_Type.get(), fInt2_Type.get(), fInt3_Type.get(), fInt4_Type.get() })) - , fGenUType_Type(new Type("$genUType", { fUInt_Type.get(), fUInt2_Type.get(), + , fUVec_Type(new Type(String("$uvec"), { fInvalid_Type.get(), fUInt2_Type.get(), fUInt3_Type.get(), fUInt4_Type.get() })) - , fGenBType_Type(new Type("$genBType", { fBool_Type.get(), fBool2_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(), fBool3_Type.get(), fBool4_Type.get() })) - , 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)) + , fSkCaps_Type(new Type(String("$sk_Caps"))) + , fSkArgs_Type(new Type(String("$sk_Args"))) + , fColorSpaceXform_Type(new Type(String("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 @@ private: class Defined : public Expression { public: Defined(const Type& type) - : INHERITED(-1, kDefined_Kind, type) {} + : INHERITED(Position(), kDefined_Kind, type) {} bool hasSideEffects() const override { return false; } String description() const override { - return "<defined>"; + return String("<defined>"); } typedef Expression INHERITED; diff --git a/src/sksl/SkSLErrorReporter.h b/src/sksl/SkSLErrorReporter.h index 303a0e14e5..172e4888d8 100644 --- a/src/sksl/SkSLErrorReporter.h +++ b/src/sksl/SkSLErrorReporter.h @@ -19,11 +19,11 @@ class ErrorReporter { public: virtual ~ErrorReporter() {} - void error(int offset, const char* msg) { - this->error(offset, String(msg)); + void error(Position position, const char* msg) { + this->error(position, String(msg)); } - virtual void error(int offset, String msg) = 0; + virtual void error(Position position, String msg) = 0; virtual int errorCount() = 0; }; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 52a40f8367..64527a0eb6 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -42,19 +42,6 @@ void GLSLCodeGenerator::write(const String& s) { 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()); } @@ -64,9 +51,7 @@ void GLSLCodeGenerator::writeLine() { } void GLSLCodeGenerator::writeExtension(const Extension& ext) { - this->write("#extension "); - this->write(ext.fName); - this->writeLine(" : enable"); + this->writeLine("#extension " + ext.fName + " : enable"); } void GLSLCodeGenerator::writeType(const Type& type) { @@ -74,23 +59,19 @@ void GLSLCodeGenerator::writeType(const Type& type) { for (const Type* search : fWrittenStructs) { if (*search == type) { // already written - this->write(type.fName); + this->write(type.name()); return; } } fWrittenStructs.push_back(&type); - this->write("struct "); - this->write(type.fName); - this->writeLine(" {"); + this->writeLine("struct " + type.name() + " {"); 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->write(" "); - this->write(f.fName); - this->writeLine(";"); + this->writeLine(" " + f.fName + ";"); } fIndentation--; this->write("}"); @@ -157,12 +138,12 @@ void GLSLCodeGenerator::writeType(const Type& type) { this->write("uint"); } else { - this->write(type.fName); + this->write(type.name()); } break; } default: - this->write(type.fName); + this->write(type.name()); } } } @@ -229,8 +210,8 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); - this->fFunctionHeader += String(" ") + absExpr.fType.fName + " " + tmpVar1 + ";\n"; - this->fFunctionHeader += String(" ") + otherExpr.fType.fName + " " + tmpVar2 + ";\n"; + this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; + this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; this->write("((" + tmpVar1 + " = "); this->writeExpression(absExpr, kTopLevel_Precedence); this->write(") < (" + tmpVar2 + " = "); @@ -522,9 +503,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, this->write("("); } this->writeExpression(*b.fLeft, precedence); - this->write(" "); - this->write(Compiler::OperatorName(b.fOperator)); - this->write(" "); + this->write(" " + Token::OperatorName(b.fOperator) + " "); this->writeExpression(*b.fRight, precedence); if (precedence >= parentPrecedence) { this->write(")"); @@ -551,7 +530,7 @@ void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, if (kPrefix_Precedence >= parentPrecedence) { this->write("("); } - this->write(Compiler::OperatorName(p.fOperator)); + this->write(Token::OperatorName(p.fOperator)); this->writeExpression(*p.fOperand, kPrefix_Precedence); if (kPrefix_Precedence >= parentPrecedence) { this->write(")"); @@ -564,7 +543,7 @@ void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, this->write("("); } this->writeExpression(*p.fOperand, kPostfix_Precedence); - this->write(Compiler::OperatorName(p.fOperator)); + this->write(Token::OperatorName(p.fOperator)); if (kPostfix_Precedence >= parentPrecedence) { this->write(")"); } diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index 353cd66824..e10299aa14 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -90,8 +90,6 @@ protected: 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 482020af7f..50d242896a 100644 --- a/src/sksl/SkSLHCodeGenerator.cpp +++ b/src/sksl/SkSLHCodeGenerator.cpp @@ -23,17 +23,17 @@ HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, St , fSectionAndParameterHelper(*program, *errors) {} String HCodeGenerator::ParameterType(const Type& type) { - if (type.name() == "float2") { + if (type.fName == "float2") { return "SkPoint"; - } else if (type.name() == "int4") { + } else if (type.fName == "int4") { return "SkIRect"; - } else if (type.name() == "float4") { + } else if (type.fName == "float4") { return "SkRect"; - } else if (type.name() == "float4x4") { + } else if (type.fName == "float4x4") { return "SkMatrix44"; } else if (type.kind() == Type::kSampler_Kind) { return "sk_sp<GrTextureProxy>"; - } else if (type.name() == "colorSpaceXform") { + } else if (type.fName == "colorSpaceXform") { return "sk_sp<GrColorSpaceXform>"; } return type.name(); @@ -127,7 +127,7 @@ void HCodeGenerator::writeMake() { separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), - String(param->fName).c_str()); + param->fName.c_str()); separator = ", "; } this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); @@ -136,7 +136,7 @@ void HCodeGenerator::writeMake() { fFullName.c_str()); separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef("%s%s", separator, String(param->fName).c_str()); + this->writef("%s%s", separator, param->fName.c_str()); separator = ", "; } this->writeExtraConstructorParams(separator); @@ -148,7 +148,7 @@ void HCodeGenerator::writeMake() { void HCodeGenerator::failOnSection(const char* section, const char* msg) { std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section); if (s.size()) { - fErrors.error(s[0]->fOffset, String("@") + section + " " + msg); + fErrors.error(s[0]->fPosition, String("@") + section + " " + msg); } } @@ -165,7 +165,7 @@ void HCodeGenerator::writeConstructor() { const char* separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), - String(param->fName).c_str()); + param->fName.c_str()); separator = ", "; } this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); @@ -177,8 +177,7 @@ void HCodeGenerator::writeConstructor() { this->writef(")"); this->writeSection(INITIALIZERS_SECTION, "\n , "); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - String nameString(param->fName); - const char* name = nameString.c_str(); + const char* name = param->fName.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( @@ -202,7 +201,7 @@ void HCodeGenerator::writeConstructor() { for (const auto& param : fSectionAndParameterHelper.getParameters()) { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", - FieldName(String(param->fName).c_str()).c_str()); + FieldName(param->fName.c_str()).c_str()); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -217,8 +216,8 @@ void HCodeGenerator::writeConstructor() { void HCodeGenerator::writeFields() { this->writeSection(FIELDS_SECTION); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef(" %s %s;\n", FieldType(param->fType).c_str(), - FieldName(String(param->fName).c_str()).c_str()); + const char* name = param->fName.c_str(); + this->writef(" %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str()); } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { this->writef(" GrCoordTransform %sCoordTransform;\n", @@ -246,8 +245,7 @@ bool HCodeGenerator::generateCode() { if (param->fType.kind() == Type::kSampler_Kind) { continue; } - String nameString(param->fName); - const char* name = nameString.c_str(); + const char* name = param->fName.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 83ab993c2a..a46a9312c1 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -162,7 +162,7 @@ void IRGenerator::finish() { } std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) { - return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName)); + return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName)); } std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) { @@ -206,7 +206,7 @@ std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) { } statements.push_back(std::move(statement)); } - return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable)); + return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable)); } std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement( @@ -234,12 +234,12 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa 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->fOffset, "array size must be positive"); + fErrors.error(size->fPosition, "array size must be positive"); } name += "[" + to_string(count) + "]"; } else { @@ -250,12 +250,12 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa fSymbolTable->takeOwnership((Type*) type); sizes.push_back(std::move(size)); } else { - type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1); + type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1); fSymbolTable->takeOwnership((Type*) type); sizes.push_back(nullptr); } } - auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers, + auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers, varDecl.fName, *type, storage)); std::unique_ptr<Expression> value; if (varDecl.fValue) { @@ -266,7 +266,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa value = this->coerce(std::move(value), *type); var->fWriteCount = 1; } - if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" && + if (storage == Variable::kGlobal_Storage && varDecl.fName == String("sk_FragColor") && (*fSymbolTable)[varDecl.fName]) { // already defined, ignore } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] && @@ -281,7 +281,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa fSymbolTable->add(varDecl.fName, std::move(var)); } } - return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset, + return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition, baseType, std::move(variables))); } @@ -334,11 +334,11 @@ std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) { } 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.fOffset, std::move(empty), + return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty), fSymbolTable)); } } - return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test), + return std::unique_ptr<Statement>(new IfStatement(s.fPosition, s.fIsStatic, std::move(test), std::move(ifTrue), std::move(ifFalse))); } @@ -371,7 +371,7 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer), + return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer), std::move(test), std::move(next), std::move(statement), fSymbolTable)); } @@ -387,7 +387,7 @@ std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test), + return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test), std::move(statement))); } @@ -402,7 +402,7 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) { if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement), + return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement), std::move(test))); } @@ -435,13 +435,13 @@ std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& } } if (!caseValue->isConstant()) { - fErrors.error(caseValue->fOffset, "case value must be a constant"); + fErrors.error(caseValue->fPosition, "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->fOffset, "duplicate case value"); + fErrors.error(caseValue->fPosition, "duplicate case value"); } caseValues.insert(v); } @@ -453,10 +453,10 @@ std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& } statements.push_back(std::move(converted)); } - cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue), + cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue), std::move(statements))); } - return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic, + return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, s.fIsStatic, std::move(value), std::move(cases), fSymbolTable)); } @@ -479,7 +479,7 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& return nullptr; } if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) { - fErrors.error(result->fOffset, "may not return a value from a void function"); + fErrors.error(result->fPosition, "may not return a value from a void function"); } else { result = this->coerce(std::move(result), fCurrentFunction->fReturnType); if (!result) { @@ -489,45 +489,45 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& return std::unique_ptr<Statement>(new ReturnStatement(std::move(result))); } else { if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) { - fErrors.error(r.fOffset, "expected function to return '" + - fCurrentFunction->fReturnType.description() + "'"); + fErrors.error(r.fPosition, "expected function to return '" + + fCurrentFunction->fReturnType.description() + "'"); } - return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset)); + return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition)); } } std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) { if (fLoopLevel > 0 || fSwitchLevel > 0) { - return std::unique_ptr<Statement>(new BreakStatement(b.fOffset)); + return std::unique_ptr<Statement>(new BreakStatement(b.fPosition)); } else { - fErrors.error(b.fOffset, "break statement must be inside a loop or switch"); + fErrors.error(b.fPosition, "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.fOffset)); + return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition)); } else { - fErrors.error(c.fOffset, "continue statement must be inside a loop"); + fErrors.error(c.fPosition, "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.fOffset)); + return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition)); } 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(-1, + FunctionDeclaration* invokeDecl = new FunctionDeclaration(Position(), invokeModifiers, "_invoke", std::vector<const Variable*>(), *fContext.fVoid_Type); - out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(-1, + out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(Position(), *invokeDecl, std::move(main)))); fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl)); @@ -535,47 +535,47 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr< std::vector<std::unique_ptr<VarDeclaration>> variables; Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"]; ASSERT(loopIdx); - std::unique_ptr<Expression> test(new BinaryExpression(-1, - std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)), + std::unique_ptr<Expression> test(new BinaryExpression(Position(), + std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)), Token::LT, - std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)), + std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), fInvocations)), *fContext.fBool_Type)); std::unique_ptr<Expression> next(new PostfixExpression( std::unique_ptr<Expression>( - new VariableReference(-1, + new VariableReference(Position(), *loopIdx, VariableReference::kReadWrite_RefKind)), Token::PLUSPLUS)); - ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive"); + ASTIdentifier endPrimitiveID = ASTIdentifier(Position(), "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(-1, + this->call(Position(), *invokeDecl, std::vector<std::unique_ptr<Expression>>())))); loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement( - this->call(-1, + this->call(Position(), std::move(endPrimitive), std::vector<std::unique_ptr<Expression>>())))); - std::unique_ptr<Expression> assignment(new BinaryExpression(-1, - std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)), + std::unique_ptr<Expression> assignment(new BinaryExpression(Position(), + std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)), Token::EQ, - std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)), + std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), 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(-1, + new ForStatement(Position(), std::move(initializer), std::move(test), std::move(next), - std::unique_ptr<Block>(new Block(-1, std::move(loopBody))), + std::unique_ptr<Block>(new Block(Position(), std::move(loopBody))), fSymbolTable)); std::vector<std::unique_ptr<Statement>> children; children.push_back(std::move(loop)); - return std::unique_ptr<Block>(new Block(-1, std::move(children))); + return std::unique_ptr<Block>(new Block(Position(), std::move(children))); } void IRGenerator::convertFunction(const ASTFunction& f, @@ -597,8 +597,9 @@ void IRGenerator::convertFunction(const ASTFunction& f, fSymbolTable->takeOwnership(newType); type = newType; } - StringFragment name = param->fName; - Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type, + String name = param->fName; + Position pos = param->fPosition; + Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type, Variable::kParameter_Storage); fSymbolTable->takeOwnership(var); parameters.push_back(var); @@ -617,7 +618,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, functions.push_back((FunctionDeclaration*) entry); break; default: - fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined"); + fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined"); return; } for (const auto& other : functions) { @@ -632,26 +633,26 @@ void IRGenerator::convertFunction(const ASTFunction& f, } if (match) { if (*returnType != other->fReturnType) { - FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters, + FunctionDeclaration newDecl(f.fPosition, f.fModifiers, f.fName, parameters, *returnType); - fErrors.error(f.fOffset, "functions '" + newDecl.description() + - "' and '" + other->description() + - "' differ only in return type"); + fErrors.error(f.fPosition, "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.fOffset, "modifiers on parameter " + - to_string((uint64_t) i + 1) + - " differ between declaration and " - "definition"); + fErrors.error(f.fPosition, "modifiers on parameter " + + to_string((uint64_t) i + 1) + + " differ between declaration and " + "definition"); return; } } if (other->fDefined) { - fErrors.error(f.fOffset, "duplicate definition of " + - other->description()); + fErrors.error(f.fPosition, "duplicate definition of " + + other->description()); } break; } @@ -660,7 +661,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, } if (!decl) { // couldn't find an existing declaration - auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset, + auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition, f.fModifiers, f.fName, parameters, @@ -697,7 +698,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag; out->push_back(std::unique_ptr<FunctionDefinition>( - new FunctionDefinition(f.fOffset, *decl, std::move(body)))); + new FunctionDefinition(f.fPosition, *decl, std::move(body)))); } } @@ -716,14 +717,14 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte for (const auto& stmt : decl->fVars) { VarDeclaration& vd = (VarDeclaration&) *stmt; if (haveRuntimeArray) { - fErrors.error(decl->fOffset, + fErrors.error(decl->fPosition, "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->fOffset, + fErrors.error(decl->fPosition, "initializers are not permitted on interface block fields"); } if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag | @@ -731,7 +732,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte Modifiers::kUniform_Flag | Modifiers::kBuffer_Flag | Modifiers::kConst_Flag)) { - fErrors.error(decl->fOffset, + fErrors.error(decl->fPosition, "interface block fields may not have storage qualifiers"); } if (vd.fVar->fType.kind() == Type::kArray_Kind && @@ -740,7 +741,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte } } } - Type* type = new Type(intf.fOffset, intf.fTypeName, fields); + Type* type = new Type(intf.fPosition, intf.fTypeName, fields); old->takeOwnership(type); std::vector<std::unique_ptr<Expression>> sizes; for (const auto& size : intf.fSizes) { @@ -754,7 +755,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte if (converted->fKind == Expression::kIntLiteral_Kind) { count = ((IntLiteral&) *converted).fValue; if (count <= 0) { - fErrors.error(converted->fOffset, "array size must be positive"); + fErrors.error(converted->fPosition, "array size must be positive"); } name += "[" + to_string(count) + "]"; } else { @@ -765,24 +766,24 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte fSymbolTable->takeOwnership((Type*) type); sizes.push_back(std::move(converted)); } else { - type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1); + type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1); fSymbolTable->takeOwnership((Type*) type); sizes.push_back(nullptr); } } - Variable* var = new Variable(intf.fOffset, intf.fModifiers, - intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName, + Variable* var = new Variable(intf.fPosition, intf.fModifiers, + intf.fInstanceName.size() ? intf.fInstanceName : intf.fTypeName, *type, Variable::kGlobal_Storage); old->takeOwnership(var); - if (intf.fInstanceName.fLength) { + if (intf.fInstanceName.size()) { 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.fOffset, *var, + old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var, (int) i))); } } - return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset, + return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, var, intf.fTypeName, intf.fInstanceName, @@ -794,8 +795,7 @@ const Type* IRGenerator::convertType(const ASTType& type) { const Symbol* result = (*fSymbolTable)[type.fName]; if (result && result->fKind == Symbol::kType_Kind) { for (int size : type.fSizes) { - String name(result->fName); - name += "["; + String name = result->fName + "["; if (size != -1) { name += to_string(size); } @@ -805,7 +805,7 @@ const Type* IRGenerator::convertType(const ASTType& type) { } return (const Type*) result; } - fErrors.error(type.fOffset, "unknown type '" + type.fName + "'"); + fErrors.error(type.fPosition, "unknown type '" + type.fName + "'"); return nullptr; } @@ -814,13 +814,13 @@ std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& case ASTExpression::kIdentifier_Kind: return this->convertIdentifier((ASTIdentifier&) expr); case ASTExpression::kBool_Kind: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition, ((ASTBoolLiteral&) expr).fValue)); case ASTExpression::kInt_Kind: - return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset, + return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition, ((ASTIntLiteral&) expr).fValue)); case ASTExpression::kFloat_Kind: - return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset, + return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition, ((ASTFloatLiteral&) expr).fValue)); case ASTExpression::kBinary_Kind: return this->convertBinaryExpression((ASTBinaryExpression&) expr); @@ -838,7 +838,7 @@ std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) { const Symbol* result = (*fSymbolTable)[identifier.fText]; if (!result) { - fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'"); + fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'"); return nullptr; } switch (result->fKind) { @@ -847,13 +847,13 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& (const FunctionDeclaration*) result }; return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, - identifier.fOffset, + identifier.fPosition, f)); } case Symbol::kUnresolvedFunction_Kind: { const UnresolvedFunction* f = (const UnresolvedFunction*) result; return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, - identifier.fOffset, + identifier.fPosition, f->fFunctions)); } case Symbol::kVariable_Kind: { @@ -870,13 +870,13 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& #endif // default to kRead_RefKind; this will be corrected later if the variable is written to return std::unique_ptr<VariableReference>(new VariableReference( - identifier.fOffset, + identifier.fPosition, *var, VariableReference::kRead_RefKind)); } case Symbol::kField_Kind: { const Field* field = (const Field*) result; - VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner, + VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner, VariableReference::kRead_RefKind); return std::unique_ptr<Expression>(new FieldAccess( std::unique_ptr<Expression>(base), @@ -885,7 +885,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& } case Symbol::kType_Kind: { const Type* t = (const Type*) result; - return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset, + return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition, *t)); } default: @@ -894,7 +894,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& } std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) { - return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText)); + return std::unique_ptr<Section>(new Section(s.fPosition, s.fName, s.fArgument, s.fText)); } @@ -911,24 +911,24 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr return nullptr; } if (expr->coercionCost(type) == INT_MAX) { - fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" + + fErrors.error(expr->fPosition, "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(-1, type.fName); + ASTIdentifier id(Position(), type.description()); std::unique_ptr<Expression> ctor = this->convertIdentifier(id); ASSERT(ctor); - return this->call(-1, std::move(ctor), std::move(args)); + return this->call(Position(), 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(-1, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); } static bool is_matrix_multiply(const Type& left, const Type& right) { @@ -1094,9 +1094,9 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, case Token::LOGICALXOR: result = leftVal ^ rightVal; break; default: return nullptr; } - return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result)); + return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosition, result)); } - #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \ + #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \ leftVal op rightVal)) if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) { int64_t leftVal = ((IntLiteral&) left).fValue; @@ -1109,13 +1109,13 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, if (rightVal) { return RESULT(Int, /); } - fErrors.error(right.fOffset, "division by zero"); + fErrors.error(right.fPosition, "division by zero"); return nullptr; case Token::PERCENT: if (rightVal) { return RESULT(Int, %); } - fErrors.error(right.fOffset, "division by zero"); + fErrors.error(right.fPosition, "division by zero"); return nullptr; case Token::BITWISEAND: return RESULT(Int, &); case Token::BITWISEOR: return RESULT(Int, |); @@ -1143,7 +1143,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, if (rightVal) { return RESULT(Float, /); } - fErrors.error(right.fOffset, "division by zero"); + fErrors.error(right.fPosition, "division by zero"); return nullptr; case Token::EQEQ: return RESULT(Bool, ==); case Token::NEQ: return RESULT(Bool, !=); @@ -1164,16 +1164,16 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, 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, -1, value)); \ + args.emplace_back(new FloatLiteral(fContext, Position(), value)); \ } \ - return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \ + return std::unique_ptr<Expression>(new Constructor(Position(), left.fType, \ std::move(args))); switch (op) { case Token::EQEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), left.compareConstant(fContext, right))); case Token::NEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), !left.compareConstant(fContext, right))); case Token::PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+); case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-); @@ -1187,10 +1187,10 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, left.fKind == right.fKind) { switch (op) { case Token::EQEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), left.compareConstant(fContext, right))); case Token::NEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), !left.compareConstant(fContext, right))); default: return nullptr; @@ -1227,14 +1227,14 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( } if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType, &leftType, &rightType, &resultType, - !Compiler::IsAssignment(expression.fOperator))) { - fErrors.error(expression.fOffset, String("type mismatch: '") + - Compiler::OperatorName(expression.fOperator) + - "' cannot operate on '" + left->fType.fName + - "', '" + right->fType.fName + "'"); + !Token::IsAssignment(expression.fOperator))) { + fErrors.error(expression.fPosition, "type mismatch: '" + + Token::OperatorName(expression.fOperator) + + "' cannot operate on '" + left->fType.fName + + "', '" + right->fType.fName + "'"); return nullptr; } - if (Compiler::IsAssignment(expression.fOperator)) { + if (Token::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> IRGenerator::convertBinaryExpression( std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator, *right.get()); if (!result) { - result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset, + result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition, std::move(left), expression.fOperator, std::move(right), @@ -1274,9 +1274,9 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( const Type* resultType; if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType, &falseType, &resultType, true) || trueType != falseType) { - fErrors.error(expression.fOffset, "ternary operator result mismatch: '" + - ifTrue->fType.fName + "', '" + - ifFalse->fType.fName + "'"); + fErrors.error(expression.fPosition, "ternary operator result mismatch: '" + + ifTrue->fType.fName + "', '" + + ifFalse->fType.fName + "'"); return nullptr; } ifTrue = this->coerce(std::move(ifTrue), *trueType); @@ -1295,7 +1295,7 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( return ifFalse; } } - return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset, + return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition, std::move(test), std::move(ifTrue), std::move(ifFalse))); @@ -1315,8 +1315,8 @@ void IRGenerator::fixRectSampling(std::vector<std::unique_ptr<Expression>>& argu ASSERT(textureSizeSymbol->fKind == Symbol::kFunctionDeclaration_Kind); const FunctionDeclaration& textureSize = (FunctionDeclaration&) *textureSizeSymbol; std::vector<std::unique_ptr<Expression>> sizeArguments; - sizeArguments.emplace_back(new VariableReference(-1, sampler)); - std::unique_ptr<Expression> float2ize = call(-1, textureSize, std::move(sizeArguments)); + sizeArguments.emplace_back(new VariableReference(Position(), sampler)); + std::unique_ptr<Expression> float2ize = call(Position(), textureSize, std::move(sizeArguments)); const Type& type = arguments[1]->fType; std::unique_ptr<Expression> scale; if (type == *fContext.fFloat2_Type) { @@ -1325,14 +1325,14 @@ void IRGenerator::fixRectSampling(std::vector<std::unique_ptr<Expression>>& argu ASSERT(type == *fContext.fFloat3_Type); std::vector<std::unique_ptr<Expression>> float3rguments; float3rguments.push_back(std::move(float2ize)); - float3rguments.emplace_back(new FloatLiteral(fContext, -1, 1.0)); - scale.reset(new Constructor(-1, *fContext.fFloat3_Type, std::move(float3rguments))); + float3rguments.emplace_back(new FloatLiteral(fContext, Position(), 1.0)); + scale.reset(new Constructor(Position(), *fContext.fFloat3_Type, std::move(float3rguments))); } - arguments[1].reset(new BinaryExpression(-1, std::move(scale), Token::STAR, + arguments[1].reset(new BinaryExpression(Position(), std::move(scale), Token::STAR, std::move(arguments[1]), type)); } -std::unique_ptr<Expression> IRGenerator::call(int offset, +std::unique_ptr<Expression> IRGenerator::call(Position position, const FunctionDeclaration& function, std::vector<std::unique_ptr<Expression>> arguments) { if (function.fParameters.size() != arguments.size()) { @@ -1343,7 +1343,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, msg += "s"; } msg += ", but found " + to_string((uint64_t) arguments.size()); - fErrors.error(offset, msg); + fErrors.error(position, msg); return nullptr; } std::vector<const Type*> types; @@ -1357,7 +1357,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, msg += arguments[i]->fType.description(); } msg += ")"; - fErrors.error(offset, msg); + fErrors.error(position, msg); return nullptr; } for (size_t i = 0; i < arguments.size(); i++) { @@ -1374,7 +1374,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, arguments[0]->fType == *fContext.fSampler2DRect_Type) { this->fixRectSampling(arguments); } - return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function, + return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function, std::move(arguments))); } @@ -1409,26 +1409,26 @@ std::unique_ptr<Expression> IRGenerator::applyColorSpace(std::unique_ptr<Express std::unique_ptr<Expression> xform) { // Before: texture(img, coords, xform); // After: COLORSPACE(texture(img, coords), xform) - int offset = texture->fOffset; + Position p = texture->fPosition; 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(offset, colorspaceFunction, std::move(args)); + return this->call(p, colorspaceFunction, std::move(args)); } -std::unique_ptr<Expression> IRGenerator::call(int offset, +std::unique_ptr<Expression> IRGenerator::call(Position position, std::unique_ptr<Expression> functionValue, std::vector<std::unique_ptr<Expression>> arguments) { if (functionValue->fKind == Expression::kTypeReference_Kind) { - return this->convertConstructor(offset, + return this->convertConstructor(position, ((TypeReference&) *functionValue).fValue, std::move(arguments)); } if (functionValue->fKind != Expression::kFunctionReference_Kind) { - fErrors.error(offset, "'" + functionValue->description() + "' is not a function"); + fErrors.error(position, "'" + functionValue->description() + "' is not a function"); return nullptr; } FunctionReference* ref = (FunctionReference*) functionValue.get(); @@ -1436,7 +1436,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, arguments.back()->fType == *fContext.fColorSpaceXform_Type) { std::unique_ptr<Expression> colorspace = std::move(arguments.back()); arguments.pop_back(); - return this->applyColorSpace(this->call(offset, + return this->applyColorSpace(this->call(position, std::move(functionValue), std::move(arguments)), std::move(colorspace)); @@ -1453,7 +1453,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, } } if (best) { - return this->call(offset, *best, std::move(arguments)); + return this->call(position, *best, std::move(arguments)); } String msg = "no match for " + ref->fFunctions[0]->fName + "("; String separator; @@ -1463,21 +1463,21 @@ std::unique_ptr<Expression> IRGenerator::call(int offset, msg += arguments[i]->fType.description(); } msg += ")"; - fErrors.error(offset, msg); + fErrors.error(position, msg); return nullptr; } - return this->call(offset, *ref->fFunctions[0], std::move(arguments)); + return this->call(position, *ref->fFunctions[0], std::move(arguments)); } std::unique_ptr<Expression> IRGenerator::convertNumberConstructor( - int offset, + Position position, const Type& type, std::vector<std::unique_ptr<Expression>> args) { ASSERT(type.isNumber()); if (args.size() != 1) { - fErrors.error(offset, "invalid arguments to '" + type.description() + - "' constructor, (expected exactly 1 argument, but found " + - to_string((uint64_t) args.size()) + ")"); + fErrors.error(position, "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 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor( } 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, offset, (double) value)); + return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (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, - offset, + position, ((IntLiteral&) *args[0]).fValue, &type)); } if (args[0]->fType == *fContext.fBool_Type) { - std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0)); - std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1)); + std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); + std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1)); return std::unique_ptr<Expression>( - new TernaryExpression(offset, std::move(args[0]), + new TernaryExpression(position, std::move(args[0]), this->coerce(std::move(one), type), this->coerce(std::move(zero), type))); } if (!args[0]->fType.isNumber()) { - fErrors.error(offset, "invalid argument to '" + type.description() + - "' constructor (expected a number or bool, but found '" + - args[0]->fType.description() + "')"); + fErrors.error(position, "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(offset, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } int component_count(const Type& type) { @@ -1530,14 +1530,14 @@ int component_count(const Type& type) { } std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( - int offset, + Position position, 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(offset, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } int actual = 0; int expected = type.rows() * type.columns(); @@ -1547,9 +1547,9 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( if (args[i]->fType.kind() == Type::kVector_Kind) { if (type.componentType().isNumber() != args[i]->fType.componentType().isNumber()) { - fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid " - "parameter to '" + type.description() + - "' constructor"); + fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid " + "parameter to '" + type.description() + + "' constructor"); return nullptr; } actual += args[i]->fType.columns(); @@ -1562,23 +1562,23 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( } } } else { - fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid " - "parameter to '" + type.description() + "' constructor"); + fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid " + "parameter to '" + type.description() + "' constructor"); return nullptr; } } if (actual != 1 && actual != expected) { - fErrors.error(offset, "invalid arguments to '" + type.description() + - "' constructor (expected " + to_string(expected) + - " scalars, but found " + to_string(actual) + ")"); + fErrors.error(position, "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(offset, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } std::unique_ptr<Expression> IRGenerator::convertConstructor( - int offset, + Position position, const Type& type, std::vector<std::unique_ptr<Expression>> args) { // FIXME: add support for structs @@ -1588,7 +1588,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( return std::move(args[0]); } if (type.isNumber()) { - return this->convertNumberConstructor(offset, type, std::move(args)); + return this->convertNumberConstructor(position, 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 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( return nullptr; } } - return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) { - return this->convertCompoundConstructor(offset, type, std::move(args)); + return this->convertCompoundConstructor(position, type, std::move(args)); } else { - fErrors.error(offset, "cannot construct '" + type.description() + "'"); + fErrors.error(position, "cannot construct '" + type.description() + "'"); return nullptr; } } @@ -1615,31 +1615,31 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( switch (expression.fOperator) { case Token::PLUS: if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(expression.fOffset, + fErrors.error(expression.fPosition, "'+' 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.fOffset, + fErrors.error(expression.fPosition, "'-' cannot operate on '" + base->fType.description() + "'"); return nullptr; } if (base->fKind == Expression::kIntLiteral_Kind) { - return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset, + return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition, -((IntLiteral&) *base).fValue)); } if (base->fKind == Expression::kFloatLiteral_Kind) { double value = -((FloatLiteral&) *base).fValue; - return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset, + return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition, value)); } return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base))); case Token::PLUSPLUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fOffset, - String("'") + Compiler::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1647,8 +1647,8 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( break; case Token::MINUSMINUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fOffset, - String("'") + Compiler::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1656,20 +1656,20 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( break; case Token::LOGICALNOT: if (base->fType != *fContext.fBool_Type) { - fErrors.error(expression.fOffset, - String("'") + Compiler::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::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->fOffset, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fPosition, !((BoolLiteral&) *base).fValue)); } break; case Token::BITWISENOT: if (base->fType != *fContext.fInt_Type) { - fErrors.error(expression.fOffset, - String("'") + Compiler::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1690,18 +1690,18 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression 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->fOffset, + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition, *newType)); } else { - fErrors.error(base->fOffset, "array size must be a constant"); + fErrors.error(base->fPosition, "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->fOffset, "expected array, but found '" + base->fType.description() + - "'"); + fErrors.error(base->fPosition, "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::convertIndex(std::unique_ptr<Expression } std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base, - StringFragment field) { + const String& 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->fOffset, "type '" + base->fType.description() + "' does not have a " - "field named '" + field + ""); + fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a " + "field named '" + field + ""); return nullptr; } std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base, - StringFragment fields) { + const String& fields) { if (base->fType.kind() != Type::kVector_Kind) { - fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'"); + fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'"); return nullptr; } std::vector<int> swizzleComponents; - for (size_t i = 0; i < fields.fLength; i++) { + for (size_t i = 0; i < fields.size(); i++) { switch (fields[i]) { case 'x': // fall through case 'r': // fall through @@ -1770,40 +1770,40 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi } // fall through default: - fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'", - fields[i])); + fErrors.error(base->fPosition, String::printf("invalid swizzle component '%c'", + fields[i])); return nullptr; } } ASSERT(swizzleComponents.size() > 0); if (swizzleComponents.size() > 4) { - fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'"); + fErrors.error(base->fPosition, "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(int offset, String name) { +std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name) { auto found = fCapsMap.find(name); if (found == fCapsMap.end()) { - fErrors.error(offset, "unknown capability flag '" + name + "'"); + fErrors.error(position, "unknown capability flag '" + name + "'"); return nullptr; } String fullName = "sk_Caps." + name; - return std::unique_ptr<Expression>(new Setting(offset, fullName, - found->second.literal(fContext, offset))); + return std::unique_ptr<Expression>(new Setting(position, fullName, + found->second.literal(fContext, position))); } -std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) { +std::unique_ptr<Expression> IRGenerator::getArg(Position position, String name) { auto found = fSettings->fArgs.find(name); if (found == fSettings->fArgs.end()) { - fErrors.error(offset, "unknown argument '" + name + "'"); + fErrors.error(position, "unknown argument '" + name + "'"); return nullptr; } String fullName = "sk_Args." + name; - return std::unique_ptr<Expression>(new Setting(offset, + return std::unique_ptr<Expression>(new Setting(position, fullName, - found->second.literal(fContext, offset))); + found->second.literal(fContext, position))); } std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( @@ -1822,10 +1822,10 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType, -1); fSymbolTable->takeOwnership(newType); - return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset, + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition, *newType)); } else { - fErrors.error(expression.fOffset, "'[]' must follow a type name"); + fErrors.error(expression.fPosition, "'[]' must follow a type name"); return nullptr; } } @@ -1840,15 +1840,15 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( } arguments.push_back(std::move(converted)); } - return this->call(expression.fOffset, std::move(base), std::move(arguments)); + return this->call(expression.fPosition, std::move(base), std::move(arguments)); } case ASTSuffix::kField_Kind: { if (base->fType == *fContext.fSkCaps_Type) { - return this->getCap(expression.fOffset, + return this->getCap(expression.fPosition, ((ASTFieldSuffix&) *expression.fSuffix).fField); } if (base->fType == *fContext.fSkArgs_Type) { - return this->getArg(expression.fOffset, + return this->getArg(expression.fPosition, ((ASTFieldSuffix&) *expression.fSuffix).fField); } switch (base->fType.kind()) { @@ -1859,14 +1859,14 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( return this->convertField(std::move(base), ((ASTFieldSuffix&) *expression.fSuffix).fField); default: - fErrors.error(base->fOffset, "cannot swizzle value of type '" + - base->fType.description() + "'"); + fErrors.error(base->fPosition, "cannot swizzle value of type '" + + base->fType.description() + "'"); return nullptr; } } case ASTSuffix::kPostIncrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fOffset, + fErrors.error(expression.fPosition, "'++' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1875,7 +1875,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( Token::PLUSPLUS)); case ASTSuffix::kPostDecrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fOffset, + fErrors.error(expression.fPosition, "'--' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1890,14 +1890,14 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( void IRGenerator::checkValid(const Expression& expr) { switch (expr.fKind) { case Expression::kFunctionReference_Kind: - fErrors.error(expr.fOffset, "expected '(' to begin function call"); + fErrors.error(expr.fPosition, "expected '(' to begin function call"); break; case Expression::kTypeReference_Kind: - fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation"); + fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation"); break; default: if (expr.fType == *fContext.fInvalid_Type) { - fErrors.error(expr.fOffset, "invalid expression"); + fErrors.error(expr.fPosition, "invalid expression"); } } } @@ -1920,7 +1920,7 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { case Expression::kVariableReference_Kind: { const Variable& var = ((VariableReference&) expr).fVariable; if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) { - fErrors.error(expr.fOffset, + fErrors.error(expr.fPosition, "cannot modify immutable variable '" + var.fName + "'"); } ((VariableReference&) expr).setRefKind(readWrite ? VariableReference::kReadWrite_RefKind @@ -1932,7 +1932,7 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { break; case Expression::kSwizzle_Kind: if (has_duplicates((Swizzle&) expr)) { - fErrors.error(expr.fOffset, + fErrors.error(expr.fPosition, "cannot write to the same swizzle field more than once"); } this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite); @@ -1941,20 +1941,18 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite); break; default: - fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'"); + fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'"); break; } } -void IRGenerator::convertProgram(const char* text, - size_t length, +void IRGenerator::convertProgram(String text, SymbolTable& types, Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* out) { - Parser parser(text, length, types, fErrors); + Parser parser(text, 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 3dda02835b..0a1bae4f64 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -61,8 +61,7 @@ public: IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root, ErrorReporter& errorReporter); - void convertProgram(const char* text, - size_t length, + void convertProgram(String text, SymbolTable& types, Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* result); @@ -104,26 +103,26 @@ private: const ASTModifiersDeclaration& m); const Type* convertType(const ASTType& type); - std::unique_ptr<Expression> call(int offset, + std::unique_ptr<Expression> call(Position position, 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(int offset, std::unique_ptr<Expression> function, + std::unique_ptr<Expression> call(Position position, 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( - int offset, + Position position, const Type& type, std::vector<std::unique_ptr<Expression>> params); std::unique_ptr<Expression> convertCompoundConstructor( - int offset, + Position position, const Type& type, std::vector<std::unique_ptr<Expression>> params); - std::unique_ptr<Expression> convertConstructor(int offset, + std::unique_ptr<Expression> convertConstructor(Position position, const Type& type, std::vector<std::unique_ptr<Expression>> params); std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c); @@ -143,13 +142,13 @@ private: 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(int offset, String name); - std::unique_ptr<Expression> getArg(int offset, String name); + std::unique_ptr<Expression> getCap(Position position, String name); + std::unique_ptr<Expression> getArg(Position position, String name); std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression); std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base, - StringFragment field); + const String& field); std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base, - StringFragment fields); + const String& 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 deleted file mode 100644 index 968391ea96..0000000000 --- a/src/sksl/SkSLLayoutLexer.cpp +++ /dev/null @@ -1,1343 +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 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 deleted file mode 100644 index f3d250ad8d..0000000000 --- a/src/sksl/SkSLLayoutLexer.h +++ /dev/null @@ -1,95 +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 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 deleted file mode 100644 index ed905ac2cf..0000000000 --- a/src/sksl/SkSLLexer.cpp +++ /dev/null @@ -1,1925 +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 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 deleted file mode 100644 index 246be22b9e..0000000000 --- a/src/sksl/SkSLLexer.h +++ /dev/null @@ -1,238 +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 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 d8ecc618bc..f712b34e1a 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -7,6 +7,26 @@ #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" @@ -63,7 +83,7 @@ public: bool checkValid() { if (fParser->fDepth > MAX_PARSE_DEPTH) { - fParser->error(fParser->peek(), String("exceeded max parse depth")); + fParser->error(fParser->peek().fPosition, String("exceeded max parse depth")); return false; } return true; @@ -73,12 +93,20 @@ private: Parser* fParser; }; -Parser::Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors) -: fText(text) -, fPushback(Token::INVALID, -1, -1) +Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors) +: fPushback(Position(-1, -1), Token::INVALID_TOKEN, String()) , fTypes(types) , fErrors(errors) { - fLexer.start(text, length); + 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); } /* (precision | directive | section | declaration)* END_OF_FILE */ @@ -120,39 +148,53 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } } -Token Parser::nextRawToken() { - if (fPushback.fKind != Token::INVALID) { - Token result = fPushback; - fPushback.fKind = Token::INVALID; +Token Parser::nextRawToken(bool needText) { + if (fPushback.fKind != Token::INVALID_TOKEN) { + Token result(std::move(fPushback)); + fPushback.fKind = Token::INVALID_TOKEN; + fPushback.fText.clear(); return result; } - Token result = fLexer.next(); - 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 Parser::nextToken() { - Token token = this->nextRawToken(); - while (token.fKind == Token::WHITESPACE || token.fKind == Token::LINE_COMMENT || - token.fKind == Token::BLOCK_COMMENT) { - token = this->nextRawToken(); - } + Token token; + do { + token = this->nextRawToken(false); + } while (token.fKind == Token::WHITESPACE); return token; } void Parser::pushback(Token t) { - ASSERT(fPushback.fKind == Token::INVALID); + ASSERT(fPushback.fKind == Token::INVALID_TOKEN); fPushback = std::move(t); } Token Parser::peek() { - if (fPushback.fKind == Token::INVALID) { + if (fPushback.fKind == Token::INVALID_TOKEN) { fPushback = this->nextToken(); } return fPushback; } bool Parser::checkNext(Token::Kind kind, Token* result) { - if (fPushback.fKind != Token::INVALID && fPushback.fKind != kind) { + if (fPushback.fKind != Token::INVALID_TOKEN && fPushback.fKind != kind) { return false; } Token next = this->nextToken(); @@ -174,25 +216,25 @@ bool Parser::expect(Token::Kind kind, const char* expected, Token* result) { } return true; } else { - this->error(next, "expected " + String(expected) + ", but found '" + - this->text(next) + "'"); + 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"); + } return false; } } -StringFragment Parser::text(Token token) { - return StringFragment(fText + token.fOffset, token.fLength); -} - -void Parser::error(Token token, String msg) { - this->error(token.fOffset, msg); +void Parser::error(Position p, const char* msg) { + this->error(p, String(msg)); } -void Parser::error(int offset, String msg) { - fErrors.error(offset, msg); +void Parser::error(Position p, String msg) { + fErrors.error(p, msg); } -bool Parser::isType(StringFragment name) { +bool Parser::isType(const String& name) { return nullptr != fTypes[name]; } @@ -214,8 +256,8 @@ std::unique_ptr<ASTDeclaration> Parser::precision() { result = Modifiers::kHighp_Flag; break; default: - this->error(p, "expected 'lowp', 'mediump', or 'highp', but found '" + - this->text(p) + "'"); + this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + + p.fText + "'"); return nullptr; } // FIXME handle the type @@ -223,7 +265,7 @@ std::unique_ptr<ASTDeclaration> Parser::precision() { return nullptr; } this->expect(Token::SEMICOLON, "';'"); - return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fOffset, result)); + return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result)); } /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | @@ -233,18 +275,16 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { return nullptr; } - StringFragment text = this->text(start); - if (text == "#version") { + if (start.fText == "#version") { this->expect(Token::INT_LITERAL, "a version number"); Token next = this->peek(); - StringFragment nextText = this->text(next); - if (nextText == "es" || nextText == "compatibility") { + if (next.fText == "es" || next.fText == "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 (text == "#extension") { + } else if (start.fText == "#extension") { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { return nullptr; @@ -256,10 +296,10 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { if (!this->expect(Token::IDENTIFIER, "an identifier")) { return nullptr; } - return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fOffset, - String(this->text(name)))); + return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition, + std::move(name.fText))); } else { - this->error(start, "unsupported directive '" + this->text(start) + "'"); + this->error(start.fPosition, "unsupported directive '" + start.fText + "'"); return nullptr; } } @@ -278,7 +318,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) { return nullptr; } - argument = this->text(argToken); + argument = argToken.fText; if (!this->expect(Token::RPAREN, "')'")) { return nullptr; } @@ -289,7 +329,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { String text; int level = 1; for (;;) { - Token next = this->nextRawToken(); + Token next = this->nextRawToken(true); switch (next.fKind) { case Token::LBRACE: ++level; @@ -298,7 +338,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { --level; break; case Token::END_OF_FILE: - this->error(start, "reached end of file while parsing section"); + this->error(start.fPosition, "reached end of file while parsing section"); return nullptr; default: break; @@ -306,13 +346,10 @@ std::unique_ptr<ASTDeclaration> Parser::section() { if (!level) { break; } - text += this->text(next); + text += next.fText; } - StringFragment name = this->text(start); - ++name.fChars; - --name.fLength; - return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fOffset, - String(name), + return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition, + String(start.fText.c_str() + 1), argument, text)); } @@ -322,7 +359,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { std::unique_ptr<ASTDeclaration> Parser::declaration() { Modifiers modifiers = this->modifiers(); Token lookahead = this->peek(); - if (lookahead.fKind == Token::IDENTIFIER && !this->isType(this->text(lookahead))) { + if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) { // we have an identifier that's not a type, could be the start of an interface block return this->interfaceBlock(modifiers); } @@ -366,14 +403,14 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() { return nullptr; } } - return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fOffset, + return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, modifiers, std::move(type), - this->text(name), + std::move(name.fText), std::move(parameters), std::move(body))); } else { - return this->varDeclarationEnd(modifiers, std::move(type), this->text(name)); + return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText)); } } @@ -388,7 +425,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() { if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { return nullptr; } - return this->varDeclarationEnd(modifiers, std::move(type), this->text(name)); + return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText)); } /* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */ @@ -413,7 +450,7 @@ std::unique_ptr<ASTType> Parser::structDeclaration() { 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->fOffset, "array size in struct field must be a constant"); + this->error(decl->fPosition, "array size in struct field must be a constant"); return nullptr; } uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue; @@ -423,16 +460,15 @@ std::unique_ptr<ASTType> Parser::structDeclaration() { } fields.push_back(Type::Field(decl->fModifiers, var.fName, type)); if (var.fValue) { - this->error(decl->fOffset, "initializers are not permitted on struct fields"); + this->error(decl->fPosition, "initializers are not permitted on struct fields"); } } } if (!this->expect(Token::RBRACE, "'}'")) { return nullptr; } - 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), + 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, ASTType::kStruct_Kind, std::vector<int>())); } @@ -446,11 +482,11 @@ std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modif if (this->checkNext(Token::IDENTIFIER, &name)) { std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers, std::move(type), - this->text(name)); + std::move(name.fText)); if (result) { for (const auto& var : result->fVars) { if (var.fValue) { - this->error(var.fValue->fOffset, + this->error(var.fValue->fPosition, "struct variables cannot be initialized"); } } @@ -465,7 +501,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modif (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods, std::unique_ptr<ASTType> type, - StringFragment name) { + String name) { std::vector<ASTVarDeclaration> vars; std::vector<std::unique_ptr<ASTExpression>> currentVarSizes; while (this->checkNext(Token::LBRACKET)) { @@ -489,7 +525,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods, return nullptr; } } - vars.emplace_back(name, std::move(currentVarSizes), std::move(value)); + vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value)); while (this->checkNext(Token::COMMA)) { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { @@ -517,7 +553,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods, return nullptr; } } - vars.emplace_back(this->text(name), std::move(currentVarSizes), std::move(value)); + vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value)); } if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; @@ -544,13 +580,14 @@ std::unique_ptr<ASTParameter> Parser::parameter() { if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) { return nullptr; } - sizes.push_back(SkSL::stoi(this->text(sizeToken))); + sizes.push_back(SkSL::stoi(sizeToken.fText)); if (!this->expect(Token::RBRACKET, "']'")) { return nullptr; } } - return std::unique_ptr<ASTParameter>(new ASTParameter(name.fOffset, modifiers, std::move(type), - this->text(name), std::move(sizes))); + return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers, + std::move(type), name.fText, + std::move(sizes))); } /** (EQ INT_LITERAL)? */ @@ -560,7 +597,7 @@ int Parser::layoutInt() { } Token resultToken; if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) { - return SkSL::stoi(this->text(resultToken)); + return SkSL::stoi(resultToken.fText); } return -1; } @@ -570,13 +607,13 @@ String Parser::layoutCode() { if (!this->expect(Token::EQ, "'='")) { return ""; } - Token start = this->nextRawToken(); + Token start = this->nextRawToken(true); this->pushback(start); String code; int level = 1; bool done = false; while (!done) { - Token next = this->nextRawToken(); + Token next = this->nextRawToken(true); switch (next.fKind) { case Token::LPAREN: ++level; @@ -590,7 +627,7 @@ String Parser::layoutCode() { } break; case Token::END_OF_FILE: - this->error(start, "reached end of file while parsing layout"); + this->error(start.fPosition, "reached end of file while parsing layout"); return nullptr; default: break; @@ -602,7 +639,7 @@ String Parser::layoutCode() { this->pushback(std::move(next)); } else { - code += this->text(next); + code += next.fText; } } return code; @@ -614,10 +651,10 @@ Layout::Key Parser::layoutKey() { this->expect(Token::EQ, "'='"); Token key; if (this->expect(Token::IDENTIFIER, "an identifer", &key)) { - if (this->text(key) == "identity") { + if (key.fText == "identity") { return Layout::kIdentity_Key; } else { - this->error(key, "unsupported layout key"); + this->error(key.fPosition, "unsupported layout key"); } } } @@ -651,84 +688,84 @@ Layout Parser::layout() { } for (;;) { Token t = this->nextToken(); - String text = this->text(t); - fLayoutLexer.start(text.c_str(), text.size()); - int token = fLayoutLexer.next().fKind; - if (token != LayoutToken::INVALID) { + 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) { switch (token) { - case LayoutToken::LOCATION: + case Token::LOCATION: location = this->layoutInt(); break; - case LayoutToken::OFFSET: + case Token::OFFSET: offset = this->layoutInt(); break; - case LayoutToken::BINDING: + case Token::BINDING: binding = this->layoutInt(); break; - case LayoutToken::INDEX: + case Token::INDEX: index = this->layoutInt(); break; - case LayoutToken::SET: + case Token::SET: set = this->layoutInt(); break; - case LayoutToken::BUILTIN: + case Token::BUILTIN: builtin = this->layoutInt(); break; - case LayoutToken::INPUT_ATTACHMENT_INDEX: + case Token::INPUT_ATTACHMENT_INDEX: inputAttachmentIndex = this->layoutInt(); break; - case LayoutToken::ORIGIN_UPPER_LEFT: + case Token::ORIGIN_UPPER_LEFT: originUpperLeft = true; break; - case LayoutToken::OVERRIDE_COVERAGE: + case Token::OVERRIDE_COVERAGE: overrideCoverage = true; break; - case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS: + case Token::BLEND_SUPPORT_ALL_EQUATIONS: blendSupportAllEquations = true; break; - case LayoutToken::PUSH_CONSTANT: + case Token::PUSH_CONSTANT: pushConstant = true; break; - case LayoutToken::POINTS: + case Token::POINTS: primitive = Layout::kPoints_Primitive; break; - case LayoutToken::LINES: + case Token::LINES: primitive = Layout::kLines_Primitive; break; - case LayoutToken::LINE_STRIP: + case Token::LINE_STRIP: primitive = Layout::kLineStrip_Primitive; break; - case LayoutToken::LINES_ADJACENCY: + case Token::LINES_ADJACENCY: primitive = Layout::kLinesAdjacency_Primitive; break; - case LayoutToken::TRIANGLES: + case Token::TRIANGLES: primitive = Layout::kTriangles_Primitive; break; - case LayoutToken::TRIANGLE_STRIP: + case Token::TRIANGLE_STRIP: primitive = Layout::kTriangleStrip_Primitive; break; - case LayoutToken::TRIANGLES_ADJACENCY: + case Token::TRIANGLES_ADJACENCY: primitive = Layout::kTrianglesAdjacency_Primitive; break; - case LayoutToken::MAX_VERTICES: + case Token::MAX_VERTICES: maxVertices = this->layoutInt(); break; - case LayoutToken::INVOCATIONS: + case Token::INVOCATIONS: invocations = this->layoutInt(); break; - case LayoutToken::WHEN: + case Token::WHEN: when = this->layoutCode(); break; - case LayoutToken::KEY: + case Token::KEY: key = this->layoutKey(); break; - default: - ASSERT(false); } - } else if (Layout::ReadFormat(this->text(t), &format)) { + } else if (Layout::ReadFormat(t.fText, &format)) { // AST::ReadFormat stored the result in 'format'. } else { - this->error(t, ("'" + this->text(t) + "' is not a valid layout qualifier").c_str()); + this->error(t.fPosition, ("'" + t.fText + + "' is not a valid layout qualifier").c_str()); } if (this->checkNext(Token::RPAREN)) { break; @@ -862,7 +899,7 @@ std::unique_ptr<ASTStatement> Parser::statement() { return this->block(); case Token::SEMICOLON: this->nextToken(); - return std::unique_ptr<ASTStatement>(new ASTBlock(start.fOffset, + return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition, std::vector<std::unique_ptr<ASTStatement>>())); case Token::CONST: // fall through case Token::HIGHP: // fall through @@ -875,7 +912,7 @@ std::unique_ptr<ASTStatement> Parser::statement() { return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl))); } case Token::IDENTIFIER: - if (this->isType(this->text(start))) { + if (this->isType(start.fText)) { auto decl = this->varDeclarations(); if (!decl) { return nullptr; @@ -895,8 +932,8 @@ std::unique_ptr<ASTType> Parser::type() { if (!this->expect(Token::IDENTIFIER, "a type", &type)) { return nullptr; } - if (!this->isType(this->text(type))) { - this->error(type, ("no type named '" + this->text(type) + "'").c_str()); + if (!this->isType(type.fText)) { + this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str()); return nullptr; } std::vector<int> sizes; @@ -913,7 +950,7 @@ std::unique_ptr<ASTType> Parser::type() { } this->expect(Token::RBRACKET, "']'"); } - return std::unique_ptr<ASTType>(new ASTType(type.fOffset, this->text(type), + return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText), ASTType::kIdentifier_Kind, sizes)); } @@ -927,7 +964,7 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { // 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, "no type named '" + this->text(name) + "'"); + this->error(name.fPosition, "no type named '" + name.fText + "'"); return nullptr; } this->nextToken(); @@ -941,9 +978,8 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { } this->nextToken(); std::vector<std::unique_ptr<ASTExpression>> sizes; - StringFragment instanceName; - Token instanceNameToken; - if (this->checkNext(Token::IDENTIFIER, &instanceNameToken)) { + Token instanceName; + if (this->checkNext(Token::IDENTIFIER, &instanceName)) { while (this->checkNext(Token::LBRACKET)) { if (this->peek().fKind != Token::RBRACKET) { std::unique_ptr<ASTExpression> size = this->expression(); @@ -956,13 +992,12 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { } this->expect(Token::RBRACKET, "']'"); } - instanceName = this->text(instanceNameToken); } this->expect(Token::SEMICOLON, "';'"); - return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fOffset, mods, - this->text(name), + return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods, + std::move(name.fText), std::move(decls), - instanceName, + std::move(instanceName.fText), std::move(sizes))); } @@ -994,7 +1029,7 @@ std::unique_ptr<ASTIfStatement> Parser::ifStatement() { return nullptr; } } - return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fOffset, + return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, isStatic, std::move(test), std::move(ifTrue), @@ -1027,7 +1062,7 @@ std::unique_ptr<ASTDoStatement> Parser::doStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fOffset, + return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition, std::move(statement), std::move(test))); } @@ -1052,7 +1087,7 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() { if (!statement) { return nullptr; } - return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fOffset, + return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition, std::move(test), std::move(statement))); } @@ -1079,7 +1114,7 @@ std::unique_ptr<ASTSwitchCase> Parser::switchCase() { } statements.push_back(std::move(s)); } - return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fOffset, std::move(value), + return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value), std::move(statements))); } @@ -1127,13 +1162,13 @@ std::unique_ptr<ASTStatement> Parser::switchStatement() { } statements.push_back(std::move(s)); } - cases.emplace_back(new ASTSwitchCase(defaultStart.fOffset, nullptr, + cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr, std::move(statements))); } if (!this->expect(Token::RBRACE, "'}'")) { return nullptr; } - return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fOffset, + return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition, isStatic, std::move(value), std::move(cases))); @@ -1165,7 +1200,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() { break; } case Token::IDENTIFIER: { - if (this->isType(this->text(nextToken))) { + if (this->isType(nextToken.fText)) { std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations(); if (!vd) { return nullptr; @@ -1202,7 +1237,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() { if (!statement) { return nullptr; } - return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fOffset, + return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition, std::move(initializer), std::move(test), std::move(next), std::move(statement))); @@ -1224,7 +1259,7 @@ std::unique_ptr<ASTReturnStatement> Parser::returnStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fOffset, + return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition, std::move(expression))); } @@ -1237,7 +1272,7 @@ std::unique_ptr<ASTBreakStatement> Parser::breakStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fOffset)); + return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition)); } /* CONTINUE SEMICOLON */ @@ -1249,7 +1284,7 @@ std::unique_ptr<ASTContinueStatement> Parser::continueStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fOffset)); + return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition)); } /* DISCARD SEMICOLON */ @@ -1261,7 +1296,7 @@ std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fOffset)); + return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition)); } /* LBRACE statement* RBRACE */ @@ -1279,10 +1314,10 @@ std::unique_ptr<ASTBlock> Parser::block() { switch (this->peek().fKind) { case Token::RBRACE: this->nextToken(); - return std::unique_ptr<ASTBlock>(new ASTBlock(start.fOffset, + return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition, std::move(statements))); case Token::END_OF_FILE: - this->error(this->peek(), "expected '}', but found end of file"); + this->error(this->peek().fPosition, "expected '}', but found end of file"); return nullptr; default: { std::unique_ptr<ASTStatement> statement = this->statement(); @@ -1679,7 +1714,7 @@ std::unique_ptr<ASTSuffix> Parser::suffix() { switch (next.fKind) { case Token::LBRACKET: { if (this->checkNext(Token::RBRACKET)) { - return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fOffset)); + return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition)); } std::unique_ptr<ASTExpression> e = this->expression(); if (!e) { @@ -1689,10 +1724,10 @@ std::unique_ptr<ASTSuffix> Parser::suffix() { return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e))); } case Token::DOT: { - int offset = this->peek().fOffset; - StringFragment text; + Position pos = this->peek().fPosition; + String text; if (this->identifier(&text)) { - return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(offset, std::move(text))); + return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text))); } return nullptr; } @@ -1711,17 +1746,17 @@ std::unique_ptr<ASTSuffix> Parser::suffix() { } } this->expect(Token::RPAREN, "')' to complete function parameters"); - return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fOffset, + return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition, std::move(parameters))); } case Token::PLUSPLUS: - return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset, + return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, ASTSuffix::kPostIncrement_Kind)); case Token::MINUSMINUS: - return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset, + return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, ASTSuffix::kPostDecrement_Kind)); default: { - this->error(next, "expected expression suffix, but found '" + this->text(next) + + this->error(next.fPosition, "expected expression suffix, but found '" + next.fText + "'\n"); return nullptr; } @@ -1734,23 +1769,23 @@ std::unique_ptr<ASTExpression> Parser::term() { Token t = this->peek(); switch (t.fKind) { case Token::IDENTIFIER: { - StringFragment text; + String text; if (this->identifier(&text)) { - result.reset(new ASTIdentifier(t.fOffset, std::move(text))); + result.reset(new ASTIdentifier(t.fPosition, std::move(text))); } break; } case Token::INT_LITERAL: { int64_t i; if (this->intLiteral(&i)) { - result.reset(new ASTIntLiteral(t.fOffset, i)); + result.reset(new ASTIntLiteral(t.fPosition, i)); } break; } case Token::FLOAT_LITERAL: { double f; if (this->floatLiteral(&f)) { - result.reset(new ASTFloatLiteral(t.fOffset, f)); + result.reset(new ASTFloatLiteral(t.fPosition, f)); } break; } @@ -1758,7 +1793,7 @@ std::unique_ptr<ASTExpression> Parser::term() { case Token::FALSE_LITERAL: { bool b; if (this->boolLiteral(&b)) { - result.reset(new ASTBoolLiteral(t.fOffset, b)); + result.reset(new ASTBoolLiteral(t.fPosition, b)); } break; } @@ -1772,7 +1807,7 @@ std::unique_ptr<ASTExpression> Parser::term() { } default: this->nextToken(); - this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'\n"); + this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n"); result = nullptr; } return result; @@ -1782,7 +1817,7 @@ std::unique_ptr<ASTExpression> Parser::term() { bool Parser::intLiteral(int64_t* dest) { Token t; if (this->expect(Token::INT_LITERAL, "integer literal", &t)) { - *dest = SkSL::stol(this->text(t)); + *dest = SkSL::stol(t.fText); return true; } return false; @@ -1792,7 +1827,7 @@ bool Parser::intLiteral(int64_t* dest) { bool Parser::floatLiteral(double* dest) { Token t; if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) { - *dest = SkSL::stod(this->text(t)); + *dest = SkSL::stod(t.fText); return true; } return false; @@ -1809,16 +1844,16 @@ bool Parser::boolLiteral(bool* dest) { *dest = false; return true; default: - this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'\n"); + this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n"); return false; } } /* IDENTIFIER */ -bool Parser::identifier(StringFragment* dest) { +bool Parser::identifier(String* dest) { Token t; if (this->expect(Token::IDENTIFIER, "identifier", &t)) { - *dest = this->text(t); + *dest = std::move(t.fText); return true; } return false; diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index 5391f6c2ee..4edd8e4e02 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -14,8 +14,7 @@ #include <unordered_set> #include "SkSLErrorReporter.h" #include "ir/SkSLLayout.h" -#include "SkSLLexer.h" -#include "SkSLLayoutLexer.h" +#include "SkSLToken.h" struct yy_buffer_state; #define YY_TYPEDEF_YY_BUFFER_STATE @@ -52,7 +51,9 @@ class SymbolTable; */ class Parser { public: - Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors); + Parser(String text, SymbolTable& types, ErrorReporter& errors); + + ~Parser(); /** * Consumes a complete .sksl file and produces a list of declarations. Errors are reported via @@ -61,15 +62,13 @@ public: */ 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. + * 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.). */ - Token nextRawToken(); + Token nextRawToken(bool needText); /** * Return the next non-whitespace token from the parse stream. @@ -104,15 +103,15 @@ private: * 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(Token token, String msg); - void error(int offset, String msg); + void error(Position p, const char* msg); + void error(Position p, String msg); + /** * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will * always return true. */ - bool isType(StringFragment name); + bool isType(const String& 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 @@ -134,7 +133,7 @@ private: std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers, std::unique_ptr<ASTType> type, - StringFragment name); + String name); std::unique_ptr<ASTParameter> parameter(); @@ -224,11 +223,10 @@ private: bool boolLiteral(bool* dest); - bool identifier(StringFragment* dest); + bool identifier(String* dest); - const char* fText; - Lexer fLexer; - LayoutLexer fLayoutLexer; + void* fScanner; + void* fLayoutScanner; 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 7ae3252fe8..d367df93cb 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -850,7 +850,8 @@ void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, OutputSt this->writeWord(word1, out); } -void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputStream& out) { +void SPIRVCodeGenerator::writeString(const char* string, OutputStream& out) { + size_t length = strlen(string); out.write(string, length); switch (length % 4) { case 1: @@ -867,25 +868,28 @@ void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputSt } } -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, 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, int32_t word1, StringFragment string, +void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out) { - this->writeOpCode(opCode, 2 + (string.fLength + 4) / 4, out); + int32_t length = (int32_t) strlen(string); + this->writeOpCode(opCode, 2 + (length + 4) / 4, out); this->writeWord(word1, out); - this->writeString(string.fChars, string.fLength, out); + this->writeString(string, out); } void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, - StringFragment string, OutputStream& out) { - this->writeOpCode(opCode, 3 + (string.fLength + 4) / 4, out); + const char* string, OutputStream& out) { + int32_t length = (int32_t) strlen(string); + this->writeOpCode(opCode, 3 + (length + 4) / 4, out); this->writeWord(word1, out); this->writeWord(word2, out); - this->writeString(string.fChars, string.fLength, out); + this->writeString(string, out); } void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, @@ -999,12 +1003,12 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout; if (fieldLayout.fOffset >= 0) { if (fieldLayout.fOffset < (int) offset) { - fErrors.error(type.fOffset, + fErrors.error(type.fPosition, "offset of field '" + type.fields()[i].fName + "' must be at " "least " + to_string((int) offset)); } if (fieldLayout.fOffset % alignment) { - fErrors.error(type.fOffset, + fErrors.error(type.fPosition, "offset of field '" + type.fields()[i].fName + "' must be a multiple" " of " + to_string((int) alignment)); } @@ -1015,7 +1019,8 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor offset += alignment - mod; } } - this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName, fNameBuffer); + this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(), + fNameBuffer); this->writeLayout(fieldLayout, resultId, i); if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset, @@ -1076,7 +1081,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) break; case Type::kArray_Kind: { if (type.columns() > 0) { - IntLiteral count(fContext, -1, type.columns()); + IntLiteral count(fContext, Position(), type.columns()); this->writeInstruction(SpvOpTypeArray, result, this->getType(type.componentType(), layout), this->writeIntLiteral(count), fConstantBuffer); @@ -1326,9 +1331,9 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn case kSubpassLoad_SpecialIntrinsic: { SpvId img = this->writeExpression(*c.fArguments[0], out); std::vector<std::unique_ptr<Expression>> 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)); + 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)); SpvId coords = this->writeConstantVector(ctor); if (1 == c.fArguments.size()) { this->writeInstruction(SpvOpImageRead, @@ -1561,7 +1566,7 @@ SpvId SPIRVCodeGenerator::writeUIntConstructor(const Constructor& c, OutputStrea void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, OutputStream& out) { - FloatLiteral zero(fContext, -1, 0); + FloatLiteral zero(fContext, Position(), 0); SpvId zeroId = this->writeFloatLiteral(zero); std::vector<SpvId> columnIds; for (int column = 0; column < type.columns(); column++) { @@ -1598,10 +1603,10 @@ void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcTyp 1)); SpvId zeroId; if (dstType.componentType() == *fContext.fFloat_Type) { - FloatLiteral zero(fContext, -1, 0.0); + FloatLiteral zero(fContext, Position(), 0.0); zeroId = this->writeFloatLiteral(zero); } else if (dstType.componentType() == *fContext.fInt_Type) { - IntLiteral zero(fContext, -1, 0); + IntLiteral zero(fContext, Position(), 0); zeroId = this->writeIntLiteral(zero); } else { ABORT("unsupported matrix component type"); @@ -1859,7 +1864,7 @@ std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, Ou case Expression::kFieldAccess_Kind: { FieldAccess& fieldExpr = (FieldAccess&) expr; chain = this->getAccessChain(*fieldExpr.fBase, out); - IntLiteral index(fContext, -1, fieldExpr.fFieldIndex); + IntLiteral index(fContext, Position(), fieldExpr.fFieldIndex); chain.push_back(this->writeIntLiteral(index)); break; } @@ -2005,7 +2010,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer(); ASSERT(base); if (count == 1) { - IntLiteral index(fContext, -1, swizzle.fComponents[0]); + IntLiteral index(fContext, Position(), swizzle.fComponents[0]); SpvId member = this->nextId(); this->writeInstruction(SpvOpAccessChain, this->getPointerType(swizzle.fType, @@ -2059,19 +2064,20 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O std::shared_ptr<SymbolTable> st(new SymbolTable(&fErrors)); ASSERT(fRTHeightFieldIndex == (SpvId) -1); std::vector<Type::Field> fields; - fields.emplace_back(Modifiers(), SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get()); - StringFragment name("sksl_synthetic_uniforms"); - Type intfStruct(-1, name, fields); + fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME), + fContext.fFloat_Type.get()); + String name("sksl_synthetic_uniforms"); + Type intfStruct(Position(), 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(-1, + Variable* intfVar = new Variable(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, intfStruct, Variable::kGlobal_Storage); fSynthetics.takeOwnership(intfVar); - InterfaceBlock intf(-1, intfVar, name, String(""), + InterfaceBlock intf(Position(), intfVar, name, String(""), std::vector<std::unique_ptr<Expression>>(), st); fRTHeightStructId = this->writeInterfaceBlock(intf); fRTHeightFieldIndex = 0; @@ -2081,7 +2087,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O SpvId xId = this->nextId(); this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId, result, 0, out); - IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex); + IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex); SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); SpvId heightPtr = this->nextId(); this->writeOpCode(SpvOpAccessChain, 5, out); @@ -2098,9 +2104,9 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O SpvId flippedYId = this->nextId(); this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId, heightRead, rawYId, out); - FloatLiteral zero(fContext, -1, 0.0); + FloatLiteral zero(fContext, Position(), 0.0); SpvId zeroId = writeFloatLiteral(zero); - FloatLiteral one(fContext, -1, 1.0); + FloatLiteral one(fContext, Position(), 1.0); SpvId oneId = writeFloatLiteral(one); SpvId flipped = this->nextId(); this->writeOpCode(SpvOpCompositeConstruct, 7, out); @@ -2503,7 +2509,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) { ASSERT(a.fOperator == Token::LOGICALAND); - BoolLiteral falseLiteral(fContext, -1, false); + BoolLiteral falseLiteral(fContext, Position(), false); SpvId falseConstant = this->writeBoolLiteral(falseLiteral); SpvId lhs = this->writeExpression(*a.fLeft, out); SpvId rhsLabel = this->nextId(); @@ -2524,7 +2530,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) { ASSERT(o.fOperator == Token::LOGICALOR); - BoolLiteral trueLiteral(fContext, -1, true); + BoolLiteral trueLiteral(fContext, Position(), true); SpvId trueConstant = this->writeBoolLiteral(trueLiteral); SpvId lhs = this->writeExpression(*o.fLeft, out); SpvId rhsLabel = this->nextId(); @@ -2578,10 +2584,10 @@ SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, Out 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, -1, 1)); + return std::unique_ptr<Expression>(new IntLiteral(context, Position(), 1)); } else if (type == *context.fFloat_Type) { - return std::unique_ptr<Expression>(new FloatLiteral(context, -1, 1.0)); + return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0)); } else { ABORT("math is unsupported on type '%s'", type.name().c_str()); } @@ -2741,7 +2747,7 @@ SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, Outpu SpvId result = fFunctionMap[&f]; this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result, SpvFunctionControlMaskNone, this->getFunctionType(f), out); - this->writeInstruction(SpvOpName, result, f.fName, fNameBuffer); + this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer); for (size_t i = 0; i < f.fParameters.size(); i++) { SpvId id = this->nextId(); fVariableMap[f.fParameters[i]] = id; @@ -2838,8 +2844,8 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { std::vector<Type::Field> fields = type->fields(); fRTHeightStructId = result; fRTHeightFieldIndex = fields.size(); - fields.emplace_back(Modifiers(), StringFragment(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); - type = new Type(type->fOffset, type->name(), fields); + fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); + type = new Type(type->fPosition, type->name(), fields); } SpvId typeId = this->getType(*type, layout); if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) { @@ -2916,7 +2922,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio fVariableMap[var] = id; SpvId type = this->getPointerType(var->fType, storageClass); this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer); - this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer); + this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); this->writePrecisionModifier(var->fModifiers, id); if (varDecl.fValue) { ASSERT(!fCurrentBlock); @@ -2952,7 +2958,7 @@ void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, Outpu fVariableMap[var] = id; SpvId type = this->getPointerType(var->fType, SpvStorageClassFunction); this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer); - this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer); + this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); if (varDecl.fValue) { SpvId value = this->writeExpression(*varDecl.fValue, out); this->writeInstruction(SpvOpStore, id, value, out); @@ -3080,7 +3086,7 @@ void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStre // 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.fOffset, "internal error: while loop support has been disabled in SPIR-V, " + fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, " "see SkSLSPIRVCodeGenerator.cpp for details"); SpvId header = this->nextId(); @@ -3112,7 +3118,7 @@ void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& ou // 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.fOffset, "internal error: do loop support has been disabled in SPIR-V, see " + fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see " "SkSLSPIRVCodeGenerator.cpp for details"); SpvId header = this->nextId(); @@ -3262,7 +3268,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& this->writeCapabilities(out); this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out); this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out); - this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->fName.fLength + 4) / 4) + + this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) + (int32_t) interfaceVars.size(), out); switch (program.fKind) { case Program::kVertex_Kind: @@ -3279,7 +3285,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& } SpvId entryPoint = fFunctionMap[main]; this->writeWord(entryPoint, out); - this->writeString(main->fName.fChars, main->fName.fLength, out); + this->writeString(main->fName.c_str(), out); for (int var : interfaceVars) { this->writeWord(var, out); } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index eb6ec40a3f..a532c9a3bc 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -241,19 +241,19 @@ private: void writeWord(int32_t word, OutputStream& out); - void writeString(const char* string, size_t length, OutputStream& out); + void writeString(const char* string, OutputStream& out); void writeLabel(SpvId id, OutputStream& out); void writeInstruction(SpvOp_ opCode, OutputStream& out); - void writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out); + void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out); void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out); - void writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string, OutputStream& out); + void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out); - void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, StringFragment string, + void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* 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 fccfff473b..f70b82c439 100644 --- a/src/sksl/SkSLSectionAndParameterHelper.h +++ b/src/sksl/SkSLSectionAndParameterHelper.h @@ -56,21 +56,21 @@ public: if (IsSupportedSection(s->fName.c_str())) { if (SectionAcceptsArgument(s->fName.c_str())) { if (!s->fArgument.size()) { - errors.error(s->fOffset, + errors.error(s->fPosition, ("section '@" + s->fName + "' requires one parameter").c_str()); } } else if (s->fArgument.size()) { - errors.error(s->fOffset, + errors.error(s->fPosition, ("section '@" + s->fName + "' has no parameters").c_str()); } } else { - errors.error(s->fOffset, + errors.error(s->fPosition, ("unsupported section '@" + s->fName + "'").c_str()); } if (!SectionPermitsDuplicates(s->fName.c_str()) && fSections.find(s->fName) != fSections.end()) { - errors.error(s->fOffset, + errors.error(s->fPosition, ("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 5c53c43c72..ac6d7f85c1 100644 --- a/src/sksl/SkSLString.cpp +++ b/src/sksl/SkSLString.cpp @@ -77,32 +77,6 @@ String String::operator+(const String& s) const { 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()); } @@ -133,28 +107,6 @@ bool operator!=(const char* s1, const String& s2) { 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 !memcmp(fChars, s, fLength); -} - -bool StringFragment::operator!=(const char* s) const { - return memcmp(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 9cfdce4768..93bd7a5773 100644 --- a/src/sksl/SkSLString.h +++ b/src/sksl/SkSLString.h @@ -8,8 +8,6 @@ #ifndef SKSL_STRING #define SKSL_STRING -#include <cstring> - #define SKSL_USE_STD_STRING #include <stdarg.h> @@ -24,33 +22,6 @@ 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; @@ -70,9 +41,6 @@ public: 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 @@ -85,11 +53,6 @@ public: 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; @@ -123,18 +86,6 @@ long stol(const String& s); } // 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 new file mode 100644 index 0000000000..2857a82547 --- /dev/null +++ b/src/sksl/SkSLToken.h @@ -0,0 +1,227 @@ +/* + * 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 c2f7b749a5..9a24970262 100644 --- a/src/sksl/ast/SkSLASTBinaryExpression.h +++ b/src/sksl/ast/SkSLASTBinaryExpression.h @@ -9,8 +9,7 @@ #define SKSL_ASTBINARYEXPRESSION #include "SkSLASTExpression.h" -#include "../SkSLCompiler.h" -#include "../SkSLLexer.h" +#include "../SkSLToken.h" namespace SkSL { @@ -20,13 +19,13 @@ namespace SkSL { struct ASTBinaryExpression : public ASTExpression { ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op, std::unique_ptr<ASTExpression> right) - : INHERITED(op.fOffset, kBinary_Kind) + : INHERITED(op.fPosition, kBinary_Kind) , fLeft(std::move(left)) , fOperator(op.fKind) , fRight(std::move(right)) {} String description() const override { - return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " + + return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " + fRight->description() + ")"; } diff --git a/src/sksl/ast/SkSLASTBlock.h b/src/sksl/ast/SkSLASTBlock.h index df01f62a15..37c0e81a95 100644 --- a/src/sksl/ast/SkSLASTBlock.h +++ b/src/sksl/ast/SkSLASTBlock.h @@ -16,8 +16,8 @@ namespace SkSL { * Represents a curly-braced block of statements. */ struct ASTBlock : public ASTStatement { - ASTBlock(int offset, std::vector<std::unique_ptr<ASTStatement>> statements) - : INHERITED(offset, kBlock_Kind) + ASTBlock(Position position, std::vector<std::unique_ptr<ASTStatement>> statements) + : INHERITED(position, 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 6782d36e7e..48e916eed5 100644 --- a/src/sksl/ast/SkSLASTBoolLiteral.h +++ b/src/sksl/ast/SkSLASTBoolLiteral.h @@ -16,8 +16,8 @@ namespace SkSL { * Represents "true" or "false". */ struct ASTBoolLiteral : public ASTExpression { - ASTBoolLiteral(int offset, bool value) - : INHERITED(offset, kBool_Kind) + ASTBoolLiteral(Position position, bool value) + : INHERITED(position, kBool_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTBreakStatement.h b/src/sksl/ast/SkSLASTBreakStatement.h index 2937dae447..079ee76d20 100644 --- a/src/sksl/ast/SkSLASTBreakStatement.h +++ b/src/sksl/ast/SkSLASTBreakStatement.h @@ -16,8 +16,8 @@ namespace SkSL { * A 'break' statement. */ struct ASTBreakStatement : public ASTStatement { - ASTBreakStatement(int offset) - : INHERITED(offset, kBreak_Kind) {} + ASTBreakStatement(Position position) + : INHERITED(position, kBreak_Kind) {} String description() const override { return String("break;"); diff --git a/src/sksl/ast/SkSLASTCallSuffix.h b/src/sksl/ast/SkSLASTCallSuffix.h index 316a0ae7cc..3ba3f0e60f 100644 --- a/src/sksl/ast/SkSLASTCallSuffix.h +++ b/src/sksl/ast/SkSLASTCallSuffix.h @@ -17,8 +17,8 @@ namespace SkSL { * A parenthesized list of arguments following an expression, indicating a function call. */ struct ASTCallSuffix : public ASTSuffix { - ASTCallSuffix(int offset, std::vector<std::unique_ptr<ASTExpression>> arguments) - : INHERITED(offset, ASTSuffix::kCall_Kind) + ASTCallSuffix(Position position, std::vector<std::unique_ptr<ASTExpression>> arguments) + : INHERITED(position, 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 30b2dae4ec..fdfce8598d 100644 --- a/src/sksl/ast/SkSLASTContinueStatement.h +++ b/src/sksl/ast/SkSLASTContinueStatement.h @@ -16,8 +16,8 @@ namespace SkSL { * A 'continue' statement. */ struct ASTContinueStatement : public ASTStatement { - ASTContinueStatement(int offset) - : INHERITED(offset, kContinue_Kind) {} + ASTContinueStatement(Position position) + : INHERITED(position, kContinue_Kind) {} String description() const override { return String("continue;"); diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h index 53aa65f6f2..873c6b2208 100644 --- a/src/sksl/ast/SkSLASTDeclaration.h +++ b/src/sksl/ast/SkSLASTDeclaration.h @@ -26,8 +26,8 @@ struct ASTDeclaration : public ASTPositionNode { kSection_Kind }; - ASTDeclaration(int offset, Kind kind) - : INHERITED(offset) + ASTDeclaration(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ast/SkSLASTDiscardStatement.h b/src/sksl/ast/SkSLASTDiscardStatement.h index 083c3f82d7..dcf6b15e64 100644 --- a/src/sksl/ast/SkSLASTDiscardStatement.h +++ b/src/sksl/ast/SkSLASTDiscardStatement.h @@ -16,8 +16,8 @@ namespace SkSL { * A 'discard' statement. */ struct ASTDiscardStatement : public ASTStatement { - ASTDiscardStatement(int offset) - : INHERITED(offset, kDiscard_Kind) {} + ASTDiscardStatement(Position position) + : INHERITED(position, kDiscard_Kind) {} String description() const override { return String("discard;"); diff --git a/src/sksl/ast/SkSLASTDoStatement.h b/src/sksl/ast/SkSLASTDoStatement.h index 36324e3685..fc97d9e142 100644 --- a/src/sksl/ast/SkSLASTDoStatement.h +++ b/src/sksl/ast/SkSLASTDoStatement.h @@ -16,9 +16,9 @@ namespace SkSL { * A 'do' loop. */ struct ASTDoStatement : public ASTStatement { - ASTDoStatement(int offset, std::unique_ptr<ASTStatement> statement, + ASTDoStatement(Position position, std::unique_ptr<ASTStatement> statement, std::unique_ptr<ASTExpression> test) - : INHERITED(offset, kDo_Kind) + : INHERITED(position, 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 0d8ddc781f..11815aef84 100644 --- a/src/sksl/ast/SkSLASTExpression.h +++ b/src/sksl/ast/SkSLASTExpression.h @@ -27,8 +27,8 @@ struct ASTExpression : public ASTPositionNode { kTernary_Kind }; - ASTExpression(int offset, Kind kind) - : INHERITED(offset) + ASTExpression(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} const Kind fKind; diff --git a/src/sksl/ast/SkSLASTExpressionStatement.h b/src/sksl/ast/SkSLASTExpressionStatement.h index 14f087f57c..398a16a23a 100644 --- a/src/sksl/ast/SkSLASTExpressionStatement.h +++ b/src/sksl/ast/SkSLASTExpressionStatement.h @@ -17,7 +17,7 @@ namespace SkSL { */ struct ASTExpressionStatement : public ASTStatement { ASTExpressionStatement(std::unique_ptr<ASTExpression> expression) - : INHERITED(expression->fOffset, kExpression_Kind) + : INHERITED(expression->fPosition, 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 c394b1d4d0..a6fde0694c 100644 --- a/src/sksl/ast/SkSLASTExtension.h +++ b/src/sksl/ast/SkSLASTExtension.h @@ -16,8 +16,8 @@ namespace SkSL { * An extension declaration. */ struct ASTExtension : public ASTDeclaration { - ASTExtension(int offset, String name) - : INHERITED(offset, kExtension_Kind) + ASTExtension(Position position, String name) + : INHERITED(position, 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 b29ddf3bda..bde1e4aec5 100644 --- a/src/sksl/ast/SkSLASTFieldSuffix.h +++ b/src/sksl/ast/SkSLASTFieldSuffix.h @@ -17,15 +17,15 @@ namespace SkSL { * actually vector swizzle (which looks the same to the parser). */ struct ASTFieldSuffix : public ASTSuffix { - ASTFieldSuffix(int offset, StringFragment field) - : INHERITED(offset, ASTSuffix::kField_Kind) - , fField(field) {} + ASTFieldSuffix(Position position, String field) + : INHERITED(position, ASTSuffix::kField_Kind) + , fField(std::move(field)) {} String description() const override { return "." + fField; } - StringFragment fField; + String fField; typedef ASTSuffix INHERITED; }; diff --git a/src/sksl/ast/SkSLASTFloatLiteral.h b/src/sksl/ast/SkSLASTFloatLiteral.h index 6e63b4e4ca..15fe836049 100644 --- a/src/sksl/ast/SkSLASTFloatLiteral.h +++ b/src/sksl/ast/SkSLASTFloatLiteral.h @@ -16,8 +16,8 @@ namespace SkSL { * A literal floating point number. */ struct ASTFloatLiteral : public ASTExpression { - ASTFloatLiteral(int offset, double value) - : INHERITED(offset, kFloat_Kind) + ASTFloatLiteral(Position position, double value) + : INHERITED(position, kFloat_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTForStatement.h b/src/sksl/ast/SkSLASTForStatement.h index 713f9522f7..326713eb62 100644 --- a/src/sksl/ast/SkSLASTForStatement.h +++ b/src/sksl/ast/SkSLASTForStatement.h @@ -16,10 +16,10 @@ namespace SkSL { * A 'for' loop. */ struct ASTForStatement : public ASTStatement { - ASTForStatement(int offset, std::unique_ptr<ASTStatement> initializer, + ASTForStatement(Position position, std::unique_ptr<ASTStatement> initializer, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next, std::unique_ptr<ASTStatement> statement) - : INHERITED(offset, kFor_Kind) + : INHERITED(position, 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 4fa2482d8b..36d8a3af9f 100644 --- a/src/sksl/ast/SkSLASTFunction.h +++ b/src/sksl/ast/SkSLASTFunction.h @@ -19,13 +19,13 @@ namespace SkSL { * A function declaration or definition. The fBody field will be null for declarations. */ struct ASTFunction : public ASTDeclaration { - ASTFunction(int offset, Modifiers modifiers, std::unique_ptr<ASTType> returnType, - StringFragment name, std::vector<std::unique_ptr<ASTParameter>> parameters, + ASTFunction(Position position, Modifiers modifiers, std::unique_ptr<ASTType> returnType, + String name, std::vector<std::unique_ptr<ASTParameter>> parameters, std::unique_ptr<ASTBlock> body) - : INHERITED(offset, kFunction_Kind) + : INHERITED(position, kFunction_Kind) , fModifiers(modifiers) , fReturnType(std::move(returnType)) - , fName(name) + , fName(std::move(name)) , fParameters(std::move(parameters)) , fBody(std::move(body)) {} @@ -47,7 +47,7 @@ struct ASTFunction : public ASTDeclaration { const Modifiers fModifiers; const std::unique_ptr<ASTType> fReturnType; - const StringFragment fName; + const String 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 a84370ec3f..016123cf8c 100644 --- a/src/sksl/ast/SkSLASTIdentifier.h +++ b/src/sksl/ast/SkSLASTIdentifier.h @@ -16,15 +16,15 @@ namespace SkSL { * An identifier in an expression context. */ struct ASTIdentifier : public ASTExpression { - ASTIdentifier(int offset, StringFragment text) - : INHERITED(offset, kIdentifier_Kind) - , fText(text) {} + ASTIdentifier(Position position, String text) + : INHERITED(position, kIdentifier_Kind) + , fText(std::move(text)) {} String description() const override { - return String(fText); + return fText; } - const StringFragment fText; + const String fText; typedef ASTExpression INHERITED; }; diff --git a/src/sksl/ast/SkSLASTIfStatement.h b/src/sksl/ast/SkSLASTIfStatement.h index 85b1239e0b..2752b2b750 100644 --- a/src/sksl/ast/SkSLASTIfStatement.h +++ b/src/sksl/ast/SkSLASTIfStatement.h @@ -16,9 +16,9 @@ namespace SkSL { * An 'if' statement. */ struct ASTIfStatement : public ASTStatement { - ASTIfStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> test, + ASTIfStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse) - : INHERITED(offset, kIf_Kind) + : INHERITED(position, 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 cb19e549ef..31142e3685 100644 --- a/src/sksl/ast/SkSLASTIndexSuffix.h +++ b/src/sksl/ast/SkSLASTIndexSuffix.h @@ -18,12 +18,12 @@ namespace SkSL { * 'float[](5, 6)' are represented with a null fExpression. */ struct ASTIndexSuffix : public ASTSuffix { - ASTIndexSuffix(int offset) - : INHERITED(offset, ASTSuffix::kIndex_Kind) + ASTIndexSuffix(Position position) + : INHERITED(position, ASTSuffix::kIndex_Kind) , fExpression(nullptr) {} ASTIndexSuffix(std::unique_ptr<ASTExpression> expression) - : INHERITED(expression ? expression->fOffset : -1, ASTSuffix::kIndex_Kind) + : INHERITED(expression ? expression->fPosition : Position(), 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 927537b250..fe04347fd8 100644 --- a/src/sksl/ast/SkSLASTIntLiteral.h +++ b/src/sksl/ast/SkSLASTIntLiteral.h @@ -17,8 +17,8 @@ namespace SkSL { * appear as a unary minus being applied to an integer literal. */ struct ASTIntLiteral : public ASTExpression { - ASTIntLiteral(int offset, uint64_t value) - : INHERITED(offset, kInt_Kind) + ASTIntLiteral(Position position, uint64_t value) + : INHERITED(position, kInt_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h index d445ae0398..f111f73e18 100644 --- a/src/sksl/ast/SkSLASTInterfaceBlock.h +++ b/src/sksl/ast/SkSLASTInterfaceBlock.h @@ -23,17 +23,17 @@ namespace SkSL { */ struct ASTInterfaceBlock : public ASTDeclaration { // valueName is empty when it was not present in the source - ASTInterfaceBlock(int offset, + ASTInterfaceBlock(Position position, Modifiers modifiers, - StringFragment typeName, + String typeName, std::vector<std::unique_ptr<ASTVarDeclarations>> declarations, - StringFragment instanceName, + String instanceName, std::vector<std::unique_ptr<ASTExpression>> sizes) - : INHERITED(offset, kInterfaceBlock_Kind) + : INHERITED(position, kInterfaceBlock_Kind) , fModifiers(modifiers) - , fTypeName(typeName) + , fTypeName(std::move(typeName)) , fDeclarations(std::move(declarations)) - , fInstanceName(instanceName) + , fInstanceName(std::move(instanceName)) , fSizes(std::move(sizes)) {} String description() const override { @@ -42,7 +42,7 @@ struct ASTInterfaceBlock : public ASTDeclaration { result += fDeclarations[i]->description() + "\n"; } result += "}"; - if (fInstanceName.fLength) { + if (fInstanceName.size()) { result += " " + fInstanceName; for (const auto& size : fSizes) { result += "["; @@ -56,9 +56,9 @@ struct ASTInterfaceBlock : public ASTDeclaration { } const Modifiers fModifiers; - const StringFragment fTypeName; + const String fTypeName; const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations; - const StringFragment fInstanceName; + const String 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 5269cd54d4..ba07f168b2 100644 --- a/src/sksl/ast/SkSLASTModifiersDeclaration.h +++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h @@ -20,7 +20,7 @@ namespace SkSL { */ struct ASTModifiersDeclaration : public ASTDeclaration { ASTModifiersDeclaration(Modifiers modifiers) - : INHERITED(-1, kModifiers_Kind) + : INHERITED(Position(), kModifiers_Kind) , fModifiers(modifiers) {} String description() const { diff --git a/src/sksl/ast/SkSLASTParameter.h b/src/sksl/ast/SkSLASTParameter.h index 965e374540..01227c637e 100644 --- a/src/sksl/ast/SkSLASTParameter.h +++ b/src/sksl/ast/SkSLASTParameter.h @@ -20,12 +20,12 @@ namespace SkSL { 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(int offset, Modifiers modifiers, std::unique_ptr<ASTType> type, - StringFragment name, std::vector<int> sizes) - : INHERITED(offset) + ASTParameter(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type, + String name, std::vector<int> sizes) + : INHERITED(position) , fModifiers(modifiers) , fType(std::move(type)) - , fName(name) + , fName(std::move(name)) , fSizes(std::move(sizes)) {} String description() const override { @@ -38,7 +38,7 @@ struct ASTParameter : public ASTPositionNode { const Modifiers fModifiers; const std::unique_ptr<ASTType> fType; - const StringFragment fName; + const String fName; const std::vector<int> fSizes; typedef ASTPositionNode INHERITED; diff --git a/src/sksl/ast/SkSLASTPositionNode.h b/src/sksl/ast/SkSLASTPositionNode.h index b8f22a765b..cc435c486c 100644 --- a/src/sksl/ast/SkSLASTPositionNode.h +++ b/src/sksl/ast/SkSLASTPositionNode.h @@ -17,12 +17,10 @@ namespace SkSL { * An AST node with an associated position in the source. */ struct ASTPositionNode : public ASTNode { - ASTPositionNode(int offset) - : fOffset(offset) {} + ASTPositionNode(Position position) + : fPosition(position) {} - // character offset of this element within the program being compiled, for error reporting - // purposes - const int fOffset; + const Position fPosition; }; } // namespace diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h index 0b81ca3887..4b50ed3979 100644 --- a/src/sksl/ast/SkSLASTPrecision.h +++ b/src/sksl/ast/SkSLASTPrecision.h @@ -18,8 +18,8 @@ namespace SkSL { */ struct ASTPrecision : public ASTDeclaration { // FIXME handle the type - ASTPrecision(int offset, Modifiers::Flag precision) - : INHERITED(offset, kPrecision_Kind) + ASTPrecision(Position position, Modifiers::Flag precision) + : INHERITED(position, kPrecision_Kind) , fPrecision(precision) {} String description() const { diff --git a/src/sksl/ast/SkSLASTPrefixExpression.h b/src/sksl/ast/SkSLASTPrefixExpression.h index 0403a2f172..08e50f7bf1 100644 --- a/src/sksl/ast/SkSLASTPrefixExpression.h +++ b/src/sksl/ast/SkSLASTPrefixExpression.h @@ -9,8 +9,7 @@ #define SKSL_ASTPREFIXEXPRESSION #include "SkSLASTExpression.h" -#include "../SkSLCompiler.h" -#include "../SkSLLexer.h" +#include "../SkSLToken.h" namespace SkSL { @@ -19,12 +18,12 @@ namespace SkSL { */ struct ASTPrefixExpression : public ASTExpression { ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand) - : INHERITED(op.fOffset, kPrefix_Kind) + : INHERITED(op.fPosition, kPrefix_Kind) , fOperator(op.fKind) , fOperand(std::move(operand)) {} String description() const override { - return Compiler::OperatorName(fOperator) + fOperand->description(); + return Token::OperatorName(fOperator) + fOperand->description(); } const Token::Kind fOperator; diff --git a/src/sksl/ast/SkSLASTReturnStatement.h b/src/sksl/ast/SkSLASTReturnStatement.h index 489658a78b..6762eb3f90 100644 --- a/src/sksl/ast/SkSLASTReturnStatement.h +++ b/src/sksl/ast/SkSLASTReturnStatement.h @@ -17,8 +17,8 @@ namespace SkSL { */ struct ASTReturnStatement : public ASTStatement { // expression may be null - ASTReturnStatement(int offset, std::unique_ptr<ASTExpression> expression) - : INHERITED(offset, kReturn_Kind) + ASTReturnStatement(Position position, std::unique_ptr<ASTExpression> expression) + : INHERITED(position, 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 6c1f8eefa2..d0887e20fe 100644 --- a/src/sksl/ast/SkSLASTSection.h +++ b/src/sksl/ast/SkSLASTSection.h @@ -16,8 +16,8 @@ namespace SkSL { * A section declaration (e.g. @body { body code here }).. */ struct ASTSection : public ASTDeclaration { - ASTSection(int offset, String name, String arg, String text) - : INHERITED(offset, kSection_Kind) + ASTSection(Position position, String name, String arg, String text) + : INHERITED(position, 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 c22a2fbb0a..1989a1fce6 100644 --- a/src/sksl/ast/SkSLASTStatement.h +++ b/src/sksl/ast/SkSLASTStatement.h @@ -33,8 +33,8 @@ struct ASTStatement : public ASTPositionNode { kDiscard_Kind }; - ASTStatement(int offset, Kind kind) - : INHERITED(offset) + ASTStatement(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ast/SkSLASTSuffix.h b/src/sksl/ast/SkSLASTSuffix.h index 898855c478..f06c6fd362 100644 --- a/src/sksl/ast/SkSLASTSuffix.h +++ b/src/sksl/ast/SkSLASTSuffix.h @@ -26,8 +26,8 @@ struct ASTSuffix : public ASTPositionNode { kPostDecrement_Kind }; - ASTSuffix(int offset, Kind kind) - : INHERITED(offset) + ASTSuffix(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTSuffixExpression.h b/src/sksl/ast/SkSLASTSuffixExpression.h index 31cddb29d1..2cff9a865f 100644 --- a/src/sksl/ast/SkSLASTSuffixExpression.h +++ b/src/sksl/ast/SkSLASTSuffixExpression.h @@ -18,7 +18,7 @@ namespace SkSL { */ struct ASTSuffixExpression : public ASTExpression { ASTSuffixExpression(std::unique_ptr<ASTExpression> base, std::unique_ptr<ASTSuffix> suffix) - : INHERITED(base->fOffset, kSuffix_Kind) + : INHERITED(base->fPosition, 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 221e2128ed..405013a6a7 100644 --- a/src/sksl/ast/SkSLASTSwitchCase.h +++ b/src/sksl/ast/SkSLASTSwitchCase.h @@ -17,9 +17,9 @@ namespace SkSL { */ struct ASTSwitchCase : public ASTStatement { // a null value means "default:" - ASTSwitchCase(int offset, std::unique_ptr<ASTExpression> value, + ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value, std::vector<std::unique_ptr<ASTStatement>> statements) - : INHERITED(offset, kSwitch_Kind) + : INHERITED(position, 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 3bee0a4728..ecd0a6755d 100644 --- a/src/sksl/ast/SkSLASTSwitchStatement.h +++ b/src/sksl/ast/SkSLASTSwitchStatement.h @@ -17,9 +17,9 @@ namespace SkSL { * A 'switch' statement. */ struct ASTSwitchStatement : public ASTStatement { - ASTSwitchStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> value, + ASTSwitchStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> value, std::vector<std::unique_ptr<ASTSwitchCase>> cases) - : INHERITED(offset, kSwitch_Kind) + : INHERITED(position, 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 35795e9f12..07c92975e0 100644 --- a/src/sksl/ast/SkSLASTTernaryExpression.h +++ b/src/sksl/ast/SkSLASTTernaryExpression.h @@ -19,7 +19,7 @@ struct ASTTernaryExpression : public ASTExpression { ASTTernaryExpression(std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> ifTrue, std::unique_ptr<ASTExpression> ifFalse) - : INHERITED(test->fOffset, kTernary_Kind) + : INHERITED(test->fPosition, 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 44fd95bdc7..57a8025b7b 100644 --- a/src/sksl/ast/SkSLASTType.h +++ b/src/sksl/ast/SkSLASTType.h @@ -21,9 +21,9 @@ struct ASTType : public ASTPositionNode { kStruct_Kind }; - ASTType(int offset, StringFragment name, Kind kind, std::vector<int> sizes) - : INHERITED(offset) - , fName(name) + ASTType(Position position, String name, Kind kind, std::vector<int> sizes) + : INHERITED(position) + , fName(std::move(name)) , fKind(kind) , fSizes(std::move(sizes)) {} @@ -31,7 +31,7 @@ struct ASTType : public ASTPositionNode { return fName; } - const StringFragment fName; + const String fName; const Kind fKind; diff --git a/src/sksl/ast/SkSLASTVarDeclaration.h b/src/sksl/ast/SkSLASTVarDeclaration.h index 38c9104865..2dcb9787ea 100644 --- a/src/sksl/ast/SkSLASTVarDeclaration.h +++ b/src/sksl/ast/SkSLASTVarDeclaration.h @@ -22,7 +22,7 @@ namespace SkSL { * instances. */ struct ASTVarDeclaration { - ASTVarDeclaration(StringFragment name, + ASTVarDeclaration(const String name, std::vector<std::unique_ptr<ASTExpression>> sizes, std::unique_ptr<ASTExpression> value) : fName(name) @@ -30,7 +30,7 @@ struct ASTVarDeclaration { , 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 @@ struct ASTVarDeclaration { return result; } - StringFragment fName; + String fName; // array sizes, if any. e.g. 'foo[3][]' has sizes [3, null] std::vector<std::unique_ptr<ASTExpression>> fSizes; @@ -60,7 +60,7 @@ struct ASTVarDeclarations : public ASTDeclaration { ASTVarDeclarations(Modifiers modifiers, std::unique_ptr<ASTType> type, std::vector<ASTVarDeclaration> vars) - : INHERITED(type->fOffset, kVar_Kind) + : INHERITED(type->fPosition, 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 8ec5bf6789..c3a4069ba0 100644 --- a/src/sksl/ast/SkSLASTVarDeclarationStatement.h +++ b/src/sksl/ast/SkSLASTVarDeclarationStatement.h @@ -18,7 +18,7 @@ namespace SkSL { */ struct ASTVarDeclarationStatement : public ASTStatement { ASTVarDeclarationStatement(std::unique_ptr<ASTVarDeclarations> decl) - : INHERITED(decl->fOffset, kVarDeclaration_Kind) + : INHERITED(decl->fPosition, 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 c0da0afb7d..e63c50293a 100644 --- a/src/sksl/ast/SkSLASTWhileStatement.h +++ b/src/sksl/ast/SkSLASTWhileStatement.h @@ -16,9 +16,9 @@ namespace SkSL { * A 'while' statement. */ struct ASTWhileStatement : public ASTStatement { - ASTWhileStatement(int offset, std::unique_ptr<ASTExpression> test, + ASTWhileStatement(Position position, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTStatement> statement) - : INHERITED(offset, kWhile_Kind) + : INHERITED(position, 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 new file mode 100644 index 0000000000..ad73b63583 --- /dev/null +++ b/src/sksl/disable_flex_warnings.h @@ -0,0 +1,28 @@ +/* + * 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 c26994edf2..789db5783b 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 "../SkSLLexer.h" +#include "../SkSLToken.h" namespace SkSL { @@ -19,9 +19,9 @@ namespace SkSL { * A binary operation. */ struct BinaryExpression : public Expression { - BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op, + BinaryExpression(Position position, std::unique_ptr<Expression> left, Token::Kind op, std::unique_ptr<Expression> right, const Type& type) - : INHERITED(offset, kBinary_Kind, type) + : INHERITED(position, kBinary_Kind, type) , fLeft(std::move(left)) , fOperator(op) , fRight(std::move(right)) {} @@ -34,12 +34,12 @@ struct BinaryExpression : public Expression { } bool hasSideEffects() const override { - return Compiler::IsAssignment(fOperator) || fLeft->hasSideEffects() || + return Token::IsAssignment(fOperator) || fLeft->hasSideEffects() || fRight->hasSideEffects(); } String description() const override { - return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " + + return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " + fRight->description() + ")"; } diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h index af1975396e..bcd4bb1b59 100644 --- a/src/sksl/ir/SkSLBlock.h +++ b/src/sksl/ir/SkSLBlock.h @@ -17,9 +17,9 @@ namespace SkSL { * A block of multiple statements functioning as a single statement. */ struct Block : public Statement { - Block(int offset, std::vector<std::unique_ptr<Statement>> statements, + Block(Position position, std::vector<std::unique_ptr<Statement>> statements, const std::shared_ptr<SymbolTable> symbols = nullptr) - : INHERITED(offset, kBlock_Kind) + : INHERITED(position, 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 9a69f0f138..a4151b8b35 100644 --- a/src/sksl/ir/SkSLBoolLiteral.h +++ b/src/sksl/ir/SkSLBoolLiteral.h @@ -17,8 +17,8 @@ namespace SkSL { * Represents 'true' or 'false'. */ struct BoolLiteral : public Expression { - BoolLiteral(const Context& context, int offset, bool value) - : INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type) + BoolLiteral(const Context& context, Position position, bool value) + : INHERITED(position, 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 da392f5960..f6edc558e5 100644 --- a/src/sksl/ir/SkSLBreakStatement.h +++ b/src/sksl/ir/SkSLBreakStatement.h @@ -17,8 +17,8 @@ namespace SkSL { * A 'break' statement. */ struct BreakStatement : public Statement { - BreakStatement(int offset) - : INHERITED(offset, kBreak_Kind) {} + BreakStatement(Position position) + : INHERITED(position, kBreak_Kind) {} String description() const override { return String("break;"); diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h index 32fc0fb2e7..beed0f702d 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 "float2(x, y)". + * Represents the construction of a compound type, such as "float2x, 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,8 +25,9 @@ namespace SkSL { * collection of vectors and scalars totalling exactly the right number of scalar components. */ struct Constructor : public Expression { - Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments) - : INHERITED(offset, kConstructor_Kind, type) + Constructor(Position position, const Type& type, + std::vector<std::unique_ptr<Expression>> arguments) + : INHERITED(position, kConstructor_Kind, type) , fArguments(std::move(arguments)) {} std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, @@ -36,13 +37,13 @@ struct Constructor : public Expression { // promote float(1) to 1.0 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext, - fOffset, + fPosition, 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, - fOffset, + fPosition, intValue, &fType)); } @@ -95,8 +96,8 @@ struct Constructor : public Expression { // a constant scalar constructor should have been collapsed down to the appropriate // literal ASSERT(fType.kind() == Type::kMatrix_Kind); - const FloatLiteral fzero(context, -1, 0); - const IntLiteral izero(context, -1, 0); + const FloatLiteral fzero(context, Position(), 0); + const IntLiteral izero(context, Position(), 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 6ed40c404f..3f5bc1d4bb 100644 --- a/src/sksl/ir/SkSLContinueStatement.h +++ b/src/sksl/ir/SkSLContinueStatement.h @@ -17,8 +17,8 @@ namespace SkSL { * A 'continue' statement. */ struct ContinueStatement : public Statement { - ContinueStatement(int offset) - : INHERITED(offset, kContinue_Kind) {} + ContinueStatement(Position position) + : INHERITED(position, kContinue_Kind) {} String description() const override { return String("continue;"); diff --git a/src/sksl/ir/SkSLDiscardStatement.h b/src/sksl/ir/SkSLDiscardStatement.h index b62530e6f3..62124668ee 100644 --- a/src/sksl/ir/SkSLDiscardStatement.h +++ b/src/sksl/ir/SkSLDiscardStatement.h @@ -17,8 +17,8 @@ namespace SkSL { * A 'discard' statement. */ struct DiscardStatement : public Statement { - DiscardStatement(int offset) - : INHERITED(offset, kDiscard_Kind) {} + DiscardStatement(Position position) + : INHERITED(position, kDiscard_Kind) {} String description() const override { return String("discard;"); diff --git a/src/sksl/ir/SkSLDoStatement.h b/src/sksl/ir/SkSLDoStatement.h index 3abec550eb..f1ecd9a8bf 100644 --- a/src/sksl/ir/SkSLDoStatement.h +++ b/src/sksl/ir/SkSLDoStatement.h @@ -17,9 +17,9 @@ namespace SkSL { * A 'do' statement. */ struct DoStatement : public Statement { - DoStatement(int offset, std::unique_ptr<Statement> statement, + DoStatement(Position position, std::unique_ptr<Statement> statement, std::unique_ptr<Expression> test) - : INHERITED(offset, kDo_Kind) + : INHERITED(position, 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 555e66061d..286610f078 100644 --- a/src/sksl/ir/SkSLExpression.h +++ b/src/sksl/ir/SkSLExpression.h @@ -44,8 +44,8 @@ struct Expression : public IRNode { kDefined_Kind }; - Expression(int offset, Kind kind, const Type& type) - : INHERITED(offset) + Expression(Position position, Kind kind, const Type& type) + : INHERITED(position) , fKind(kind) , fType(std::move(type)) {} diff --git a/src/sksl/ir/SkSLExpressionStatement.h b/src/sksl/ir/SkSLExpressionStatement.h index 215763b8fd..d1ab8e9ed9 100644 --- a/src/sksl/ir/SkSLExpressionStatement.h +++ b/src/sksl/ir/SkSLExpressionStatement.h @@ -18,7 +18,7 @@ namespace SkSL { */ struct ExpressionStatement : public Statement { ExpressionStatement(std::unique_ptr<Expression> expression) - : INHERITED(expression->fOffset, kExpression_Kind) + : INHERITED(expression->fPosition, 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 b5a48b94ab..70dc6b3eaf 100644 --- a/src/sksl/ir/SkSLExtension.h +++ b/src/sksl/ir/SkSLExtension.h @@ -16,8 +16,8 @@ namespace SkSL { * An extension declaration. */ struct Extension : public ProgramElement { - Extension(int offset, String name) - : INHERITED(offset, kExtension_Kind) + Extension(Position position, String name) + : INHERITED(position, 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 fe2af7fa6e..abea730da1 100644 --- a/src/sksl/ir/SkSLField.h +++ b/src/sksl/ir/SkSLField.h @@ -22,8 +22,8 @@ namespace SkSL { * result of declaring anonymous interface blocks. */ struct Field : public Symbol { - Field(int offset, const Variable& owner, int fieldIndex) - : INHERITED(offset, kField_Kind, owner.fType.fields()[fieldIndex].fName) + Field(Position position, const Variable& owner, int fieldIndex) + : INHERITED(position, 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 0f66dec5a4..e0a335f528 100644 --- a/src/sksl/ir/SkSLFieldAccess.h +++ b/src/sksl/ir/SkSLFieldAccess.h @@ -26,7 +26,7 @@ struct FieldAccess : public Expression { FieldAccess(std::unique_ptr<Expression> base, int fieldIndex, OwnerKind ownerKind = kDefault_OwnerKind) - : INHERITED(base->fOffset, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType) + : INHERITED(base->fPosition, 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 e6a3062f36..21a485fb0a 100644 --- a/src/sksl/ir/SkSLFloatLiteral.h +++ b/src/sksl/ir/SkSLFloatLiteral.h @@ -17,9 +17,9 @@ namespace SkSL { * A literal floating point number. */ struct FloatLiteral : public Expression { - FloatLiteral(const Context& context, int offset, double value, + FloatLiteral(const Context& context, Position position, double value, const Type* type = nullptr) - : INHERITED(offset, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type) + : INHERITED(position, 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 6896ceb902..ca3e6cfb7a 100644 --- a/src/sksl/ir/SkSLForStatement.h +++ b/src/sksl/ir/SkSLForStatement.h @@ -18,10 +18,10 @@ namespace SkSL { * A 'for' statement. */ struct ForStatement : public Statement { - ForStatement(int offset, std::unique_ptr<Statement> initializer, + ForStatement(Position position, 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(offset, kFor_Kind) + : INHERITED(position, 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 115281d63d..44f8c7ed5a 100644 --- a/src/sksl/ir/SkSLFunctionCall.h +++ b/src/sksl/ir/SkSLFunctionCall.h @@ -17,9 +17,9 @@ namespace SkSL { * A function invocation. */ struct FunctionCall : public Expression { - FunctionCall(int offset, const Type& type, const FunctionDeclaration& function, + FunctionCall(Position position, const Type& type, const FunctionDeclaration& function, std::vector<std::unique_ptr<Expression>> arguments) - : INHERITED(offset, kFunctionCall_Kind, type) + : INHERITED(position, kFunctionCall_Kind, type) , fFunction(std::move(function)) , fArguments(std::move(arguments)) {} @@ -33,7 +33,7 @@ struct FunctionCall : public Expression { } String description() const override { - String result = String(fFunction.fName) + "("; + String result = 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 d0f9d240d7..64236d3980 100644 --- a/src/sksl/ir/SkSLFunctionDeclaration.h +++ b/src/sksl/ir/SkSLFunctionDeclaration.h @@ -21,9 +21,9 @@ namespace SkSL { * A function declaration (not a definition -- does not contain a body). */ struct FunctionDeclaration : public Symbol { - FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name, + FunctionDeclaration(Position position, Modifiers modifiers, String name, std::vector<const Variable*> parameters, const Type& returnType) - : INHERITED(offset, kFunctionDeclaration_Kind, std::move(name)) + : INHERITED(position, 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 e0dabc5791..0277db1f07 100644 --- a/src/sksl/ir/SkSLFunctionDefinition.h +++ b/src/sksl/ir/SkSLFunctionDefinition.h @@ -18,9 +18,9 @@ namespace SkSL { * A function definition (a declaration plus an associated block of code). */ struct FunctionDefinition : public ProgramElement { - FunctionDefinition(int offset, const FunctionDeclaration& declaration, + FunctionDefinition(Position position, const FunctionDeclaration& declaration, std::unique_ptr<Statement> body) - : INHERITED(offset, kFunction_Kind) + : INHERITED(position, kFunction_Kind) , fDeclaration(declaration) , fBody(std::move(body)) {} diff --git a/src/sksl/ir/SkSLFunctionReference.h b/src/sksl/ir/SkSLFunctionReference.h index 58831c5e99..ee761c2639 100644 --- a/src/sksl/ir/SkSLFunctionReference.h +++ b/src/sksl/ir/SkSLFunctionReference.h @@ -19,9 +19,9 @@ namespace SkSL { * always eventually replaced by FunctionCalls in valid programs. */ struct FunctionReference : public Expression { - FunctionReference(const Context& context, int offset, + FunctionReference(const Context& context, Position position, std::vector<const FunctionDeclaration*> function) - : INHERITED(offset, kFunctionReference_Kind, *context.fInvalid_Type) + : INHERITED(position, 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 5ada50607e..139be32f44 100644 --- a/src/sksl/ir/SkSLIRNode.h +++ b/src/sksl/ir/SkSLIRNode.h @@ -8,7 +8,7 @@ #ifndef SKSL_IRNODE #define SKSL_IRNODE -#include "../SkSLLexer.h" +#include "../SkSLPosition.h" namespace SkSL { @@ -17,16 +17,14 @@ namespace SkSL { * version of the program (all types determined, everything validated), ready for code generation. */ struct IRNode { - IRNode(int offset) - : fOffset(offset) {} + IRNode(Position position) + : fPosition(position) {} virtual ~IRNode() {} virtual String description() const = 0; - // character offset of this element within the program being compiled, for error reporting - // purposes - const int fOffset; + const Position fPosition; }; } // namespace diff --git a/src/sksl/ir/SkSLIfStatement.h b/src/sksl/ir/SkSLIfStatement.h index 4c2ca0b1fa..b09c10ee95 100644 --- a/src/sksl/ir/SkSLIfStatement.h +++ b/src/sksl/ir/SkSLIfStatement.h @@ -17,9 +17,9 @@ namespace SkSL { * An 'if' statement. */ struct IfStatement : public Statement { - IfStatement(int offset, bool isStatic, std::unique_ptr<Expression> test, + IfStatement(Position position, bool isStatic, std::unique_ptr<Expression> test, std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse) - : INHERITED(offset, kIf_Kind) + : INHERITED(position, 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 2daf1b552a..c305365049 100644 --- a/src/sksl/ir/SkSLIndexExpression.h +++ b/src/sksl/ir/SkSLIndexExpression.h @@ -45,7 +45,7 @@ static const Type& index_type(const Context& context, const Type& type) { struct IndexExpression : public Expression { IndexExpression(const Context& context, std::unique_ptr<Expression> base, std::unique_ptr<Expression> index) - : INHERITED(base->fOffset, kIndex_Kind, index_type(context, base->fType)) + : INHERITED(base->fPosition, 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 da2b4082de..6199f96610 100644 --- a/src/sksl/ir/SkSLIntLiteral.h +++ b/src/sksl/ir/SkSLIntLiteral.h @@ -19,8 +19,8 @@ namespace SkSL { 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, int offset, int64_t value, const Type* type = nullptr) - : INHERITED(offset, kIntLiteral_Kind, type ? *type : *context.fInt_Type) + IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr) + : INHERITED(position, 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 03986b87cd..a28a6a1b54 100644 --- a/src/sksl/ir/SkSLInterfaceBlock.h +++ b/src/sksl/ir/SkSLInterfaceBlock.h @@ -25,10 +25,10 @@ namespace SkSL { * At the IR level, this is represented by a single variable of struct type. */ struct InterfaceBlock : public ProgramElement { - InterfaceBlock(int offset, const Variable* var, String typeName, String instanceName, + InterfaceBlock(Position position, const Variable* var, String typeName, String instanceName, std::vector<std::unique_ptr<Expression>> sizes, std::shared_ptr<SymbolTable> typeOwner) - : INHERITED(offset, kInterfaceBlock_Kind) + : INHERITED(position, 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 5c9608f02f..a0ce74852d 100644 --- a/src/sksl/ir/SkSLModifiersDeclaration.h +++ b/src/sksl/ir/SkSLModifiersDeclaration.h @@ -20,7 +20,7 @@ namespace SkSL { */ struct ModifiersDeclaration : public ProgramElement { ModifiersDeclaration(Modifiers modifiers) - : INHERITED(-1, kModifiers_Kind) + : INHERITED(Position(), kModifiers_Kind) , fModifiers(modifiers) {} String description() const { diff --git a/src/sksl/ir/SkSLNop.h b/src/sksl/ir/SkSLNop.h index e7aae9b7b8..5ebea40583 100644 --- a/src/sksl/ir/SkSLNop.h +++ b/src/sksl/ir/SkSLNop.h @@ -18,7 +18,7 @@ namespace SkSL { */ struct Nop : public Statement { Nop() - : INHERITED(-1, kNop_Kind) {} + : INHERITED(Position(), kNop_Kind) {} virtual bool isEmpty() const override { return true; diff --git a/src/sksl/ir/SkSLPostfixExpression.h b/src/sksl/ir/SkSLPostfixExpression.h index c53f1de507..e02555db70 100644 --- a/src/sksl/ir/SkSLPostfixExpression.h +++ b/src/sksl/ir/SkSLPostfixExpression.h @@ -9,7 +9,7 @@ #define SKSL_POSTFIXEXPRESSION #include "SkSLExpression.h" -#include "SkSLLexer.h" +#include "SkSLToken.h" namespace SkSL { @@ -18,7 +18,7 @@ namespace SkSL { */ struct PostfixExpression : public Expression { PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op) - : INHERITED(operand->fOffset, kPostfix_Kind, operand->fType) + : INHERITED(operand->fPosition, kPostfix_Kind, operand->fType) , fOperand(std::move(operand)) , fOperator(op) {} @@ -27,7 +27,7 @@ struct PostfixExpression : public Expression { } String description() const override { - return fOperand->description() + Compiler::OperatorName(fOperator); + return fOperand->description() + Token::OperatorName(fOperator); } std::unique_ptr<Expression> fOperand; diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h index d5d97b2517..5ac84c66b1 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 "SkSLLexer.h" +#include "SkSLToken.h" namespace SkSL { @@ -20,7 +20,7 @@ namespace SkSL { */ struct PrefixExpression : public Expression { PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand) - : INHERITED(operand->fOffset, kPrefix_Kind, operand->fType) + : INHERITED(operand->fPosition, kPrefix_Kind, operand->fType) , fOperand(std::move(operand)) , fOperator(op) {} @@ -38,7 +38,7 @@ struct PrefixExpression : public Expression { if (fOperand->fKind == Expression::kFloatLiteral_Kind) { return std::unique_ptr<Expression>(new FloatLiteral( irGenerator.fContext, - fOffset, + Position(), -((FloatLiteral&) *fOperand).fValue)); } @@ -46,7 +46,7 @@ struct PrefixExpression : public Expression { } String description() const override { - return Compiler::OperatorName(fOperator) + fOperand->description(); + return Token::OperatorName(fOperator) + fOperand->description(); } std::unique_ptr<Expression> fOperand; diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 639e09b16a..a3eeaa3612 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -39,15 +39,15 @@ struct Program { : fKind(kInt_Kind) , fValue(i) {} - std::unique_ptr<Expression> literal(const Context& context, int offset) const { + std::unique_ptr<Expression> literal(const Context& context, Position position) const { switch (fKind) { case Program::Settings::Value::kBool_Kind: return std::unique_ptr<Expression>(new BoolLiteral(context, - offset, + position, fValue)); case Program::Settings::Value::kInt_Kind: return std::unique_ptr<Expression>(new IntLiteral(context, - offset, + position, fValue)); default: ASSERT(false); @@ -103,7 +103,6 @@ struct Program { }; Program(Kind kind, - std::unique_ptr<String> source, Settings settings, Modifiers::Flag defaultPrecision, Context* context, @@ -111,7 +110,6 @@ struct Program { std::shared_ptr<SymbolTable> symbols, Inputs inputs) : fKind(kind) - , fSource(std::move(source)) , fSettings(settings) , fDefaultPrecision(defaultPrecision) , fContext(context) @@ -120,7 +118,6 @@ struct Program { , 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 4a3566d287..1e2bb48641 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -25,8 +25,8 @@ struct ProgramElement : public IRNode { kSection_Kind }; - ProgramElement(int offset, Kind kind) - : INHERITED(offset) + ProgramElement(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ir/SkSLReturnStatement.h b/src/sksl/ir/SkSLReturnStatement.h index 1b479b8097..841db94669 100644 --- a/src/sksl/ir/SkSLReturnStatement.h +++ b/src/sksl/ir/SkSLReturnStatement.h @@ -17,11 +17,11 @@ namespace SkSL { * A 'return' statement. */ struct ReturnStatement : public Statement { - ReturnStatement(int offset) - : INHERITED(offset, kReturn_Kind) {} + ReturnStatement(Position position) + : INHERITED(position, kReturn_Kind) {} ReturnStatement(std::unique_ptr<Expression> expression) - : INHERITED(expression->fOffset, kReturn_Kind) + : INHERITED(expression->fPosition, 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 96c257b1f8..f9815b1caa 100644 --- a/src/sksl/ir/SkSLSection.h +++ b/src/sksl/ir/SkSLSection.h @@ -16,8 +16,8 @@ namespace SkSL { * A section declaration (e.g. @body { body code here }).. */ struct Section : public ProgramElement { - Section(int offset, String name, String arg, String text) - : INHERITED(offset, kSection_Kind) + Section(Position position, String name, String arg, String text) + : INHERITED(position, 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 f479ad167b..995fcf55bf 100644 --- a/src/sksl/ir/SkSLSetting.h +++ b/src/sksl/ir/SkSLSetting.h @@ -18,8 +18,8 @@ namespace SkSL { * collapsed down to their constant representations during the compilation process. */ struct Setting : public Expression { - Setting(int offset, String name, std::unique_ptr<Expression> value) - : INHERITED(offset, kSetting_Kind, value->fType) + Setting(Position position, String name, std::unique_ptr<Expression> value) + : INHERITED(position, 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 a116cc1c4c..1bc524451b 100644 --- a/src/sksl/ir/SkSLStatement.h +++ b/src/sksl/ir/SkSLStatement.h @@ -35,8 +35,8 @@ struct Statement : public IRNode { kWhile_Kind }; - Statement(int offset, Kind kind) - : INHERITED(offset) + Statement(Position position, Kind kind) + : INHERITED(position) , fKind(kind) {} virtual bool isEmpty() const { diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h index c33224bdbb..8043f2e787 100644 --- a/src/sksl/ir/SkSLSwitchCase.h +++ b/src/sksl/ir/SkSLSwitchCase.h @@ -17,9 +17,9 @@ namespace SkSL { * A single case of a 'switch' statement. */ struct SwitchCase : public Statement { - SwitchCase(int offset, std::unique_ptr<Expression> value, + SwitchCase(Position position, std::unique_ptr<Expression> value, std::vector<std::unique_ptr<Statement>> statements) - : INHERITED(offset, kSwitch_Kind) + : INHERITED(position, 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 68d0ef02df..dec5b749a5 100644 --- a/src/sksl/ir/SkSLSwitchStatement.h +++ b/src/sksl/ir/SkSLSwitchStatement.h @@ -17,10 +17,10 @@ namespace SkSL { * A 'switch' statement. */ struct SwitchStatement : public Statement { - SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value, + SwitchStatement(Position position, bool isStatic, std::unique_ptr<Expression> value, std::vector<std::unique_ptr<SwitchCase>> cases, const std::shared_ptr<SymbolTable> symbols) - : INHERITED(offset, kSwitch_Kind) + : INHERITED(position, 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 3256ef211a..9d7ca37bdc 100644 --- a/src/sksl/ir/SkSLSwizzle.h +++ b/src/sksl/ir/SkSLSwizzle.h @@ -65,7 +65,7 @@ static const Type& get_type(const Context& context, Expression& value, size_t co */ struct Swizzle : public Expression { Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components) - : INHERITED(base->fOffset, kSwizzle_Kind, get_type(context, *base, components.size())) + : INHERITED(base->fPosition, 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 @@ struct Swizzle : public Expression { ASSERT(fComponents.size() == 1); int64_t value = ((Constructor&) *fBase).getIVecComponent(fComponents[0]); return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, - -1, - value)); + Position(), + 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, - -1, + Position(), value)); } } diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h index f4c675319b..e883ea7555 100644 --- a/src/sksl/ir/SkSLSymbol.h +++ b/src/sksl/ir/SkSLSymbol.h @@ -24,13 +24,13 @@ struct Symbol : public IRNode { kField_Kind }; - Symbol(int offset, Kind kind, StringFragment name) - : INHERITED(offset) + Symbol(Position position, Kind kind, String name) + : INHERITED(position) , fKind(kind) - , fName(name) {} + , fName(std::move(name)) {} const Kind fKind; - StringFragment fName; + const String fName; typedef IRNode INHERITED; }; diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp index 40e8e66c9f..4d39e8bc9d 100644 --- a/src/sksl/ir/SkSLSymbolTable.cpp +++ b/src/sksl/ir/SkSLSymbolTable.cpp @@ -21,7 +21,7 @@ std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& } } -const Symbol* SymbolTable::operator[](StringFragment name) { +const Symbol* SymbolTable::operator[](const String& name) { const auto& entry = fSymbols.find(name); if (entry == fSymbols.end()) { if (fParent) { @@ -64,12 +64,12 @@ Symbol* SymbolTable::takeOwnership(Symbol* s) { return s; } -void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) { +void SymbolTable::add(const String& name, std::unique_ptr<Symbol> symbol) { this->addWithoutOwnership(name, symbol.get()); fOwnedPointers.push_back(std::move(symbol)); } -void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) { +void SymbolTable::addWithoutOwnership(const String& name, const Symbol* symbol) { const auto& existing = fSymbols.find(name); if (existing == fSymbols.end()) { fSymbols[name] = symbol; @@ -93,7 +93,7 @@ void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) this->takeOwnership(u); } } else { - fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined"); + fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined"); } } diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h index 241631db80..6bafef259d 100644 --- a/src/sksl/ir/SkSLSymbolTable.h +++ b/src/sksl/ir/SkSLSymbolTable.h @@ -31,11 +31,11 @@ public: : fParent(parent) , fErrorReporter(*errorReporter) {} - const Symbol* operator[](StringFragment name); + const Symbol* operator[](const String& name); - void add(StringFragment name, std::unique_ptr<Symbol> symbol); + void add(const String& name, std::unique_ptr<Symbol> symbol); - void addWithoutOwnership(StringFragment name, const Symbol* symbol); + void addWithoutOwnership(const String& name, const Symbol* symbol); Symbol* takeOwnership(Symbol* s); @@ -48,7 +48,7 @@ private: std::vector<std::unique_ptr<Symbol>> fOwnedPointers; - std::unordered_map<StringFragment, const Symbol*> fSymbols; + std::unordered_map<String, const Symbol*> fSymbols; ErrorReporter& fErrorReporter; }; diff --git a/src/sksl/ir/SkSLTernaryExpression.h b/src/sksl/ir/SkSLTernaryExpression.h index 282a3221db..567af56e8e 100644 --- a/src/sksl/ir/SkSLTernaryExpression.h +++ b/src/sksl/ir/SkSLTernaryExpression.h @@ -17,9 +17,9 @@ namespace SkSL { * A ternary expression (test ? ifTrue : ifFalse). */ struct TernaryExpression : public Expression { - TernaryExpression(int offset, std::unique_ptr<Expression> test, + TernaryExpression(Position position, std::unique_ptr<Expression> test, std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse) - : INHERITED(offset, kTernary_Kind, ifTrue->fType) + : INHERITED(position, 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 b0474216c1..6ea4c5694c 100644 --- a/src/sksl/ir/SkSLType.h +++ b/src/sksl/ir/SkSLType.h @@ -27,9 +27,9 @@ class Context; class Type : public Symbol { public: struct Field { - Field(Modifiers modifiers, StringFragment name, const Type* type) + Field(Modifiers modifiers, String name, const Type* type) : fModifiers(modifiers) - , fName(name) + , fName(std::move(name)) , fType(std::move(type)) {} const String description() const { @@ -37,7 +37,7 @@ public: } Modifiers fModifiers; - StringFragment fName; + String fName; const Type* fType; }; @@ -62,60 +62,40 @@ public: // Create an "other" (special) type with the given name. These types cannot be directly // referenced from user code. Type(String name) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kOther_Kind) - , fNumberKind(kNonnumeric_NumberKind) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fNumberKind(kNonnumeric_NumberKind) {} // Create a generic type which maps to the listed types. Type(String name, std::vector<const Type*> types) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kGeneric_Kind) , fNumberKind(kNonnumeric_NumberKind) - , fCoercibleTypes(std::move(types)) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fCoercibleTypes(std::move(types)) {} // Create a struct type with the given fields. - Type(int offset, String name, std::vector<Field> fields) - : INHERITED(offset, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + Type(Position position, String name, std::vector<Field> fields) + : INHERITED(position, kType_Kind, std::move(name)) , fTypeKind(kStruct_Kind) , fNumberKind(kNonnumeric_NumberKind) - , fFields(std::move(fields)) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fFields(std::move(fields)) {} // Create a scalar type. Type(String name, NumberKind numberKind) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kScalar_Kind) , fNumberKind(numberKind) , fColumns(1) - , fRows(1) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fRows(1) {} // Create a scalar type which can be coerced to the listed types. Type(String name, NumberKind numberKind, std::vector<const Type*> coercibleTypes) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kScalar_Kind) , fNumberKind(numberKind) , fCoercibleTypes(std::move(coercibleTypes)) , fColumns(1) - , fRows(1) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fRows(1) {} // Create a vector type. Type(String name, const Type& componentType, int columns) @@ -123,54 +103,42 @@ public: // Create a vector or array type. Type(String name, Kind kind, const Type& componentType, int columns) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kind) , fNumberKind(kNonnumeric_NumberKind) , fComponentType(&componentType) , fColumns(columns) , fRows(1) - , fDimensions(SpvDim1D) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fDimensions(SpvDim1D) {} // Create a matrix type. Type(String name, const Type& componentType, int columns, int rows) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kMatrix_Kind) , fNumberKind(kNonnumeric_NumberKind) , fComponentType(&componentType) , fColumns(columns) , fRows(rows) - , fDimensions(SpvDim1D) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fDimensions(SpvDim1D) {} // Create a sampler type. Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, bool isSampled) - : INHERITED(-1, kType_Kind, StringFragment()) - , fNameString(std::move(name)) + : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kSampler_Kind) , fNumberKind(kNonnumeric_NumberKind) , fDimensions(dimensions) , fIsDepth(isDepth) , fIsArrayed(isArrayed) , fIsMultisampled(isMultisampled) - , fIsSampled(isSampled) { - fName.fChars = fNameString.c_str(); - fName.fLength = fNameString.size(); - } + , fIsSampled(isSampled) {} const String& name() const { - return fNameString; + return fName; } String description() const override { - return fNameString; + return fName; } bool operator==(const Type& other) const { @@ -315,7 +283,6 @@ public: 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 f7065b7c3f..eae19897c7 100644 --- a/src/sksl/ir/SkSLTypeReference.h +++ b/src/sksl/ir/SkSLTypeReference.h @@ -18,8 +18,8 @@ namespace SkSL { * always eventually replaced by Constructors in valid programs. */ struct TypeReference : public Expression { - TypeReference(const Context& context, int offset, const Type& type) - : INHERITED(offset, kTypeReference_Kind, *context.fInvalid_Type) + TypeReference(const Context& context, Position position, const Type& type) + : INHERITED(position, kTypeReference_Kind, *context.fInvalid_Type) , fValue(type) {} bool hasSideEffects() const override { @@ -27,7 +27,7 @@ struct TypeReference : public Expression { } String description() const override { - return String(fValue.fName); + return fValue.name(); } const Type& fValue; diff --git a/src/sksl/ir/SkSLUnresolvedFunction.h b/src/sksl/ir/SkSLUnresolvedFunction.h index 62035da3a3..b222bc3053 100644 --- a/src/sksl/ir/SkSLUnresolvedFunction.h +++ b/src/sksl/ir/SkSLUnresolvedFunction.h @@ -17,7 +17,7 @@ namespace SkSL { */ struct UnresolvedFunction : public Symbol { UnresolvedFunction(std::vector<const FunctionDeclaration*> funcs) - : INHERITED(-1, kUnresolvedFunction_Kind, funcs[0]->fName) + : INHERITED(Position(), 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 707715f6dc..1eda87e979 100644 --- a/src/sksl/ir/SkSLVarDeclarations.h +++ b/src/sksl/ir/SkSLVarDeclarations.h @@ -24,7 +24,7 @@ struct VarDeclaration : public Statement { VarDeclaration(const Variable* var, std::vector<std::unique_ptr<Expression>> sizes, std::unique_ptr<Expression> value) - : INHERITED(var->fOffset, Statement::kVarDeclaration_Kind) + : INHERITED(var->fPosition, Statement::kVarDeclaration_Kind) , fVar(var) , fSizes(std::move(sizes)) , fValue(std::move(value)) {} @@ -55,9 +55,9 @@ struct VarDeclaration : public Statement { * A variable declaration statement, which may consist of one or more individual variables. */ struct VarDeclarations : public ProgramElement { - VarDeclarations(int offset, const Type* baseType, + VarDeclarations(Position position, const Type* baseType, std::vector<std::unique_ptr<VarDeclaration>> vars) - : INHERITED(offset, kVar_Kind) + : INHERITED(position, 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 0258e66c6e..a6a95a9c08 100644 --- a/src/sksl/ir/SkSLVarDeclarationsStatement.h +++ b/src/sksl/ir/SkSLVarDeclarationsStatement.h @@ -18,7 +18,7 @@ namespace SkSL { */ struct VarDeclarationsStatement : public Statement { VarDeclarationsStatement(std::unique_ptr<VarDeclarations> decl) - : INHERITED(decl->fOffset, kVarDeclarations_Kind) + : INHERITED(decl->fPosition, 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 536d1e6b6d..05bba20a83 100644 --- a/src/sksl/ir/SkSLVariable.h +++ b/src/sksl/ir/SkSLVariable.h @@ -27,9 +27,9 @@ struct Variable : public Symbol { kParameter_Storage }; - Variable(int offset, Modifiers modifiers, StringFragment name, const Type& type, + Variable(Position position, Modifiers modifiers, String name, const Type& type, Storage storage) - : INHERITED(offset, kVariable_Kind, name) + : INHERITED(position, kVariable_Kind, std::move(name)) , fModifiers(modifiers) , fType(type) , fStorage(storage) diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index 54917b0431..ba17437e24 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -32,8 +32,8 @@ struct VariableReference : public Expression { kReadWrite_RefKind }; - VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind) - : INHERITED(offset, kVariableReference_Kind, variable.fType) + VariableReference(Position position, const Variable& variable, RefKind refKind = kRead_RefKind) + : INHERITED(position, kVariableReference_Kind, variable.fType) , fVariable(variable) , fRefKind(refKind) { if (refKind != kRead_RefKind) { @@ -83,17 +83,18 @@ struct VariableReference : public Expression { ASSERT(expr->isConstant()); switch (expr->fKind) { case Expression::kIntLiteral_Kind: - return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, - -1, - ((IntLiteral*) expr)->fValue)); + return std::unique_ptr<Expression>(new IntLiteral( + irGenerator.fContext, + Position(), + ((IntLiteral*) expr)->fValue)); case Expression::kFloatLiteral_Kind: return std::unique_ptr<Expression>(new FloatLiteral( - irGenerator.fContext, - -1, - ((FloatLiteral*) expr)->fValue)); + irGenerator.fContext, + Position(), + ((FloatLiteral*) expr)->fValue)); case Expression::kBoolLiteral_Kind: return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext, - -1, + Position(), ((BoolLiteral*) expr)->fValue)); case Expression::kConstructor_Kind: { const Constructor* c = (const Constructor*) expr; @@ -101,12 +102,12 @@ struct VariableReference : public Expression { for (const auto& arg : c->fArguments) { args.push_back(copy_constant(irGenerator, arg.get())); } - return std::unique_ptr<Expression>(new Constructor(-1, c->fType, + return std::unique_ptr<Expression>(new Constructor(Position(), c->fType, std::move(args))); } case Expression::kSetting_Kind: { const Setting* s = (const Setting*) expr; - return std::unique_ptr<Expression>(new Setting(-1, s->fName, + return std::unique_ptr<Expression>(new Setting(Position(), s->fName, copy_constant(irGenerator, s->fValue.get()))); } diff --git a/src/sksl/ir/SkSLWhileStatement.h b/src/sksl/ir/SkSLWhileStatement.h index aed6494999..6df1619a56 100644 --- a/src/sksl/ir/SkSLWhileStatement.h +++ b/src/sksl/ir/SkSLWhileStatement.h @@ -17,9 +17,9 @@ namespace SkSL { * A 'while' loop. */ struct WhileStatement : public Statement { - WhileStatement(int offset, std::unique_ptr<Expression> test, + WhileStatement(Position position, std::unique_ptr<Expression> test, std::unique_ptr<Statement> statement) - : INHERITED(offset, kWhile_Kind) + : INHERITED(position, kWhile_Kind) , fTest(std::move(test)) , fStatement(std::move(statement)) {} diff --git a/src/sksl/layout.flex b/src/sksl/layout.flex new file mode 100644 index 0000000000..4e6695cfdc --- /dev/null +++ b/src/sksl/layout.flex @@ -0,0 +1,63 @@ +/* + * 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 new file mode 100644 index 0000000000..63369fe93b --- /dev/null +++ b/src/sksl/lex.layout.c @@ -0,0 +1,2239 @@ +/* + * 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 new file mode 100644 index 0000000000..937c93190e --- /dev/null +++ b/src/sksl/lex.layout.cpp @@ -0,0 +1,12 @@ +/* + * 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 new file mode 100644 index 0000000000..345b336253 --- /dev/null +++ b/src/sksl/lex.layout.h @@ -0,0 +1,12 @@ +/* + * 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 new file mode 100644 index 0000000000..6e44f5aea7 --- /dev/null +++ b/src/sksl/lex.sksl.c @@ -0,0 +1,2682 @@ +/* + * 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 deleted file mode 100644 index 66d30881c1..0000000000 --- a/src/sksl/lex/layout.lex +++ /dev/null @@ -1,23 +0,0 @@ -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 new file mode 100644 index 0000000000..275a4e6633 --- /dev/null +++ b/src/sksl/sksl.flex @@ -0,0 +1,232 @@ +/* + * 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 ef1383573e..80188e61c7 100644 --- a/tests/SkSLMemoryLayoutTest.cpp +++ b/tests/SkSLMemoryLayoutTest.cpp @@ -54,30 +54,30 @@ DEF_TEST(SkSLMemoryLayout140Test, r) { // struct 1 std::vector<SkSL::Type::Field> fields1; - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fFloat3_Type.get()); - SkSL::Type s1(-1, SkSL::String("s1"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fFloat3_Type.get()); + SkSL::Type s1(SkSL::Position(), SkSL::String("s1"), fields1); REPORTER_ASSERT(r, 16 == layout.size(s1)); REPORTER_ASSERT(r, 16 == layout.alignment(s1)); - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat_Type.get()); - SkSL::Type s2(-1, SkSL::String("s2"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat_Type.get()); + SkSL::Type s2(SkSL::Position(), SkSL::String("s2"), fields1); REPORTER_ASSERT(r, 16 == layout.size(s2)); REPORTER_ASSERT(r, 16 == layout.alignment(s2)); - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("c"), context.fBool_Type.get()); - SkSL::Type s3(-1, SkSL::String("s3"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("c"), context.fBool_Type.get()); + SkSL::Type s3(SkSL::Position(), 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::StringFragment("a"), context.fInt_Type.get()); - SkSL::Type s4(-1, SkSL::String("s4"), fields2); + fields2.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fInt_Type.get()); + SkSL::Type s4(SkSL::Position(), SkSL::String("s4"), fields2); REPORTER_ASSERT(r, 16 == layout.size(s4)); REPORTER_ASSERT(r, 16 == layout.alignment(s4)); - fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat3_Type.get()); - SkSL::Type s5(-1, SkSL::String("s5"), fields2); + fields2.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat3_Type.get()); + SkSL::Type s5(SkSL::Position(), SkSL::String("s5"), fields2); REPORTER_ASSERT(r, 32 == layout.size(s5)); REPORTER_ASSERT(r, 16 == layout.alignment(s5)); @@ -135,30 +135,30 @@ DEF_TEST(SkSLMemoryLayout430Test, r) { // struct 1 std::vector<SkSL::Type::Field> fields1; - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("a"), context.fFloat3_Type.get()); - SkSL::Type s1(-1, SkSL::String("s1"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fFloat3_Type.get()); + SkSL::Type s1(SkSL::Position(), SkSL::String("s1"), fields1); REPORTER_ASSERT(r, 16 == layout.size(s1)); REPORTER_ASSERT(r, 16 == layout.alignment(s1)); - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat_Type.get()); - SkSL::Type s2(-1, SkSL::String("s2"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat_Type.get()); + SkSL::Type s2(SkSL::Position(), SkSL::String("s2"), fields1); REPORTER_ASSERT(r, 16 == layout.size(s2)); REPORTER_ASSERT(r, 16 == layout.alignment(s2)); - fields1.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("c"), context.fBool_Type.get()); - SkSL::Type s3(-1, SkSL::String("s3"), fields1); + fields1.emplace_back(SkSL::Modifiers(), SkSL::String("c"), context.fBool_Type.get()); + SkSL::Type s3(SkSL::Position(), 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::StringFragment("a"), context.fInt_Type.get()); - SkSL::Type s4(-1, SkSL::String("s4"), fields2); + fields2.emplace_back(SkSL::Modifiers(), SkSL::String("a"), context.fInt_Type.get()); + SkSL::Type s4(SkSL::Position(), SkSL::String("s4"), fields2); REPORTER_ASSERT(r, 4 == layout.size(s4)); REPORTER_ASSERT(r, 4 == layout.alignment(s4)); - fields2.emplace_back(SkSL::Modifiers(), SkSL::StringFragment("b"), context.fFloat3_Type.get()); - SkSL::Type s5(-1, SkSL::String("s5"), fields2); + fields2.emplace_back(SkSL::Modifiers(), SkSL::String("b"), context.fFloat3_Type.get()); + SkSL::Type s5(SkSL::Position(), SkSL::String("s5"), fields2); REPORTER_ASSERT(r, 32 == layout.size(s5)); REPORTER_ASSERT(r, 16 == layout.alignment(s5)); |