diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-09-11 13:50:14 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-11 21:45:20 +0000 |
commit | 5b5f096a038259b8d9084834f877588a0db80250 (patch) | |
tree | 1b78aa591c578a09012b1f8f8533c3fc3d9c1372 /src | |
parent | 9194706e8cf1ed72f07b2ed9207d81120f2135ad (diff) |
Revert "Revert "Switch to the new SkSL lexer.""
This reverts commit 358515491a0d6891e6a709688a30ad087df1beb1.
Bug: skia:
Change-Id: I013fac0ed83774d8ae7c6ee6819045cab37f5e97
Reviewed-on: https://skia-review.googlesource.com/45180
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src')
122 files changed, 4873 insertions, 6467 deletions
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp index 96961cf6e5..aebb7d35e8 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 7cec3cc431..75d73bdbd0 100644 --- a/src/effects/GrCircleBlurFragmentProcessor.cpp +++ b/src/effects/GrCircleBlurFragmentProcessor.cpp @@ -13,11 +13,13 @@ #include "GrResourceProvider.h" +// Computes an unnormalized half kernel (right side). Returns the summation of all the half +// kernel values. static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize, float sigma) { const float invSigma = 1.f / sigma; const float b = -0.5f * invSigma * invSigma; float tot = 0.0f; - + // Compute half kernel values at half pixel steps out from the center. float t = 0.5f; for (int i = 0; i < halfKernelSize; ++i) { float value = expf(t * t * b); @@ -28,8 +30,11 @@ 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) { @@ -39,6 +44,8 @@ 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; @@ -48,7 +55,8 @@ 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); @@ -64,6 +72,10 @@ 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; @@ -83,18 +95,28 @@ 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); @@ -110,34 +132,36 @@ 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; } @@ -146,9 +170,13 @@ 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; @@ -159,8 +187,10 @@ 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; @@ -188,6 +218,7 @@ 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 e9443a8d00..30391450d8 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -72,7 +72,9 @@ 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 8d3fba12bb..6e8fa28efc 100644 --- a/src/gpu/effects/GrSimpleTextureEffect.h +++ b/src/gpu/effects/GrSimpleTextureEffect.h @@ -30,6 +30,7 @@ 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 e8964db0bc..5fd4229457 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, !Token::IsAssignment(b->fOperator)); + this->addExpression(cfg, &b->fLeft, !Compiler::IsAssignment(b->fOperator)); this->addExpression(cfg, &b->fRight, constantPropagate); cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 17bcf0d11f..e84954ee85 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) && - strcmp(var.fType.fName.c_str(), "colorSpaceXform"); + var.fType.fName != "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.name()); + this->write(type.fName); } } 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->fPosition, + fErrors.error(i.fIndex->fOffset, "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->fPosition, + fErrors.error(i.fIndex->fOffset, "index into sk_TextureSamplers must be an integer literal"); return; } @@ -118,16 +118,15 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) { } static const char* default_value(const Type& type) { - const char* name = type.name().c_str(); - if (!strcmp(name, "float")) { + if (type.fName == "float") { return "0.0"; - } else if (!strcmp(name, "float2")) { + } else if (type.fName == "float2") { return "float2(0.0)"; - } else if (!strcmp(name, "float3")) { + } else if (type.fName == "float3") { return "float30.0)"; - } else if (!strcmp(name, "float4")) { + } else if (type.fName == "float4") { return "float4(0.0)"; - } else if (!strcmp(name, "floatt4x4") || !strcmp(name, "colorSpaceXform")) { + } else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") { return "float4x4(1.0)"; } ABORT("unsupported default_value type\n"); @@ -155,7 +154,8 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode fFormatArgs.push_back(cppCode + ".fX"); fFormatArgs.push_back(cppCode + ".fY"); } else { - printf("%s\n", type.name().c_str()); + this->write(type.fName); + this->write("\n"); ABORT("unsupported runtime value type\n"); } } @@ -227,11 +227,11 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) { } fFormatArgs.push_back(code); } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) { - const char* name = ref.fVariable.fName.c_str(); + String name(ref.fVariable.fName); this->writeRuntimeValue(ref.fVariable.fType, - String::printf("_outer.%s()", name).c_str()); + String::printf("_outer.%s()", name.c_str()).c_str()); } else { - this->write(ref.fVariable.fName.c_str()); + this->write(ref.fVariable.fName); } } } @@ -358,14 +358,16 @@ void CPPCodeGenerator::addUniform(const Variable& var) { var.fType == *fContext.fColorSpaceXform_Type) { type = "kMat44f_GrSLType"; } else { - ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str()); + ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(), + String(var.fName).c_str()); } if (var.fModifiers.fLayout.fWhen.size()) { this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str()); } - const char* name = var.fName.c_str(); + String name(var.fName); this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, " - "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name); + "%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision, + name.c_str()); if (var.fModifiers.fLayout.fWhen.size()) { this->write(" }\n"); } @@ -380,7 +382,7 @@ void CPPCodeGenerator::writePrivateVars() { if (is_private(*decl.fVar)) { this->writef("%s %s;\n", HCodeGenerator::FieldType(decl.fVar->fType).c_str(), - decl.fVar->fName.c_str()); + String(decl.fVar->fName).c_str()); } } } @@ -395,7 +397,7 @@ void CPPCodeGenerator::writePrivateVarValues() { VarDeclaration& decl = (VarDeclaration&) *raw; if (is_private(*decl.fVar) && decl.fValue) { this->writef("%s = %s;\n", - decl.fVar->fName.c_str(), + String(decl.fVar->fName).c_str(), decl.fValue->description().c_str()); } } @@ -414,12 +416,12 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) { this->addUniform(*u); if (u->fType == *fContext.fColorSpaceXform_Type) { if (fNeedColorSpaceHelper) { - fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported"); + fErrors.error(u->fOffset, "only a single ColorSpaceXform is supported"); } fNeedColorSpaceHelper = true; this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, " "_outer.%s().get());\n", - u->fName.c_str()); + String(u->fName).c_str()); } } this->writeSection(EMIT_CODE_SECTION); @@ -453,7 +455,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { wroteProcessor = true; this->writef(" {\n"); } - const char* name = u->fName.c_str(); + String nameString(u->fName); + const char* name = nameString.c_str(); if (u->fType == *fContext.fFloat4_Type) { this->writef(" const SkRect %sValue = _outer.%s();\n" " %s.set4fv(%sVar, 1, (float*) &%sValue);\n", @@ -485,13 +488,13 @@ 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); @@ -512,14 +515,14 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { void CPPCodeGenerator::writeClone() { if (!this->writeSection(CLONE_SECTION)) { if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) { - fErrors.error(Position(1, 1), "fragment processors with custom @fields must also have " - "a custom @clone"); + fErrors.error(0, "fragment processors with custom @fields must also have a custom" + "@clone"); } this->writef("%s::%s(const %s& src)\n" ": INHERITED(src.optimizationFlags())", fFullName.c_str(), fFullName.c_str(), fFullName.c_str()); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - String fieldName = HCodeGenerator::FieldName(param->fName.c_str()); + String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str()); this->writef("\n, %s(%s)", fieldName.c_str(), ("src." + fieldName).c_str()); @@ -535,7 +538,7 @@ void CPPCodeGenerator::writeClone() { for (const auto& param : fSectionAndParameterHelper.getParameters()) { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", - HCodeGenerator::FieldName(param->fName.c_str()).c_str()); + HCodeGenerator::FieldName(String(param->fName).c_str()).c_str()); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -572,7 +575,8 @@ void CPPCodeGenerator::writeGetKey() { "GrProcessorKeyBuilder* b) const {\n", fFullName.c_str()); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - const char* name = param->fName.c_str(); + String nameString(param->fName); + const char* name = nameString.c_str(); if (param->fType == *fContext.fColorSpaceXform_Type) { this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n", HCodeGenerator::FieldName(name).c_str()); @@ -580,7 +584,7 @@ void CPPCodeGenerator::writeGetKey() { } if (param->fModifiers.fLayout.fKey != Layout::kNo_Key && (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) { - fErrors.error(param->fPosition, + fErrors.error(param->fOffset, "layout(key) may not be specified on uniforms"); } switch (param->fModifiers.fLayout.fKey) { @@ -608,7 +612,7 @@ void CPPCodeGenerator::writeGetKey() { break; case Layout::kIdentity_Key: if (param->fType.kind() != Type::kMatrix_Kind) { - fErrors.error(param->fPosition, + fErrors.error(param->fOffset, "layout(key=identity) requires matrix type"); } this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n", @@ -656,15 +660,15 @@ 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(name).c_str()); + this->writef(" UniformHandle %sVar;\n", + HCodeGenerator::FieldName(String(u->fName).c_str()).c_str()); } } for (const auto& param : fSectionAndParameterHelper.getParameters()) { - const char* name = param->fName.c_str(); if (needs_uniform_var(*param)) { - this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str()); + this->writef(" UniformHandle %sVar;\n", + HCodeGenerator::FieldName(String(param->fName).c_str()).c_str()); } } if (fNeedColorSpaceHelper) { @@ -681,7 +685,8 @@ bool CPPCodeGenerator::generateCode() { " (void) that;\n", fullName, fullName, fullName); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - const char* name = param->fName.c_str(); + String nameString(param->fName); + const char* name = nameString.c_str(); this->writef(" if (%s != that.%s) return false;\n", HCodeGenerator::FieldName(name).c_str(), HCodeGenerator::FieldName(name).c_str()); diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 4ea956ce0f..638e4d64bf 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -51,7 +51,6 @@ static const char* SKSL_FP_INCLUDE = #include "sksl_fp.include" ; - namespace SkSL { Compiler::Compiler(Flags flags) @@ -187,20 +186,23 @@ Compiler::Compiler(Flags flags) ADD_TYPE(GSamplerCubeArrayShadow); ADD_TYPE(ColorSpaceXform); - String skCapsName("sk_Caps"); - Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName, + StringFragment skCapsName("sk_Caps"); + Variable* skCaps = new Variable(-1, Modifiers(), skCapsName, *fContext.fSkCaps_Type, Variable::kGlobal_Storage); fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); - String skArgsName("sk_Args"); - Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName, + StringFragment skArgsName("sk_Args"); + Variable* skArgs = new Variable(-1, Modifiers(), skArgsName, *fContext.fSkArgs_Type, Variable::kGlobal_Storage); fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); Modifiers::Flag ignored1; std::vector<std::unique_ptr<ProgramElement>> ignored2; - fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); + fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); + if (fErrorCount) { + printf("Unexpected errors: %s\n", fErrorText.c_str()); + } ASSERT(!fErrorCount); } @@ -260,7 +262,7 @@ 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 (Token::IsAssignment(b->fOperator)) { + } else if (Compiler::IsAssignment(b->fOperator)) { this->addDefinition( b->fLeft.get(), (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, @@ -401,7 +403,7 @@ 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 (!Token::IsAssignment(b.fOperator)) { + if (!Compiler::IsAssignment(b.fOperator)) { return false; } return is_dead(*b.fLeft); @@ -540,7 +542,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(Position(), type, std::move(args))); + auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args))); return result; } @@ -642,7 +644,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->fPosition, + this->error(expr->fOffset, "'" + var.fName + "' has not been assigned"); } break; @@ -877,7 +879,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(Position(), std::move(statements), s->fSymbols)); + return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols)); } void Compiler::simplifyStatement(DefinitionMap& definitions, @@ -964,7 +966,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions, break; } else { if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fPosition, + this->error(s.fOffset, "static switch contains non-static conditional break"); s.fIsStatic = false; } @@ -980,7 +982,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions, (*iter)->setStatement(std::move(newBlock)); } else { if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fPosition, + this->error(s.fOffset, "static switch contains non-static conditional break"); s.fIsStatic = false; } @@ -1022,16 +1024,16 @@ 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()) { - Position p; + int offset; switch (cfg.fBlocks[i].fNodes[0].fKind) { case BasicBlock::Node::kStatement_Kind: - p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition; + offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset; break; case BasicBlock::Node::kExpression_Kind: - p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition; + offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset; break; } - this->error(p, String("unreachable")); + this->error(offset, String("unreachable")); } } if (fErrorCount) { @@ -1081,14 +1083,14 @@ void Compiler::scanCFG(FunctionDefinition& f) { case Statement::kIf_Kind: if (((const IfStatement&) s).fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fPosition, "static if has non-static test"); + this->error(s.fOffset, "static if has non-static test"); } ++iter; break; case Statement::kSwitch_Kind: if (((const SwitchStatement&) s).fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { - this->error(s.fPosition, "static switch has non-static test"); + this->error(s.fOffset, "static switch has non-static test"); } ++iter; break; @@ -1121,7 +1123,7 @@ 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.fPosition, String("function can exit without returning a value")); + this->error(f.fOffset, String("function can exit without returning a value")); } } } @@ -1135,21 +1137,28 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex Modifiers::Flag ignored; switch (kind) { case Program::kVertex_Kind: - fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements); + fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes, + &ignored, &elements); break; case Program::kFragment_Kind: - fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements); + fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes, + &ignored, &elements); break; case Program::kGeometry_Kind: - fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements); + fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes, + &ignored, &elements); break; case Program::kFragmentProcessor_Kind: - fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements); + fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, + &ignored, &elements); break; } fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); Modifiers::Flag defaultPrecision; - fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements); + std::unique_ptr<String> textPtr(new String(std::move(text))); + fSource = textPtr.get(); + fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &defaultPrecision, + &elements); if (!fErrorCount) { for (auto& element : elements) { if (element->fKind == ProgramElement::kFunction_Kind) { @@ -1157,11 +1166,13 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex } } } - auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext, + auto result = std::unique_ptr<Program>(new Program(kind, std::move(textPtr), settings, + defaultPrecision, &fContext, std::move(elements), fIRGenerator->fSymbolTable, fIRGenerator->fInputs)); fIRGenerator->finish(); + fSource = nullptr; this->writeErrorCount(); if (fErrorCount) { return nullptr; @@ -1172,8 +1183,10 @@ 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(); @@ -1188,8 +1201,10 @@ 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; @@ -1205,8 +1220,10 @@ 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; } @@ -1221,22 +1238,111 @@ 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; } -void Compiler::error(Position position, String msg) { +const char* Compiler::OperatorName(Token::Kind kind) { + switch (kind) { + case Token::PLUS: return "+"; + case Token::MINUS: return "-"; + case Token::STAR: return "*"; + case Token::SLASH: return "/"; + case Token::PERCENT: return "%"; + case Token::SHL: return "<<"; + case Token::SHR: return ">>"; + case Token::LOGICALNOT: return "!"; + case Token::LOGICALAND: return "&&"; + case Token::LOGICALOR: return "||"; + case Token::LOGICALXOR: return "^^"; + case Token::BITWISENOT: return "~"; + case Token::BITWISEAND: return "&"; + case Token::BITWISEOR: return "|"; + case Token::BITWISEXOR: return "^"; + case Token::EQ: return "="; + case Token::EQEQ: return "=="; + case Token::NEQ: return "!="; + case Token::LT: return "<"; + case Token::GT: return ">"; + case Token::LTEQ: return "<="; + case Token::GTEQ: return ">="; + case Token::PLUSEQ: return "+="; + case Token::MINUSEQ: return "-="; + case Token::STAREQ: return "*="; + case Token::SLASHEQ: return "/="; + case Token::PERCENTEQ: return "%="; + case Token::SHLEQ: return "<<="; + case Token::SHREQ: return ">>="; + case Token::LOGICALANDEQ: return "&&="; + case Token::LOGICALOREQ: return "||="; + case Token::LOGICALXOREQ: return "^^="; + case Token::BITWISEANDEQ: return "&="; + case Token::BITWISEOREQ: return "|="; + case Token::BITWISEXOREQ: return "^="; + case Token::PLUSPLUS: return "++"; + case Token::MINUSMINUS: return "--"; + case Token::COMMA: return ","; + default: + ABORT("unsupported operator: %d\n", kind); + } +} + + +bool Compiler::IsAssignment(Token::Kind op) { + switch (op) { + case Token::EQ: // fall through + case Token::PLUSEQ: // fall through + case Token::MINUSEQ: // fall through + case Token::STAREQ: // fall through + case Token::SLASHEQ: // fall through + case Token::PERCENTEQ: // fall through + case Token::SHLEQ: // fall through + case Token::SHREQ: // fall through + case Token::BITWISEOREQ: // fall through + case Token::BITWISEXOREQ: // fall through + case Token::BITWISEANDEQ: // fall through + case Token::LOGICALOREQ: // fall through + case Token::LOGICALXOREQ: // fall through + case Token::LOGICALANDEQ: + return true; + default: + return false; + } +} + +Position Compiler::position(int offset) { + ASSERT(fSource); + int line = 1; + int column = 1; + for (int i = 0; i < offset; i++) { + if ((*fSource)[i] == '\n') { + ++line; + column = 1; + } + else { + ++column; + } + } + return Position(line, column); +} + +void Compiler::error(int offset, String msg) { fErrorCount++; - fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n"; + Position pos = this->position(offset); + fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n"; } String Compiler::errorText() { diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 38f63e542c..894ac41092 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -16,7 +16,6 @@ #include "SkSLCFGGenerator.h" #include "SkSLContext.h" #include "SkSLErrorReporter.h" -#include "SkSLIRGenerator.h" #define SK_FRAGCOLOR_BUILTIN 10001 #define SK_IN_BUILTIN 10002 @@ -70,7 +69,7 @@ public: bool toH(const Program& program, String name, OutputStream& out); - void error(Position position, String msg) override; + void error(int offset, String msg) override; String errorText(); @@ -80,6 +79,10 @@ 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); @@ -114,11 +117,14 @@ 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 b132cec33d..e421695f11 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(String("<INVALID>"))) - , fVoid_Type(new Type(String("void"))) - , fDouble_Type(new Type(String("double"), Type::kFloat_NumberKind)) - , fDouble2_Type(new Type(String("double2"), *fDouble_Type, 2)) - , fDouble3_Type(new Type(String("double3"), *fDouble_Type, 3)) - , fDouble4_Type(new Type(String("double4"), *fDouble_Type, 4)) - , fFloat_Type(new Type(String("float"), Type::kFloat_NumberKind)) - , fFloat2_Type(new Type(String("float2"), *fFloat_Type, 2)) - , fFloat3_Type(new Type(String("float3"), *fFloat_Type, 3)) - , fFloat4_Type(new Type(String("float4"), *fFloat_Type, 4)) - , fHalf_Type(new Type(String("half"), Type::kFloat_NumberKind)) - , fHalf2_Type(new Type(String("half2"), *fHalf_Type, 2)) - , fHalf3_Type(new Type(String("half3"), *fHalf_Type, 3)) - , fHalf4_Type(new Type(String("half4"), *fHalf_Type, 4)) - , fUInt_Type(new Type(String("uint"), Type::kUnsigned_NumberKind)) - , fUInt2_Type(new Type(String("uint2"), *fUInt_Type, 2)) - , fUInt3_Type(new Type(String("uint3"), *fUInt_Type, 3)) - , fUInt4_Type(new Type(String("uint4"), *fUInt_Type, 4)) - , fInt_Type(new Type(String("int"), Type::kSigned_NumberKind)) - , fInt2_Type(new Type(String("int2"), *fInt_Type, 2)) - , fInt3_Type(new Type(String("int3"), *fInt_Type, 3)) - , fInt4_Type(new Type(String("int4"), *fInt_Type, 4)) - , fUShort_Type(new Type(String("ushort"), Type::kUnsigned_NumberKind)) - , fUShort2_Type(new Type(String("ushort2"), *fUShort_Type, 2)) - , fUShort3_Type(new Type(String("ushort3"), *fUShort_Type, 3)) - , fUShort4_Type(new Type(String("ushort4"), *fUShort_Type, 4)) - , fShort_Type(new Type(String("short"), Type::kSigned_NumberKind)) - , fShort2_Type(new Type(String("short2"), *fShort_Type, 2)) - , fShort3_Type(new Type(String("short3"), *fShort_Type, 3)) - , fShort4_Type(new Type(String("short4"), *fShort_Type, 4)) - , fBool_Type(new Type(String("bool"), Type::kNonnumeric_NumberKind)) - , fBool2_Type(new Type(String("bool2"), *fBool_Type, 2)) - , fBool3_Type(new Type(String("bool3"), *fBool_Type, 3)) - , fBool4_Type(new Type(String("bool4"), *fBool_Type, 4)) - , fFloat2x2_Type(new Type(String("float2x2"), *fFloat_Type, 2, 2)) - , fFloat2x3_Type(new Type(String("float2x3"), *fFloat_Type, 2, 3)) - , fFloat2x4_Type(new Type(String("float2x4"), *fFloat_Type, 2, 4)) - , fFloat3x2_Type(new Type(String("float3x2"), *fFloat_Type, 3, 2)) - , fFloat3x3_Type(new Type(String("float3x3"), *fFloat_Type, 3, 3)) - , fFloat3x4_Type(new Type(String("float3x4"), *fFloat_Type, 3, 4)) - , fFloat4x2_Type(new Type(String("float4x2"), *fFloat_Type, 4, 2)) - , fFloat4x3_Type(new Type(String("float4x3"), *fFloat_Type, 4, 3)) - , fFloat4x4_Type(new Type(String("float4x4"), *fFloat_Type, 4, 4)) - , fHalf2x2_Type(new Type(String("half2x2"), *fHalf_Type, 2, 2)) - , fHalf2x3_Type(new Type(String("half2x3"), *fHalf_Type, 2, 3)) - , fHalf2x4_Type(new Type(String("half2x4"), *fHalf_Type, 2, 4)) - , fHalf3x2_Type(new Type(String("half3x2"), *fHalf_Type, 3, 2)) - , fHalf3x3_Type(new Type(String("half3x3"), *fHalf_Type, 3, 3)) - , fHalf3x4_Type(new Type(String("half3x4"), *fHalf_Type, 3, 4)) - , fHalf4x2_Type(new Type(String("half4x2"), *fHalf_Type, 4, 2)) - , fHalf4x3_Type(new Type(String("half4x3"), *fHalf_Type, 4, 3)) - , fHalf4x4_Type(new Type(String("half4x4"), *fHalf_Type, 4, 4)) - , fDouble2x2_Type(new Type(String("double2x2"), *fDouble_Type, 2, 2)) - , fDouble2x3_Type(new Type(String("double2x3"), *fDouble_Type, 2, 3)) - , fDouble2x4_Type(new Type(String("double2x4"), *fDouble_Type, 2, 4)) - , fDouble3x2_Type(new Type(String("double3x2"), *fDouble_Type, 3, 2)) - , fDouble3x3_Type(new Type(String("double3x3"), *fDouble_Type, 3, 3)) - , fDouble3x4_Type(new Type(String("double3x4"), *fDouble_Type, 3, 4)) - , fDouble4x2_Type(new Type(String("double4x2"), *fDouble_Type, 4, 2)) - , fDouble4x3_Type(new Type(String("double4x3"), *fDouble_Type, 4, 3)) - , fDouble4x4_Type(new Type(String("double4x4"), *fDouble_Type, 4, 4)) - , fSampler1D_Type(new Type(String("sampler1D"), SpvDim1D, false, false, false, true)) - , fSampler2D_Type(new Type(String("sampler2D"), SpvDim2D, false, false, false, true)) - , fSampler3D_Type(new Type(String("sampler3D"), SpvDim3D, false, false, false, true)) - , fSamplerExternalOES_Type(new Type(String("samplerExternalOES"), SpvDim2D, false, false, + : fInvalid_Type(new Type("<INVALID>")) + , fVoid_Type(new Type("void")) + , fDouble_Type(new Type("double", Type::kFloat_NumberKind)) + , fDouble2_Type(new Type("double2", *fDouble_Type, 2)) + , fDouble3_Type(new Type("double3", *fDouble_Type, 3)) + , fDouble4_Type(new Type("double4", *fDouble_Type, 4)) + , fFloat_Type(new Type("float", Type::kFloat_NumberKind)) + , fFloat2_Type(new Type("float2", *fFloat_Type, 2)) + , fFloat3_Type(new Type("float3", *fFloat_Type, 3)) + , fFloat4_Type(new Type("float4", *fFloat_Type, 4)) + , fHalf_Type(new Type("half", Type::kFloat_NumberKind)) + , fHalf2_Type(new Type("half2", *fHalf_Type, 2)) + , fHalf3_Type(new Type("half3", *fHalf_Type, 3)) + , fHalf4_Type(new Type("half4", *fHalf_Type, 4)) + , fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind)) + , fUInt2_Type(new Type("uint2", *fUInt_Type, 2)) + , fUInt3_Type(new Type("uint3", *fUInt_Type, 3)) + , fUInt4_Type(new Type("uint4", *fUInt_Type, 4)) + , fInt_Type(new Type("int", Type::kSigned_NumberKind)) + , fInt2_Type(new Type("int2", *fInt_Type, 2)) + , fInt3_Type(new Type("int3", *fInt_Type, 3)) + , fInt4_Type(new Type("int4", *fInt_Type, 4)) + , fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind)) + , fUShort2_Type(new Type("ushort2", *fUShort_Type, 2)) + , fUShort3_Type(new Type("ushort3", *fUShort_Type, 3)) + , fUShort4_Type(new Type("ushort4", *fUShort_Type, 4)) + , fShort_Type(new Type("short", Type::kSigned_NumberKind)) + , fShort2_Type(new Type("short2", *fShort_Type, 2)) + , fShort3_Type(new Type("short3", *fShort_Type, 3)) + , fShort4_Type(new Type("short4", *fShort_Type, 4)) + , fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind)) + , fBool2_Type(new Type("bool2", *fBool_Type, 2)) + , fBool3_Type(new Type("bool3", *fBool_Type, 3)) + , fBool4_Type(new Type("bool4", *fBool_Type, 4)) + , fFloat2x2_Type(new Type("float2x2", *fFloat_Type, 2, 2)) + , fFloat2x3_Type(new Type("float2x3", *fFloat_Type, 2, 3)) + , fFloat2x4_Type(new Type("float2x4", *fFloat_Type, 2, 4)) + , fFloat3x2_Type(new Type("float3x2", *fFloat_Type, 3, 2)) + , fFloat3x3_Type(new Type("float3x3", *fFloat_Type, 3, 3)) + , fFloat3x4_Type(new Type("float3x4", *fFloat_Type, 3, 4)) + , fFloat4x2_Type(new Type("float4x2", *fFloat_Type, 4, 2)) + , fFloat4x3_Type(new Type("float4x3", *fFloat_Type, 4, 3)) + , fFloat4x4_Type(new Type("float4x4", *fFloat_Type, 4, 4)) + , fHalf2x2_Type(new Type("half2x2", *fHalf_Type, 2, 2)) + , fHalf2x3_Type(new Type("half2x3", *fHalf_Type, 2, 3)) + , fHalf2x4_Type(new Type("half2x4", *fHalf_Type, 2, 4)) + , fHalf3x2_Type(new Type("half3x2", *fHalf_Type, 3, 2)) + , fHalf3x3_Type(new Type("half3x3", *fHalf_Type, 3, 3)) + , fHalf3x4_Type(new Type("half3x4", *fHalf_Type, 3, 4)) + , fHalf4x2_Type(new Type("half4x2", *fHalf_Type, 4, 2)) + , fHalf4x3_Type(new Type("half4x3", *fHalf_Type, 4, 3)) + , fHalf4x4_Type(new Type("half4x4", *fHalf_Type, 4, 4)) + , fDouble2x2_Type(new Type("double2x2", *fDouble_Type, 2, 2)) + , fDouble2x3_Type(new Type("double2x3", *fDouble_Type, 2, 3)) + , fDouble2x4_Type(new Type("double2x4", *fDouble_Type, 2, 4)) + , fDouble3x2_Type(new Type("double3x2", *fDouble_Type, 3, 2)) + , fDouble3x3_Type(new Type("double3x3", *fDouble_Type, 3, 3)) + , fDouble3x4_Type(new Type("double3x4", *fDouble_Type, 3, 4)) + , fDouble4x2_Type(new Type("double4x2", *fDouble_Type, 4, 2)) + , fDouble4x3_Type(new Type("double4x3", *fDouble_Type, 4, 3)) + , fDouble4x4_Type(new Type("double4x4", *fDouble_Type, 4, 4)) + , fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true)) + , fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true)) + , fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true)) + , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false, false, true)) - , fSamplerCube_Type(new Type(String("samplerCube"), SpvDimCube, false, false, false, true)) - , fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false, true)) - , fSampler1DArray_Type(new Type(String("sampler1DArray"))) - , fSampler2DArray_Type(new Type(String("sampler2DArray"))) - , fSamplerCubeArray_Type(new Type(String("samplerCubeArray"))) - , fSamplerBuffer_Type(new Type(String("samplerBuffer"), SpvDimBuffer, false, false, false, + , fSamplerCube_Type(new Type("samplerCube", SpvDimCube, false, false, false, true)) + , fSampler2DRect_Type(new Type("sampler2DRect", SpvDimRect, false, false, false, true)) + , fSampler1DArray_Type(new Type("sampler1DArray")) + , fSampler2DArray_Type(new Type("sampler2DArray")) + , fSamplerCubeArray_Type(new Type("samplerCubeArray")) + , fSamplerBuffer_Type(new Type("samplerBuffer", SpvDimBuffer, false, false, false, true)) - , fSampler2DMS_Type(new Type(String("sampler2DMS"))) - , fSampler2DMSArray_Type(new Type(String("sampler2DMSArray"))) - , fSampler1DShadow_Type(new Type(String("sampler1DShadow"))) - , fSampler2DShadow_Type(new Type(String("sampler2DShadow"))) - , fSamplerCubeShadow_Type(new Type(String("samplerCubeShadow"))) - , fSampler2DRectShadow_Type(new Type(String("sampler2DRectShadow"))) - , fSampler1DArrayShadow_Type(new Type(String("sampler1DArrayShadow"))) - , fSampler2DArrayShadow_Type(new Type(String("sampler2DArrayShadow"))) - , fSamplerCubeArrayShadow_Type(new Type(String("samplerCubeArrayShadow"))) + , fSampler2DMS_Type(new Type("sampler2DMS")) + , fSampler2DMSArray_Type(new Type("sampler2DMSArray")) + , fSampler1DShadow_Type(new Type("sampler1DShadow")) + , fSampler2DShadow_Type(new Type("sampler2DShadow")) + , fSamplerCubeShadow_Type(new Type("samplerCubeShadow")) + , fSampler2DRectShadow_Type(new Type("sampler2DRectShadow")) + , fSampler1DArrayShadow_Type(new Type("sampler1DArrayShadow")) + , fSampler2DArrayShadow_Type(new Type("sampler2DArrayShadow")) + , fSamplerCubeArrayShadow_Type(new Type("samplerCubeArrayShadow")) // Related to below FIXME, gsampler*s don't currently expand to cover integer case. - , fISampler2D_Type(new Type(String("isampler2D"), SpvDim2D, false, false, false, true)) + , fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true)) // FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D. - , fImage2D_Type(new Type(String("image2D"), SpvDim2D, false, false, false, true)) - , fIImage2D_Type(new Type(String("iimage2D"), SpvDim2D, false, false, false, true)) + , fImage2D_Type(new Type("image2D", SpvDim2D, false, false, false, true)) + , fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true)) // FIXME express these as "gsubpassInput" that expand to subpassInput, isubpassInput, // and usubpassInput. - , fSubpassInput_Type(new Type(String("subpassInput"), SpvDimSubpassData, false, false, - false, false)) - , fSubpassInputMS_Type(new Type(String("subpassInputMS"), SpvDimSubpassData, false, false, - true, false)) + , fSubpassInput_Type(new Type("subpassInput", SpvDimSubpassData, false, false, + false, false)) + , fSubpassInputMS_Type(new Type("subpassInputMS", SpvDimSubpassData, false, false, + true, false)) // FIXME figure out what we're supposed to do with the gsampler et al. types) - , fGSampler1D_Type(new Type(String("$gsampler1D"), static_type(*fSampler1D_Type))) - , fGSampler2D_Type(new Type(String("$gsampler2D"), static_type(*fSampler2D_Type))) - , fGSampler3D_Type(new Type(String("$gsampler3D"), static_type(*fSampler3D_Type))) - , fGSamplerCube_Type(new Type(String("$gsamplerCube"), static_type(*fSamplerCube_Type))) - , fGSampler2DRect_Type(new Type(String("$gsampler2DRect"), static_type(*fSampler2DRect_Type))) - , fGSampler1DArray_Type(new Type(String("$gsampler1DArray"), + , fGSampler1D_Type(new Type("$gsampler1D", static_type(*fSampler1D_Type))) + , fGSampler2D_Type(new Type("$gsampler2D", static_type(*fSampler2D_Type))) + , fGSampler3D_Type(new Type("$gsampler3D", static_type(*fSampler3D_Type))) + , fGSamplerCube_Type(new Type("$gsamplerCube", static_type(*fSamplerCube_Type))) + , fGSampler2DRect_Type(new Type("$gsampler2DRect", static_type(*fSampler2DRect_Type))) + , fGSampler1DArray_Type(new Type("$gsampler1DArray", static_type(*fSampler1DArray_Type))) - , fGSampler2DArray_Type(new Type(String("$gsampler2DArray"), + , fGSampler2DArray_Type(new Type("$gsampler2DArray", static_type(*fSampler2DArray_Type))) - , fGSamplerCubeArray_Type(new Type(String("$gsamplerCubeArray"), + , fGSamplerCubeArray_Type(new Type("$gsamplerCubeArray", static_type(*fSamplerCubeArray_Type))) - , fGSamplerBuffer_Type(new Type(String("$gsamplerBuffer"), static_type(*fSamplerBuffer_Type))) - , fGSampler2DMS_Type(new Type(String("$gsampler2DMS"), static_type(*fSampler2DMS_Type))) - , fGSampler2DMSArray_Type(new Type(String("$gsampler2DMSArray"), + , fGSamplerBuffer_Type(new Type("$gsamplerBuffer", static_type(*fSamplerBuffer_Type))) + , fGSampler2DMS_Type(new Type("$gsampler2DMS", static_type(*fSampler2DMS_Type))) + , fGSampler2DMSArray_Type(new Type("$gsampler2DMSArray", static_type(*fSampler2DMSArray_Type))) - , fGSampler2DArrayShadow_Type(new Type(String("$gsampler2DArrayShadow"), + , fGSampler2DArrayShadow_Type(new Type("$gsampler2DArrayShadow", static_type(*fSampler2DArrayShadow_Type))) - , fGSamplerCubeArrayShadow_Type(new Type(String("$gsamplerCubeArrayShadow"), + , fGSamplerCubeArrayShadow_Type(new Type("$gsamplerCubeArrayShadow", static_type(*fSamplerCubeArrayShadow_Type))) - , fGenType_Type(new Type(String("$genType"), { fFloat_Type.get(), fFloat2_Type.get(), - fFloat3_Type.get(), fFloat4_Type.get() })) - , fGenHType_Type(new Type(String("$genHType"), { fHalf_Type.get(), fHalf2_Type.get(), - fHalf3_Type.get(), fHalf4_Type.get() })) - , fGenDType_Type(new Type(String("$genDType"), { fDouble_Type.get(), fDouble2_Type.get(), - fDouble3_Type.get(), fDouble4_Type.get() })) - , fGenIType_Type(new Type(String("$genIType"), { fInt_Type.get(), fInt2_Type.get(), - fInt3_Type.get(), fInt4_Type.get() })) - , fGenUType_Type(new Type(String("$genUType"), { fUInt_Type.get(), fUInt2_Type.get(), - fUInt3_Type.get(), fUInt4_Type.get() })) - , fGenBType_Type(new Type(String("$genBType"), { fBool_Type.get(), fBool2_Type.get(), - fBool3_Type.get(), fBool4_Type.get() })) - , fMat_Type(new Type(String("$mat"), { fFloat2x2_Type.get(), fFloat2x3_Type.get(), - fFloat2x4_Type.get(), fFloat3x2_Type.get(), - fFloat3x3_Type.get(), fFloat3x4_Type.get(), - fFloat4x2_Type.get(), fFloat4x3_Type.get(), - fFloat4x4_Type.get(), fHalf2x2_Type.get(), - fHalf2x3_Type.get(), fHalf2x4_Type.get(), - fHalf3x2_Type.get(), fHalf3x3_Type.get(), - fHalf3x4_Type.get(), fHalf4x2_Type.get(), - fHalf4x3_Type.get(), fHalf4x4_Type.get(), - fDouble2x2_Type.get(), fDouble2x3_Type.get(), - fDouble2x4_Type.get(), fDouble3x2_Type.get(), - fDouble3x3_Type.get(), fDouble3x4_Type.get(), - fDouble4x2_Type.get(), fDouble4x3_Type.get(), - fDouble4x4_Type.get() })) - , fVec_Type(new Type(String("$vec"), { fInvalid_Type.get(), fFloat2_Type.get(), + , fGenType_Type(new Type("$genType", { fFloat_Type.get(), fFloat2_Type.get(), fFloat3_Type.get(), fFloat4_Type.get() })) - , fGVec_Type(new Type(String("$gvec"))) - , fGVec2_Type(new Type(String("$gfloat2"))) - , fGVec3_Type(new Type(String("$gfloat3"))) - , fGVec4_Type(new Type(String("$gfloat4"), static_type(*fFloat4_Type))) - , fHVec_Type(new Type(String("$hvec"), { fInvalid_Type.get(), fHalf2_Type.get(), + , fGenHType_Type(new Type("$genHType", { fHalf_Type.get(), fHalf2_Type.get(), fHalf3_Type.get(), fHalf4_Type.get() })) - , fDVec_Type(new Type(String("$dvec"), { fInvalid_Type.get(), fDouble2_Type.get(), + , fGenDType_Type(new Type("$genDType", { fDouble_Type.get(), fDouble2_Type.get(), fDouble3_Type.get(), fDouble4_Type.get() })) - , fIVec_Type(new Type(String("$ivec"), { fInvalid_Type.get(), fInt2_Type.get(), + , fGenIType_Type(new Type("$genIType", { fInt_Type.get(), fInt2_Type.get(), fInt3_Type.get(), fInt4_Type.get() })) - , fUVec_Type(new Type(String("$uvec"), { fInvalid_Type.get(), fUInt2_Type.get(), + , fGenUType_Type(new Type("$genUType", { fUInt_Type.get(), fUInt2_Type.get(), fUInt3_Type.get(), fUInt4_Type.get() })) - , fSVec_Type(new Type(String("$svec"), { fInvalid_Type.get(), fShort2_Type.get(), - fShort3_Type.get(), fShort4_Type.get() })) - , fUSVec_Type(new Type(String("$usvec"), { fInvalid_Type.get(), fUShort2_Type.get(), - fUShort3_Type.get(), fUShort4_Type.get() })) - , fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBool2_Type.get(), + , fGenBType_Type(new Type("$genBType", { fBool_Type.get(), fBool2_Type.get(), fBool3_Type.get(), fBool4_Type.get() })) - , fSkCaps_Type(new Type(String("$sk_Caps"))) - , fSkArgs_Type(new Type(String("$sk_Args"))) - , fColorSpaceXform_Type(new Type(String("colorSpaceXform"), *fFloat_Type, 4, 4)) + , fMat_Type(new Type("$mat", { fFloat2x2_Type.get(), fFloat2x3_Type.get(), + fFloat2x4_Type.get(), fFloat3x2_Type.get(), + fFloat3x3_Type.get(), fFloat3x4_Type.get(), + fFloat4x2_Type.get(), fFloat4x3_Type.get(), + fFloat4x4_Type.get(), fHalf2x2_Type.get(), + fHalf2x3_Type.get(), fHalf2x4_Type.get(), + fHalf3x2_Type.get(), fHalf3x3_Type.get(), + fHalf3x4_Type.get(), fHalf4x2_Type.get(), + fHalf4x3_Type.get(), fHalf4x4_Type.get(), + fDouble2x2_Type.get(), fDouble2x3_Type.get(), + fDouble2x4_Type.get(), fDouble3x2_Type.get(), + fDouble3x3_Type.get(), fDouble3x4_Type.get(), + fDouble4x2_Type.get(), fDouble4x3_Type.get(), + fDouble4x4_Type.get() })) + , fVec_Type(new Type("$vec", { fInvalid_Type.get(), fFloat2_Type.get(), + fFloat3_Type.get(), fFloat4_Type.get() })) + , fGVec_Type(new Type("$gvec")) + , fGVec2_Type(new Type("$gfloat2")) + , fGVec3_Type(new Type("$gfloat3")) + , fGVec4_Type(new Type("$gfloat4", static_type(*fFloat4_Type))) + , fHVec_Type(new Type("$hvec", { fInvalid_Type.get(), fHalf2_Type.get(), + fHalf3_Type.get(), fHalf4_Type.get() })) + , fDVec_Type(new Type("$dvec", { fInvalid_Type.get(), fDouble2_Type.get(), + fDouble3_Type.get(), fDouble4_Type.get() })) + , fIVec_Type(new Type("$ivec", { fInvalid_Type.get(), fInt2_Type.get(), + fInt3_Type.get(), fInt4_Type.get() })) + , fUVec_Type(new Type("$uvec", { fInvalid_Type.get(), fUInt2_Type.get(), + fUInt3_Type.get(), fUInt4_Type.get() })) + , fSVec_Type(new Type("$svec", { fInvalid_Type.get(), fShort2_Type.get(), + fShort3_Type.get(), fShort4_Type.get() })) + , fUSVec_Type(new Type("$usvec", { fInvalid_Type.get(), fUShort2_Type.get(), + fUShort3_Type.get(), fUShort4_Type.get() })) + , fBVec_Type(new Type("$bvec", { fInvalid_Type.get(), fBool2_Type.get(), + fBool3_Type.get(), fBool4_Type.get() })) + , fSkCaps_Type(new Type("$sk_Caps")) + , fSkArgs_Type(new Type("$sk_Args")) + , fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4)) , fDefined_Expression(new Defined(*fInvalid_Type)) {} static std::vector<const Type*> static_type(const Type& t) { @@ -343,14 +343,14 @@ private: class Defined : public Expression { public: Defined(const Type& type) - : INHERITED(Position(), kDefined_Kind, type) {} + : INHERITED(-1, kDefined_Kind, type) {} bool hasSideEffects() const override { return false; } String description() const override { - return String("<defined>"); + return "<defined>"; } typedef Expression INHERITED; diff --git a/src/sksl/SkSLErrorReporter.h b/src/sksl/SkSLErrorReporter.h index 172e4888d8..303a0e14e5 100644 --- a/src/sksl/SkSLErrorReporter.h +++ b/src/sksl/SkSLErrorReporter.h @@ -19,11 +19,11 @@ class ErrorReporter { public: virtual ~ErrorReporter() {} - void error(Position position, const char* msg) { - this->error(position, String(msg)); + void error(int offset, const char* msg) { + this->error(offset, String(msg)); } - virtual void error(Position position, String msg) = 0; + virtual void error(int offset, String msg) = 0; virtual int errorCount() = 0; }; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 64527a0eb6..52a40f8367 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -42,6 +42,19 @@ 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()); } @@ -51,7 +64,9 @@ void GLSLCodeGenerator::writeLine() { } void GLSLCodeGenerator::writeExtension(const Extension& ext) { - this->writeLine("#extension " + ext.fName + " : enable"); + this->write("#extension "); + this->write(ext.fName); + this->writeLine(" : enable"); } void GLSLCodeGenerator::writeType(const Type& type) { @@ -59,19 +74,23 @@ void GLSLCodeGenerator::writeType(const Type& type) { for (const Type* search : fWrittenStructs) { if (*search == type) { // already written - this->write(type.name()); + this->write(type.fName); return; } } fWrittenStructs.push_back(&type); - this->writeLine("struct " + type.name() + " {"); + this->write("struct "); + this->write(type.fName); + this->writeLine(" {"); fIndentation++; for (const auto& f : type.fields()) { this->writeModifiers(f.fModifiers, false); this->writeTypePrecision(*f.fType); // sizes (which must be static in structs) are part of the type name here this->writeType(*f.fType); - this->writeLine(" " + f.fName + ";"); + this->write(" "); + this->write(f.fName); + this->writeLine(";"); } fIndentation--; this->write("}"); @@ -138,12 +157,12 @@ void GLSLCodeGenerator::writeType(const Type& type) { this->write("uint"); } else { - this->write(type.name()); + this->write(type.fName); } break; } default: - this->write(type.name()); + this->write(type.fName); } } } @@ -210,8 +229,8 @@ 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 += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; - this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; + this->fFunctionHeader += String(" ") + absExpr.fType.fName + " " + tmpVar1 + ";\n"; + this->fFunctionHeader += String(" ") + otherExpr.fType.fName + " " + tmpVar2 + ";\n"; this->write("((" + tmpVar1 + " = "); this->writeExpression(absExpr, kTopLevel_Precedence); this->write(") < (" + tmpVar2 + " = "); @@ -503,7 +522,9 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, this->write("("); } this->writeExpression(*b.fLeft, precedence); - this->write(" " + Token::OperatorName(b.fOperator) + " "); + this->write(" "); + this->write(Compiler::OperatorName(b.fOperator)); + this->write(" "); this->writeExpression(*b.fRight, precedence); if (precedence >= parentPrecedence) { this->write(")"); @@ -530,7 +551,7 @@ void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, if (kPrefix_Precedence >= parentPrecedence) { this->write("("); } - this->write(Token::OperatorName(p.fOperator)); + this->write(Compiler::OperatorName(p.fOperator)); this->writeExpression(*p.fOperand, kPrefix_Precedence); if (kPrefix_Precedence >= parentPrecedence) { this->write(")"); @@ -543,7 +564,7 @@ void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, this->write("("); } this->writeExpression(*p.fOperand, kPostfix_Precedence); - this->write(Token::OperatorName(p.fOperator)); + this->write(Compiler::OperatorName(p.fOperator)); if (kPostfix_Precedence >= parentPrecedence) { this->write(")"); } diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index e10299aa14..353cd66824 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -90,6 +90,8 @@ 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 50d242896a..482020af7f 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.fName == "float2") { + if (type.name() == "float2") { return "SkPoint"; - } else if (type.fName == "int4") { + } else if (type.name() == "int4") { return "SkIRect"; - } else if (type.fName == "float4") { + } else if (type.name() == "float4") { return "SkRect"; - } else if (type.fName == "float4x4") { + } else if (type.name() == "float4x4") { return "SkMatrix44"; } else if (type.kind() == Type::kSampler_Kind) { return "sk_sp<GrTextureProxy>"; - } else if (type.fName == "colorSpaceXform") { + } else if (type.name() == "colorSpaceXform") { return "sk_sp<GrColorSpaceXform>"; } return type.name(); @@ -127,7 +127,7 @@ void HCodeGenerator::writeMake() { separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), - param->fName.c_str()); + String(param->fName).c_str()); separator = ", "; } this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); @@ -136,7 +136,7 @@ void HCodeGenerator::writeMake() { fFullName.c_str()); separator = ""; for (const auto& param : fSectionAndParameterHelper.getParameters()) { - this->writef("%s%s", separator, param->fName.c_str()); + this->writef("%s%s", separator, String(param->fName).c_str()); separator = ", "; } this->writeExtraConstructorParams(separator); @@ -148,7 +148,7 @@ void HCodeGenerator::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]->fPosition, String("@") + section + " " + msg); + fErrors.error(s[0]->fOffset, 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(), - param->fName.c_str()); + String(param->fName).c_str()); separator = ", "; } this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); @@ -177,7 +177,8 @@ void HCodeGenerator::writeConstructor() { this->writef(")"); this->writeSection(INITIALIZERS_SECTION, "\n , "); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - const char* name = param->fName.c_str(); + String nameString(param->fName); + const char* name = nameString.c_str(); if (param->fType.kind() == Type::kSampler_Kind) { this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name); for (const Section* s : fSectionAndParameterHelper.getSections( @@ -201,7 +202,7 @@ void HCodeGenerator::writeConstructor() { for (const auto& param : fSectionAndParameterHelper.getParameters()) { if (param->fType.kind() == Type::kSampler_Kind) { this->writef(" this->addTextureSampler(&%s);\n", - FieldName(param->fName.c_str()).c_str()); + FieldName(String(param->fName).c_str()).c_str()); } } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { @@ -216,8 +217,8 @@ void HCodeGenerator::writeConstructor() { void HCodeGenerator::writeFields() { this->writeSection(FIELDS_SECTION); for (const auto& param : fSectionAndParameterHelper.getParameters()) { - const char* name = param->fName.c_str(); - this->writef(" %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str()); + this->writef(" %s %s;\n", FieldType(param->fType).c_str(), + FieldName(String(param->fName).c_str()).c_str()); } for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) { this->writef(" GrCoordTransform %sCoordTransform;\n", @@ -245,7 +246,8 @@ bool HCodeGenerator::generateCode() { if (param->fType.kind() == Type::kSampler_Kind) { continue; } - const char* name = param->fName.c_str(); + String nameString(param->fName); + const char* name = nameString.c_str(); this->writef(" %s %s() const { return %s; }\n", FieldType(param->fType).c_str(), name, FieldName(name).c_str()); } diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index a46a9312c1..83ab993c2a 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.fPosition, extension.fName)); + return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName)); } std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) { @@ -206,7 +206,7 @@ std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) { } statements.push_back(std::move(statement)); } - return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable)); + return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable)); } std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement( @@ -234,12 +234,12 @@ 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->fPosition, "array size must be positive"); + fErrors.error(size->fOffset, "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->fName + "[]", Type::kArray_Kind, *type, -1); + type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1); fSymbolTable->takeOwnership((Type*) type); sizes.push_back(nullptr); } } - auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers, + auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers, varDecl.fName, *type, storage)); std::unique_ptr<Expression> value; if (varDecl.fValue) { @@ -266,7 +266,7 @@ 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 == String("sk_FragColor") && + if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" && (*fSymbolTable)[varDecl.fName]) { // already defined, ignore } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] && @@ -281,7 +281,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa fSymbolTable->add(varDecl.fName, std::move(var)); } } - return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition, + return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset, baseType, std::move(variables))); } @@ -334,11 +334,11 @@ 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.fPosition, std::move(empty), + return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty), fSymbolTable)); } } - return std::unique_ptr<Statement>(new IfStatement(s.fPosition, s.fIsStatic, std::move(test), + return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test), std::move(ifTrue), std::move(ifFalse))); } @@ -371,7 +371,7 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer), + return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer), std::move(test), std::move(next), std::move(statement), fSymbolTable)); } @@ -387,7 +387,7 @@ std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test), + return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test), std::move(statement))); } @@ -402,7 +402,7 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) { if (!statement) { return nullptr; } - return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement), + return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement), std::move(test))); } @@ -435,13 +435,13 @@ std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& } } if (!caseValue->isConstant()) { - fErrors.error(caseValue->fPosition, "case value must be a constant"); + fErrors.error(caseValue->fOffset, "case value must be a constant"); return nullptr; } ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind); int64_t v = ((IntLiteral&) *caseValue).fValue; if (caseValues.find(v) != caseValues.end()) { - fErrors.error(caseValue->fPosition, "duplicate case value"); + fErrors.error(caseValue->fOffset, "duplicate case value"); } caseValues.insert(v); } @@ -453,10 +453,10 @@ std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& } statements.push_back(std::move(converted)); } - cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue), + cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue), std::move(statements))); } - return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, s.fIsStatic, + return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic, std::move(value), std::move(cases), fSymbolTable)); } @@ -479,7 +479,7 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& return nullptr; } if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) { - fErrors.error(result->fPosition, "may not return a value from a void function"); + fErrors.error(result->fOffset, "may not return a value from a void function"); } else { result = this->coerce(std::move(result), fCurrentFunction->fReturnType); if (!result) { @@ -489,45 +489,45 @@ 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.fPosition, "expected function to return '" + - fCurrentFunction->fReturnType.description() + "'"); + fErrors.error(r.fOffset, "expected function to return '" + + fCurrentFunction->fReturnType.description() + "'"); } - return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition)); + return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset)); } } std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) { if (fLoopLevel > 0 || fSwitchLevel > 0) { - return std::unique_ptr<Statement>(new BreakStatement(b.fPosition)); + return std::unique_ptr<Statement>(new BreakStatement(b.fOffset)); } else { - fErrors.error(b.fPosition, "break statement must be inside a loop or switch"); + fErrors.error(b.fOffset, "break statement must be inside a loop or switch"); return nullptr; } } std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) { if (fLoopLevel > 0) { - return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition)); + return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset)); } else { - fErrors.error(c.fPosition, "continue statement must be inside a loop"); + fErrors.error(c.fOffset, "continue statement must be inside a loop"); return nullptr; } } std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) { - return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition)); + return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset)); } std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main, std::vector<std::unique_ptr<ProgramElement>>* out) { Layout invokeLayout; Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag); - FunctionDeclaration* invokeDecl = new FunctionDeclaration(Position(), + FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1, invokeModifiers, "_invoke", std::vector<const Variable*>(), *fContext.fVoid_Type); - out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(Position(), + out->push_back(std::unique_ptr<ProgramElement>(new FunctionDefinition(-1, *invokeDecl, std::move(main)))); fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl)); @@ -535,47 +535,47 @@ std::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(Position(), - std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)), + std::unique_ptr<Expression> test(new BinaryExpression(-1, + std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)), Token::LT, - std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), fInvocations)), + std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)), *fContext.fBool_Type)); std::unique_ptr<Expression> next(new PostfixExpression( std::unique_ptr<Expression>( - new VariableReference(Position(), + new VariableReference(-1, *loopIdx, VariableReference::kReadWrite_RefKind)), Token::PLUSPLUS)); - ASTIdentifier endPrimitiveID = ASTIdentifier(Position(), "EndPrimitive"); + ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive"); std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID); ASSERT(endPrimitive); std::vector<std::unique_ptr<Statement>> loopBody; std::vector<std::unique_ptr<Expression>> invokeArgs; loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement( - this->call(Position(), + this->call(-1, *invokeDecl, std::vector<std::unique_ptr<Expression>>())))); loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement( - this->call(Position(), + this->call(-1, std::move(endPrimitive), std::vector<std::unique_ptr<Expression>>())))); - std::unique_ptr<Expression> assignment(new BinaryExpression(Position(), - std::unique_ptr<Expression>(new VariableReference(Position(), *loopIdx)), + std::unique_ptr<Expression> assignment(new BinaryExpression(-1, + std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)), Token::EQ, - std::unique_ptr<IntLiteral>(new IntLiteral(fContext, Position(), 0)), + std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)), *fContext.fInt_Type)); std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment))); std::unique_ptr<Statement> loop = std::unique_ptr<Statement>( - new ForStatement(Position(), + new ForStatement(-1, std::move(initializer), std::move(test), std::move(next), - std::unique_ptr<Block>(new Block(Position(), std::move(loopBody))), + std::unique_ptr<Block>(new Block(-1, std::move(loopBody))), fSymbolTable)); std::vector<std::unique_ptr<Statement>> children; children.push_back(std::move(loop)); - return std::unique_ptr<Block>(new Block(Position(), std::move(children))); + return std::unique_ptr<Block>(new Block(-1, std::move(children))); } void IRGenerator::convertFunction(const ASTFunction& f, @@ -597,9 +597,8 @@ void IRGenerator::convertFunction(const ASTFunction& f, fSymbolTable->takeOwnership(newType); type = newType; } - String name = param->fName; - Position pos = param->fPosition; - Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type, + StringFragment name = param->fName; + Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type, Variable::kParameter_Storage); fSymbolTable->takeOwnership(var); parameters.push_back(var); @@ -618,7 +617,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, functions.push_back((FunctionDeclaration*) entry); break; default: - fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined"); + fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined"); return; } for (const auto& other : functions) { @@ -633,26 +632,26 @@ void IRGenerator::convertFunction(const ASTFunction& f, } if (match) { if (*returnType != other->fReturnType) { - FunctionDeclaration newDecl(f.fPosition, f.fModifiers, f.fName, parameters, + FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters, *returnType); - fErrors.error(f.fPosition, "functions '" + newDecl.description() + - "' and '" + other->description() + - "' differ only in return type"); + fErrors.error(f.fOffset, "functions '" + newDecl.description() + + "' and '" + other->description() + + "' differ only in return type"); return; } decl = other; for (size_t i = 0; i < parameters.size(); i++) { if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) { - fErrors.error(f.fPosition, "modifiers on parameter " + - to_string((uint64_t) i + 1) + - " differ between declaration and " - "definition"); + fErrors.error(f.fOffset, "modifiers on parameter " + + to_string((uint64_t) i + 1) + + " differ between declaration and " + "definition"); return; } } if (other->fDefined) { - fErrors.error(f.fPosition, "duplicate definition of " + - other->description()); + fErrors.error(f.fOffset, "duplicate definition of " + + other->description()); } break; } @@ -661,7 +660,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, } if (!decl) { // couldn't find an existing declaration - auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition, + auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset, f.fModifiers, f.fName, parameters, @@ -698,7 +697,7 @@ void IRGenerator::convertFunction(const ASTFunction& f, ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag; out->push_back(std::unique_ptr<FunctionDefinition>( - new FunctionDefinition(f.fPosition, *decl, std::move(body)))); + new FunctionDefinition(f.fOffset, *decl, std::move(body)))); } } @@ -717,14 +716,14 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte for (const auto& stmt : decl->fVars) { VarDeclaration& vd = (VarDeclaration&) *stmt; if (haveRuntimeArray) { - fErrors.error(decl->fPosition, + fErrors.error(decl->fOffset, "only the last entry in an interface block may be a runtime-sized " "array"); } fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName, &vd.fVar->fType)); if (vd.fValue) { - fErrors.error(decl->fPosition, + fErrors.error(decl->fOffset, "initializers are not permitted on interface block fields"); } if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag | @@ -732,7 +731,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte Modifiers::kUniform_Flag | Modifiers::kBuffer_Flag | Modifiers::kConst_Flag)) { - fErrors.error(decl->fPosition, + fErrors.error(decl->fOffset, "interface block fields may not have storage qualifiers"); } if (vd.fVar->fType.kind() == Type::kArray_Kind && @@ -741,7 +740,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte } } } - Type* type = new Type(intf.fPosition, intf.fTypeName, fields); + Type* type = new Type(intf.fOffset, intf.fTypeName, fields); old->takeOwnership(type); std::vector<std::unique_ptr<Expression>> sizes; for (const auto& size : intf.fSizes) { @@ -755,7 +754,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte if (converted->fKind == Expression::kIntLiteral_Kind) { count = ((IntLiteral&) *converted).fValue; if (count <= 0) { - fErrors.error(converted->fPosition, "array size must be positive"); + fErrors.error(converted->fOffset, "array size must be positive"); } name += "[" + to_string(count) + "]"; } else { @@ -766,24 +765,24 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte fSymbolTable->takeOwnership((Type*) type); sizes.push_back(std::move(converted)); } else { - type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1); + type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1); fSymbolTable->takeOwnership((Type*) type); sizes.push_back(nullptr); } } - Variable* var = new Variable(intf.fPosition, intf.fModifiers, - intf.fInstanceName.size() ? intf.fInstanceName : intf.fTypeName, + Variable* var = new Variable(intf.fOffset, intf.fModifiers, + intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName, *type, Variable::kGlobal_Storage); old->takeOwnership(var); - if (intf.fInstanceName.size()) { + if (intf.fInstanceName.fLength) { old->addWithoutOwnership(intf.fInstanceName, var); } else { for (size_t i = 0; i < fields.size(); i++) { - old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var, + old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var, (int) i))); } } - return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, + return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset, var, intf.fTypeName, intf.fInstanceName, @@ -795,7 +794,8 @@ const 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 + "["; + String name(result->fName); + name += "["; 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.fPosition, "unknown type '" + type.fName + "'"); + fErrors.error(type.fOffset, "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.fPosition, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset, ((ASTBoolLiteral&) expr).fValue)); case ASTExpression::kInt_Kind: - return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition, + return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset, ((ASTIntLiteral&) expr).fValue)); case ASTExpression::kFloat_Kind: - return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition, + return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset, ((ASTFloatLiteral&) expr).fValue)); case ASTExpression::kBinary_Kind: return this->convertBinaryExpression((ASTBinaryExpression&) expr); @@ -838,7 +838,7 @@ std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) { const Symbol* result = (*fSymbolTable)[identifier.fText]; if (!result) { - fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'"); + fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'"); return nullptr; } switch (result->fKind) { @@ -847,13 +847,13 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& (const FunctionDeclaration*) result }; return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, - identifier.fPosition, + identifier.fOffset, f)); } case Symbol::kUnresolvedFunction_Kind: { const UnresolvedFunction* f = (const UnresolvedFunction*) result; return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, - identifier.fPosition, + identifier.fOffset, f->fFunctions)); } case Symbol::kVariable_Kind: { @@ -870,13 +870,13 @@ 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.fPosition, + identifier.fOffset, *var, VariableReference::kRead_RefKind)); } case Symbol::kField_Kind: { const Field* field = (const Field*) result; - VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner, + VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner, VariableReference::kRead_RefKind); return std::unique_ptr<Expression>(new FieldAccess( std::unique_ptr<Expression>(base), @@ -885,7 +885,7 @@ 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.fPosition, + return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset, *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.fPosition, s.fName, s.fArgument, s.fText)); + return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText)); } @@ -911,24 +911,24 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr return nullptr; } if (expr->coercionCost(type) == INT_MAX) { - fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" + + fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" + expr->fType.description() + "'"); return nullptr; } if (type.kind() == Type::kScalar_Kind) { std::vector<std::unique_ptr<Expression>> args; args.push_back(std::move(expr)); - ASTIdentifier id(Position(), type.description()); + ASTIdentifier id(-1, type.fName); std::unique_ptr<Expression> ctor = this->convertIdentifier(id); ASSERT(ctor); - return this->call(Position(), std::move(ctor), std::move(args)); + return this->call(-1, std::move(ctor), std::move(args)); } if (type == *fContext.fColorSpaceXform_Type && expr->fType == *fContext.fFloat4x4_Type) { return expr; } std::vector<std::unique_ptr<Expression>> args; args.push_back(std::move(expr)); - return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args))); } static bool is_matrix_multiply(const Type& left, const Type& right) { @@ -1094,9 +1094,9 @@ 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.fPosition, result)); + return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result)); } - #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \ + #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \ leftVal op rightVal)) if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) { int64_t leftVal = ((IntLiteral&) left).fValue; @@ -1109,13 +1109,13 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, if (rightVal) { return RESULT(Int, /); } - fErrors.error(right.fPosition, "division by zero"); + fErrors.error(right.fOffset, "division by zero"); return nullptr; case Token::PERCENT: if (rightVal) { return RESULT(Int, %); } - fErrors.error(right.fPosition, "division by zero"); + fErrors.error(right.fOffset, "division by zero"); return nullptr; case Token::BITWISEAND: return RESULT(Int, &); case Token::BITWISEOR: return RESULT(Int, |); @@ -1143,7 +1143,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, if (rightVal) { return RESULT(Float, /); } - fErrors.error(right.fPosition, "division by zero"); + fErrors.error(right.fOffset, "division by zero"); return nullptr; case Token::EQEQ: return RESULT(Bool, ==); case Token::NEQ: return RESULT(Bool, !=); @@ -1164,16 +1164,16 @@ 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, Position(), value)); \ + args.emplace_back(new FloatLiteral(fContext, -1, value)); \ } \ - return std::unique_ptr<Expression>(new Constructor(Position(), left.fType, \ + return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \ std::move(args))); switch (op) { case Token::EQEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), + return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, left.compareConstant(fContext, right))); case Token::NEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), + return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, !left.compareConstant(fContext, right))); case Token::PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+); case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-); @@ -1187,10 +1187,10 @@ 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, Position(), + return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, left.compareConstant(fContext, right))); case Token::NEQ: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, Position(), + return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, !left.compareConstant(fContext, right))); default: return nullptr; @@ -1227,14 +1227,14 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( } if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType, &leftType, &rightType, &resultType, - !Token::IsAssignment(expression.fOperator))) { - fErrors.error(expression.fPosition, "type mismatch: '" + - Token::OperatorName(expression.fOperator) + - "' cannot operate on '" + left->fType.fName + - "', '" + right->fType.fName + "'"); + !Compiler::IsAssignment(expression.fOperator))) { + fErrors.error(expression.fOffset, String("type mismatch: '") + + Compiler::OperatorName(expression.fOperator) + + "' cannot operate on '" + left->fType.fName + + "', '" + right->fType.fName + "'"); return nullptr; } - if (Token::IsAssignment(expression.fOperator)) { + if (Compiler::IsAssignment(expression.fOperator)) { this->markWrittenTo(*left, expression.fOperator != Token::EQ); } left = this->coerce(std::move(left), *leftType); @@ -1245,7 +1245,7 @@ std::unique_ptr<Expression> 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.fPosition, + result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset, 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.fPosition, "ternary operator result mismatch: '" + - ifTrue->fType.fName + "', '" + - ifFalse->fType.fName + "'"); + fErrors.error(expression.fOffset, "ternary operator result mismatch: '" + + ifTrue->fType.fName + "', '" + + ifFalse->fType.fName + "'"); return nullptr; } ifTrue = this->coerce(std::move(ifTrue), *trueType); @@ -1295,7 +1295,7 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( return ifFalse; } } - return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition, + return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset, std::move(test), std::move(ifTrue), std::move(ifFalse))); @@ -1315,8 +1315,8 @@ 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(Position(), sampler)); - std::unique_ptr<Expression> float2ize = call(Position(), textureSize, std::move(sizeArguments)); + sizeArguments.emplace_back(new VariableReference(-1, sampler)); + std::unique_ptr<Expression> float2ize = call(-1, textureSize, std::move(sizeArguments)); const Type& type = arguments[1]->fType; std::unique_ptr<Expression> scale; if (type == *fContext.fFloat2_Type) { @@ -1325,14 +1325,14 @@ 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, Position(), 1.0)); - scale.reset(new Constructor(Position(), *fContext.fFloat3_Type, std::move(float3rguments))); + float3rguments.emplace_back(new FloatLiteral(fContext, -1, 1.0)); + scale.reset(new Constructor(-1, *fContext.fFloat3_Type, std::move(float3rguments))); } - arguments[1].reset(new BinaryExpression(Position(), std::move(scale), Token::STAR, + arguments[1].reset(new BinaryExpression(-1, std::move(scale), Token::STAR, std::move(arguments[1]), type)); } -std::unique_ptr<Expression> IRGenerator::call(Position position, +std::unique_ptr<Expression> IRGenerator::call(int offset, const FunctionDeclaration& function, std::vector<std::unique_ptr<Expression>> arguments) { if (function.fParameters.size() != arguments.size()) { @@ -1343,7 +1343,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, msg += "s"; } msg += ", but found " + to_string((uint64_t) arguments.size()); - fErrors.error(position, msg); + fErrors.error(offset, msg); return nullptr; } std::vector<const Type*> types; @@ -1357,7 +1357,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, msg += arguments[i]->fType.description(); } msg += ")"; - fErrors.error(position, msg); + fErrors.error(offset, msg); return nullptr; } for (size_t i = 0; i < arguments.size(); i++) { @@ -1374,7 +1374,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, arguments[0]->fType == *fContext.fSampler2DRect_Type) { this->fixRectSampling(arguments); } - return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function, + return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function, std::move(arguments))); } @@ -1409,26 +1409,26 @@ std::unique_ptr<Expression> IRGenerator::applyColorSpace(std::unique_ptr<Express std::unique_ptr<Expression> xform) { // Before: texture(img, coords, xform); // After: COLORSPACE(texture(img, coords), xform) - Position p = texture->fPosition; + int offset = texture->fOffset; std::vector<std::unique_ptr<Expression>> args; args.push_back(std::move(texture)); args.push_back(std::move(xform)); const Symbol* colorspaceSymbol = (*fSymbolTable)["COLORSPACE"]; ASSERT(colorspaceSymbol->fKind == Symbol::kFunctionDeclaration_Kind); const FunctionDeclaration& colorspaceFunction = (FunctionDeclaration&) *colorspaceSymbol; - return this->call(p, colorspaceFunction, std::move(args)); + return this->call(offset, colorspaceFunction, std::move(args)); } -std::unique_ptr<Expression> IRGenerator::call(Position position, +std::unique_ptr<Expression> IRGenerator::call(int offset, std::unique_ptr<Expression> functionValue, std::vector<std::unique_ptr<Expression>> arguments) { if (functionValue->fKind == Expression::kTypeReference_Kind) { - return this->convertConstructor(position, + return this->convertConstructor(offset, ((TypeReference&) *functionValue).fValue, std::move(arguments)); } if (functionValue->fKind != Expression::kFunctionReference_Kind) { - fErrors.error(position, "'" + functionValue->description() + "' is not a function"); + fErrors.error(offset, "'" + functionValue->description() + "' is not a function"); return nullptr; } FunctionReference* ref = (FunctionReference*) functionValue.get(); @@ -1436,7 +1436,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, arguments.back()->fType == *fContext.fColorSpaceXform_Type) { std::unique_ptr<Expression> colorspace = std::move(arguments.back()); arguments.pop_back(); - return this->applyColorSpace(this->call(position, + return this->applyColorSpace(this->call(offset, std::move(functionValue), std::move(arguments)), std::move(colorspace)); @@ -1453,7 +1453,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, } } if (best) { - return this->call(position, *best, std::move(arguments)); + return this->call(offset, *best, std::move(arguments)); } String msg = "no match for " + ref->fFunctions[0]->fName + "("; String separator; @@ -1463,21 +1463,21 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, msg += arguments[i]->fType.description(); } msg += ")"; - fErrors.error(position, msg); + fErrors.error(offset, msg); return nullptr; } - return this->call(position, *ref->fFunctions[0], std::move(arguments)); + return this->call(offset, *ref->fFunctions[0], std::move(arguments)); } std::unique_ptr<Expression> IRGenerator::convertNumberConstructor( - Position position, + int offset, const Type& type, std::vector<std::unique_ptr<Expression>> args) { ASSERT(type.isNumber()); if (args.size() != 1) { - fErrors.error(position, "invalid arguments to '" + type.description() + - "' constructor, (expected exactly 1 argument, but found " + - to_string((uint64_t) args.size()) + ")"); + fErrors.error(offset, "invalid arguments to '" + type.description() + + "' constructor, (expected exactly 1 argument, but found " + + to_string((uint64_t) args.size()) + ")"); return nullptr; } if (type.isFloat() && args[0]->fType.isFloat()) { @@ -1491,31 +1491,31 @@ 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, position, (double) value)); + return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, (double) value)); } if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || type == *fContext.fUInt_Type)) { return std::unique_ptr<Expression>(new IntLiteral(fContext, - position, + offset, ((IntLiteral&) *args[0]).fValue, &type)); } if (args[0]->fType == *fContext.fBool_Type) { - std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); - std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1)); + std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0)); + std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1)); return std::unique_ptr<Expression>( - new TernaryExpression(position, std::move(args[0]), + new TernaryExpression(offset, std::move(args[0]), this->coerce(std::move(one), type), this->coerce(std::move(zero), type))); } if (!args[0]->fType.isNumber()) { - fErrors.error(position, "invalid argument to '" + type.description() + - "' constructor (expected a number or bool, but found '" + - args[0]->fType.description() + "')"); + fErrors.error(offset, "invalid argument to '" + type.description() + + "' constructor (expected a number or bool, but found '" + + args[0]->fType.description() + "')"); return nullptr; } - return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); } int component_count(const Type& type) { @@ -1530,14 +1530,14 @@ int component_count(const Type& type) { } std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( - Position position, + int offset, const Type& type, std::vector<std::unique_ptr<Expression>> args) { ASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind); if (type.kind() == Type::kMatrix_Kind && args.size() == 1 && args[0]->fType.kind() == Type::kMatrix_Kind) { // matrix from matrix is always legal - return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); } int actual = 0; int expected = type.rows() * type.columns(); @@ -1547,9 +1547,9 @@ 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(position, "'" + args[i]->fType.description() + "' is not a valid " - "parameter to '" + type.description() + - "' constructor"); + fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid " + "parameter to '" + type.description() + + "' constructor"); return nullptr; } actual += args[i]->fType.columns(); @@ -1562,23 +1562,23 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( } } } else { - fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid " - "parameter to '" + type.description() + "' constructor"); + fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid " + "parameter to '" + type.description() + "' constructor"); return nullptr; } } if (actual != 1 && actual != expected) { - fErrors.error(position, "invalid arguments to '" + type.description() + - "' constructor (expected " + to_string(expected) + - " scalars, but found " + to_string(actual) + ")"); + fErrors.error(offset, "invalid arguments to '" + type.description() + + "' constructor (expected " + to_string(expected) + + " scalars, but found " + to_string(actual) + ")"); return nullptr; } } - return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); } std::unique_ptr<Expression> IRGenerator::convertConstructor( - Position position, + int offset, const Type& type, std::vector<std::unique_ptr<Expression>> args) { // FIXME: add support for structs @@ -1588,7 +1588,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( return std::move(args[0]); } if (type.isNumber()) { - return this->convertNumberConstructor(position, type, std::move(args)); + return this->convertNumberConstructor(offset, type, std::move(args)); } else if (kind == Type::kArray_Kind) { const Type& base = type.componentType(); for (size_t i = 0; i < args.size(); i++) { @@ -1597,11 +1597,11 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( return nullptr; } } - return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); + return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) { - return this->convertCompoundConstructor(position, type, std::move(args)); + return this->convertCompoundConstructor(offset, type, std::move(args)); } else { - fErrors.error(position, "cannot construct '" + type.description() + "'"); + fErrors.error(offset, "cannot construct '" + type.description() + "'"); return nullptr; } } @@ -1615,31 +1615,31 @@ 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.fPosition, + fErrors.error(expression.fOffset, "'+' cannot operate on '" + base->fType.description() + "'"); return nullptr; } return base; case Token::MINUS: if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fOffset, "'-' cannot operate on '" + base->fType.description() + "'"); return nullptr; } if (base->fKind == Expression::kIntLiteral_Kind) { - return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition, + return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset, -((IntLiteral&) *base).fValue)); } if (base->fKind == Expression::kFloatLiteral_Kind) { double value = -((FloatLiteral&) *base).fValue; - return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition, + return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset, value)); } return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base))); case Token::PLUSPLUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fOffset, + String("'") + Compiler::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1647,8 +1647,8 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( break; case Token::MINUSMINUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fOffset, + String("'") + Compiler::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1656,20 +1656,20 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( break; case Token::LOGICALNOT: if (base->fType != *fContext.fBool_Type) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fOffset, + String("'") + Compiler::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } if (base->fKind == Expression::kBoolLiteral_Kind) { - return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fPosition, + return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset, !((BoolLiteral&) *base).fValue)); } break; case Token::BITWISENOT: if (base->fType != *fContext.fInt_Type) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fOffset, + String("'") + Compiler::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1690,18 +1690,18 @@ 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->fPosition, + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset, *newType)); } else { - fErrors.error(base->fPosition, "array size must be a constant"); + fErrors.error(base->fOffset, "array size must be a constant"); return nullptr; } } if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + - "'"); + fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() + + "'"); return nullptr; } std::unique_ptr<Expression> converted = this->convertExpression(index); @@ -1719,26 +1719,26 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression } std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base, - const String& field) { + StringFragment field) { auto fields = base->fType.fields(); for (size_t i = 0; i < fields.size(); i++) { if (fields[i].fName == field) { return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i)); } } - fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a " - "field named '" + field + ""); + fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a " + "field named '" + field + ""); return nullptr; } std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base, - const String& fields) { + StringFragment fields) { if (base->fType.kind() != Type::kVector_Kind) { - fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'"); + fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'"); return nullptr; } std::vector<int> swizzleComponents; - for (size_t i = 0; i < fields.size(); i++) { + for (size_t i = 0; i < fields.fLength; i++) { switch (fields[i]) { case 'x': // fall through case 'r': // fall through @@ -1770,40 +1770,40 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi } // fall through default: - fErrors.error(base->fPosition, String::printf("invalid swizzle component '%c'", - fields[i])); + fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'", + fields[i])); return nullptr; } } ASSERT(swizzleComponents.size() > 0); if (swizzleComponents.size() > 4) { - fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'"); + fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'"); return nullptr; } return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents)); } -std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name) { +std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) { auto found = fCapsMap.find(name); if (found == fCapsMap.end()) { - fErrors.error(position, "unknown capability flag '" + name + "'"); + fErrors.error(offset, "unknown capability flag '" + name + "'"); return nullptr; } String fullName = "sk_Caps." + name; - return std::unique_ptr<Expression>(new Setting(position, fullName, - found->second.literal(fContext, position))); + return std::unique_ptr<Expression>(new Setting(offset, fullName, + found->second.literal(fContext, offset))); } -std::unique_ptr<Expression> IRGenerator::getArg(Position position, String name) { +std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) { auto found = fSettings->fArgs.find(name); if (found == fSettings->fArgs.end()) { - fErrors.error(position, "unknown argument '" + name + "'"); + fErrors.error(offset, "unknown argument '" + name + "'"); return nullptr; } String fullName = "sk_Args." + name; - return std::unique_ptr<Expression>(new Setting(position, + return std::unique_ptr<Expression>(new Setting(offset, fullName, - found->second.literal(fContext, position))); + found->second.literal(fContext, offset))); } std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( @@ -1822,10 +1822,10 @@ 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->fPosition, + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset, *newType)); } else { - fErrors.error(expression.fPosition, "'[]' must follow a type name"); + fErrors.error(expression.fOffset, "'[]' must follow a type name"); return nullptr; } } @@ -1840,15 +1840,15 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( } arguments.push_back(std::move(converted)); } - return this->call(expression.fPosition, std::move(base), std::move(arguments)); + return this->call(expression.fOffset, std::move(base), std::move(arguments)); } case ASTSuffix::kField_Kind: { if (base->fType == *fContext.fSkCaps_Type) { - return this->getCap(expression.fPosition, + return this->getCap(expression.fOffset, ((ASTFieldSuffix&) *expression.fSuffix).fField); } if (base->fType == *fContext.fSkArgs_Type) { - return this->getArg(expression.fPosition, + return this->getArg(expression.fOffset, ((ASTFieldSuffix&) *expression.fSuffix).fField); } switch (base->fType.kind()) { @@ -1859,14 +1859,14 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( return this->convertField(std::move(base), ((ASTFieldSuffix&) *expression.fSuffix).fField); default: - fErrors.error(base->fPosition, "cannot swizzle value of type '" + - base->fType.description() + "'"); + fErrors.error(base->fOffset, "cannot swizzle value of type '" + + base->fType.description() + "'"); return nullptr; } } case ASTSuffix::kPostIncrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fOffset, "'++' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1875,7 +1875,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( Token::PLUSPLUS)); case ASTSuffix::kPostDecrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fOffset, "'--' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1890,14 +1890,14 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( void IRGenerator::checkValid(const Expression& expr) { switch (expr.fKind) { case Expression::kFunctionReference_Kind: - fErrors.error(expr.fPosition, "expected '(' to begin function call"); + fErrors.error(expr.fOffset, "expected '(' to begin function call"); break; case Expression::kTypeReference_Kind: - fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation"); + fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation"); break; default: if (expr.fType == *fContext.fInvalid_Type) { - fErrors.error(expr.fPosition, "invalid expression"); + fErrors.error(expr.fOffset, "invalid expression"); } } } @@ -1920,7 +1920,7 @@ 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.fPosition, + fErrors.error(expr.fOffset, "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.fPosition, + fErrors.error(expr.fOffset, "cannot write to the same swizzle field more than once"); } this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite); @@ -1941,18 +1941,20 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) { this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite); break; default: - fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'"); + fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'"); break; } } -void IRGenerator::convertProgram(String text, +void IRGenerator::convertProgram(const char* text, + size_t length, SymbolTable& types, Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* out) { - Parser parser(text, types, fErrors); + Parser parser(text, length, types, fErrors); std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file(); if (fErrors.errorCount()) { + printf("float type has name: '%s'\n", fContext.fFloat_Type->name().c_str()); return; } *defaultPrecision = Modifiers::kHighp_Flag; diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 0a1bae4f64..3dda02835b 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -61,7 +61,8 @@ public: IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root, ErrorReporter& errorReporter); - void convertProgram(String text, + void convertProgram(const char* text, + size_t length, SymbolTable& types, Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* result); @@ -103,26 +104,26 @@ private: const ASTModifiersDeclaration& m); const Type* convertType(const ASTType& type); - std::unique_ptr<Expression> call(Position position, + std::unique_ptr<Expression> call(int offset, const FunctionDeclaration& function, std::vector<std::unique_ptr<Expression>> arguments); int callCost(const FunctionDeclaration& function, const std::vector<std::unique_ptr<Expression>>& arguments); - std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function, + std::unique_ptr<Expression> call(int offset, std::unique_ptr<Expression> function, std::vector<std::unique_ptr<Expression>> arguments); int coercionCost(const Expression& expr, const Type& type); std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type); std::unique_ptr<Block> convertBlock(const ASTBlock& block); std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b); std::unique_ptr<Expression> convertNumberConstructor( - Position position, + int offset, const Type& type, std::vector<std::unique_ptr<Expression>> params); std::unique_ptr<Expression> convertCompoundConstructor( - Position position, + int offset, const Type& type, std::vector<std::unique_ptr<Expression>> params); - std::unique_ptr<Expression> convertConstructor(Position position, + std::unique_ptr<Expression> convertConstructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> params); std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c); @@ -142,13 +143,13 @@ 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(Position position, String name); - std::unique_ptr<Expression> getArg(Position position, String name); + std::unique_ptr<Expression> getCap(int offset, String name); + std::unique_ptr<Expression> getArg(int offset, String name); std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression); std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base, - const String& field); + StringFragment field); std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base, - const String& fields); + StringFragment fields); std::unique_ptr<Expression> convertTernaryExpression(const ASTTernaryExpression& expression); std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s); std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w); diff --git a/src/sksl/SkSLLayoutLexer.cpp b/src/sksl/SkSLLayoutLexer.cpp new file mode 100644 index 0000000000..968391ea96 --- /dev/null +++ b/src/sksl/SkSLLayoutLexer.cpp @@ -0,0 +1,1343 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/***************************************************************************************** + ******************** This file was generated by sksllex. Do not edit. ******************* + *****************************************************************************************/ +#include "SkSLLayoutLexer.h" + +namespace SkSL { + +static int16_t transitions[127][207] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, + 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, + 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 91, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, + 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 194, 0, 0, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 95, 0, 0, 98, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 201, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 58, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, + 0, 0, 117, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 0, 0, 0, 138, 0, 0, 0, 142, 0, 0, 0, 0, 147, 0, 0, 0, 0, 152, + 0, 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, 0, 205, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, + }, + { + 0, 42, 0, 4, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 37, 0, 0, 40, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, + 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, + 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 79, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 5, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 41, 0, + 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 0, + 169, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 0, 0, 206, 0, + }, + { + 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, + 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 158, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, + 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, + 0, 0, 0, 0, 143, 144, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 89, 84, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 162, 0, 164, 0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 192, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 49, 0, 0, 52, 53, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 171, 0, 0, 174, 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, +}; + +static int16_t accepts[207] = { + -1, -1, 23, 23, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, 6, 23, -1, -1, -1, + 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, + -1, -1, -1, -1, -1, -1, 20, 23, -1, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, 14, 13, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, 1, 23, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 19, 23, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 23, -1, -1, -1, + -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 23, -1, 5, 23, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 17, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 23, -1, -1, 21, +}; + +LayoutToken LayoutLexer::next() { + int startOffset = fOffset; + if (startOffset == fLength) { + return LayoutToken(LayoutToken::END_OF_FILE, startOffset, 0); + } + int offset = startOffset; + int state = 1; + LayoutToken::Kind lastAccept = LayoutToken::Kind::INVALID; + int lastAcceptEnd = startOffset + 1; + while (offset < fLength) { + state = transitions[(int)fText[offset]][state]; + ++offset; + if (!state) { + break; + } + if (accepts[state]) { + lastAccept = (LayoutToken::Kind)accepts[state]; + lastAcceptEnd = offset; + } + } + fOffset = lastAcceptEnd; + return LayoutToken(lastAccept, startOffset, lastAcceptEnd - startOffset); +} + +} // namespace diff --git a/src/sksl/SkSLLayoutLexer.h b/src/sksl/SkSLLayoutLexer.h new file mode 100644 index 0000000000..f3d250ad8d --- /dev/null +++ b/src/sksl/SkSLLayoutLexer.h @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/***************************************************************************************** + ******************** This file was generated by sksllex. Do not edit. ******************* + *****************************************************************************************/ +#ifndef SKSL_LayoutLexer +#define SKSL_LayoutLexer +#include <cstddef> +#include <cstdint> +namespace SkSL { + +struct LayoutToken { + enum Kind { +#undef END_OF_FILE + END_OF_FILE, +#undef LOCATION + LOCATION, +#undef OFFSET + OFFSET, +#undef BINDING + BINDING, +#undef INDEX + INDEX, +#undef SET + SET, +#undef BUILTIN + BUILTIN, +#undef INPUT_ATTACHMENT_INDEX + INPUT_ATTACHMENT_INDEX, +#undef ORIGIN_UPPER_LEFT + ORIGIN_UPPER_LEFT, +#undef OVERRIDE_COVERAGE + OVERRIDE_COVERAGE, +#undef BLEND_SUPPORT_ALL_EQUATIONS + BLEND_SUPPORT_ALL_EQUATIONS, +#undef PUSH_CONSTANT + PUSH_CONSTANT, +#undef POINTS + POINTS, +#undef LINES + LINES, +#undef LINE_STRIP + LINE_STRIP, +#undef LINES_ADJACENCY + LINES_ADJACENCY, +#undef TRIANGLES + TRIANGLES, +#undef TRIANGLE_STRIP + TRIANGLE_STRIP, +#undef TRIANGLES_ADJACENCY + TRIANGLES_ADJACENCY, +#undef MAX_VERTICES + MAX_VERTICES, +#undef INVOCATIONS + INVOCATIONS, +#undef WHEN + WHEN, +#undef KEY + KEY, +#undef INVALID + INVALID, + }; + + LayoutToken() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {} + + LayoutToken(Kind kind, int offset, int length) + : fKind(kind), fOffset(offset), fLength(length) {} + + Kind fKind; + int fOffset; + int fLength; +}; + +class LayoutLexer { +public: + void start(const char* text, size_t length) { + fText = text; + fLength = length; + fOffset = 0; + } + + LayoutToken next(); + +private: + const char* fText; + int fLength; + int fOffset; +}; + +} // namespace +#endif diff --git a/src/sksl/SkSLLexer.cpp b/src/sksl/SkSLLexer.cpp new file mode 100644 index 0000000000..ed905ac2cf --- /dev/null +++ b/src/sksl/SkSLLexer.cpp @@ -0,0 +1,1925 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/***************************************************************************************** + ******************** This file was generated by sksllex. Do not edit. ******************* + *****************************************************************************************/ +#include "SkSLLexer.h" + +namespace SkSL { + +static int16_t transitions[127][281] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 44, 0, 0, 47, 0, + 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 0, 0, 32, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 44, 0, 0, 47, 0, + 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38, 35, 37, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 40, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 55, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 33, 33, 33, 0, 35, 35, 0, 38, 0, 49, 42, + 42, 45, 45, 45, 48, 48, 48, 49, 52, 52, 52, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 63, 0, 0, 0, 6, 0, 0, 0, 0, 0, 12, 0, 16, 15, 0, 0, 0, 0, 20, 0, 23, 0, 0, + 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 39, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 61, 0, 0, 64, 0, 66, 0, 68, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, 0, 278, 0, 0, 0, + }, + { + 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 35, 35, 0, 38, 0, 50, 46, + 43, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 54, 54, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 215, 10, 10, 10, 219, 10, 10, 10, 10, 224, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 89, 10, 10, 10, 10, 10, 10, + 10, 97, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 118, 10, 10, 10, 10, 10, 10, 125, 10, 10, 10, 10, 10, 10, 10, 10, + 134, 10, 10, 10, 10, 139, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 155, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 197, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 217, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 256, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 86, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 96, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 78, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 124, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 178, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 189, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 207, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 229, 10, 10, 10, 10, 10, 235, 10, 10, 10, 10, 240, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 115, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 127, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 165, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 198, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 222, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 129, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 35, + 35, 0, 38, 0, 50, 46, 43, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 54, + 54, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 88, 10, 10, + 10, 10, 10, 94, 10, 10, 10, 10, 99, 10, 10, 102, 10, 104, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 114, 10, 116, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 132, 10, 10, 10, 10, 137, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 164, 10, 10, 10, 10, 10, 10, 10, 10, 173, 10, 10, 10, 177, 10, 10, 10, + 10, 182, 10, 10, 10, 10, 10, 188, 10, 10, 10, 10, 10, 10, 10, 196, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 223, 10, 225, 10, 10, 228, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 245, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 260, 10, 10, 10, 10, 265, 10, 10, 10, 269, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 133, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 73, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 92, 93, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 117, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 149, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 226, 227, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 249, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 145, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 143, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 79, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 101, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 146, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 216, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 241, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 262, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 148, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 71, 71, 71, 71, 76, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 111, 10, 10, 10, + 10, 122, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 144, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 166, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 180, 10, 10, 10, 10, 10, 10, 10, 10, 10, 190, + 10, 192, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 206, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 221, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 238, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 248, 10, 10, 10, 10, 10, 10, 10, 10, 10, 258, 10, 10, 10, 10, 263, 10, 10, 10, + 267, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 90, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 214, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 154, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 120, 10, 10, 10, 10, 10, 10, 10, 10, 10, 130, 10, 10, 10, + 138, 135, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 201, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 255, 10, 10, 10, 259, 10, 10, 10, 10, 264, 10, 10, + 10, 10, 10, 10, 10, 272, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 163, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 168, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 252, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 170, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 107, 10, 10, 10, 105, 10, 10, 10, 10, 10, 10, 112, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 150, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 194, 10, 10, 10, 10, 10, 200, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 212, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 247, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 271, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 183, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 128, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 141, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 151, 10, + 10, 10, 160, 10, 157, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 171, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 193, 10, 10, 10, 10, 10, 199, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 250, 10, 10, 10, 254, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 270, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 186, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 147, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 162, 10, 10, 10, 10, 10, 10, 169, 10, 10, + 172, 10, 10, 10, 176, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 195, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 87, 10, 10, 10, 10, 10, 10, 10, 95, + 10, 10, 10, 10, 10, 10, 10, 103, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 126, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 142, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 174, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 187, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 205, 10, 10, 10, 10, + 10, 211, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 233, 10, 10, 10, 10, 10, 10, 10, 10, 10, 243, 10, 10, 10, 10, + 10, 10, 10, 251, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 266, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 213, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 98, 10, 10, 10, 10, 10, 10, 10, 10, 10, 108, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 123, 10, 10, 10, 10, 10, 10, 10, 131, 10, 10, + 10, 10, 136, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 175, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 191, 10, 10, 10, 10, 10, 203, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 218, 10, 220, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 231, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 242, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, + 71, 71, 71, 71, 77, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 106, 10, 110, + 109, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 121, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 140, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 153, 10, 10, 10, 10, 10, 159, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 179, 10, + 10, 10, 10, 10, 185, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 209, 10, + 10, 10, 10, 10, 10, 204, 10, 10, 10, 208, 10, 10, 10, 10, 10, 232, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 230, 10, 10, 10, 10, + 10, 236, 10, 10, 239, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 257, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 268, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 246, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 91, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 113, 10, + 10, 10, 10, 10, 119, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 152, + 10, 10, 10, 10, 10, 158, 10, 10, 10, 10, 10, 10, 10, 10, 167, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 184, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 210, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 234, 10, 10, 10, 10, 10, 10, 10, 10, 10, 244, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 253, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 181, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 261, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 75, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 161, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 237, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 53, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 156, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 202, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 273, 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 9, 0, 0, 0, 0, 0, 8, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 277, 0, 0, 0, 0, 0, + }, + { + 0, 279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, +}; + +static int16_t accepts[281] = { + -1, -1, 92, 92, 95, 66, 71, 95, 40, 39, 39, 56, 80, 61, 65, 88, 85, 42, 43, 54, 78, 52, + 50, 76, 49, 53, 51, 77, 90, 48, 1, -1, -1, 1, 55, -1, -1, 94, 93, 79, 2, 1, 1, -1, + -1, 1, -1, -1, 1, 2, -1, -1, 1, -1, 2, 2, 68, 91, 89, 73, 57, 81, 75, 69, 70, 72, + 74, 58, 82, 67, 95, 41, 41, 6, 41, 41, 41, 41, 41, 12, 46, 47, 60, 84, 64, 87, 39, 39, + 39, 39, 15, 39, 39, 39, 39, 34, 39, 39, 39, 13, 39, 39, 39, 39, 39, 39, 31, 39, 39, 23, + 39, 39, 39, 39, 16, 39, 39, 39, 39, 39, 39, 14, 39, 39, 39, 39, 39, 17, 10, 39, 39, 39, + 7, 39, 39, 39, 39, 4, 39, 39, 27, 39, 8, 39, 39, 39, 39, 26, 39, 5, 19, 39, 39, 21, + 39, 39, 39, 39, 39, 37, 39, 39, 24, 39, 39, 39, 39, 39, 39, 25, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 28, 39, 39, 20, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, + 39, 39, 39, 39, 29, 39, 39, 39, 39, 39, 33, 39, 39, 39, 18, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 35, 39, 39, 39, 39, 36, 39, 39, 39, 39, 11, + 39, 39, 39, 3, 39, 39, 39, 39, 39, 39, 22, 39, 39, 39, 39, 39, 39, 39, 32, 39, 39, 39, + 39, 9, 39, 39, 39, 39, 39, 39, 39, 30, 44, 59, 83, 63, 86, 45, 62, +}; + +Token Lexer::next() { + int startOffset = fOffset; + if (startOffset == fLength) { + return Token(Token::END_OF_FILE, startOffset, 0); + } + int offset = startOffset; + int state = 1; + Token::Kind lastAccept = Token::Kind::INVALID; + int lastAcceptEnd = startOffset + 1; + while (offset < fLength) { + state = transitions[(int)fText[offset]][state]; + ++offset; + if (!state) { + break; + } + if (accepts[state]) { + lastAccept = (Token::Kind)accepts[state]; + lastAcceptEnd = offset; + } + } + fOffset = lastAcceptEnd; + return Token(lastAccept, startOffset, lastAcceptEnd - startOffset); +} + +} // namespace diff --git a/src/sksl/SkSLLexer.h b/src/sksl/SkSLLexer.h new file mode 100644 index 0000000000..246be22b9e --- /dev/null +++ b/src/sksl/SkSLLexer.h @@ -0,0 +1,238 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/***************************************************************************************** + ******************** This file was generated by sksllex. Do not edit. ******************* + *****************************************************************************************/ +#ifndef SKSL_Lexer +#define SKSL_Lexer +#include <cstddef> +#include <cstdint> +namespace SkSL { + +struct Token { + enum Kind { +#undef END_OF_FILE + END_OF_FILE, +#undef FLOAT_LITERAL + FLOAT_LITERAL, +#undef INT_LITERAL + INT_LITERAL, +#undef TRUE_LITERAL + TRUE_LITERAL, +#undef FALSE_LITERAL + FALSE_LITERAL, +#undef IF + IF, +#undef STATIC_IF + STATIC_IF, +#undef ELSE + ELSE, +#undef FOR + FOR, +#undef WHILE + WHILE, +#undef DO + DO, +#undef SWITCH + SWITCH, +#undef STATIC_SWITCH + STATIC_SWITCH, +#undef CASE + CASE, +#undef DEFAULT + DEFAULT, +#undef BREAK + BREAK, +#undef CONTINUE + CONTINUE, +#undef DISCARD + DISCARD, +#undef RETURN + RETURN, +#undef IN + IN, +#undef OUT + OUT, +#undef INOUT + INOUT, +#undef UNIFORM + UNIFORM, +#undef CONST + CONST, +#undef LOWP + LOWP, +#undef MEDIUMP + MEDIUMP, +#undef HIGHP + HIGHP, +#undef FLAT + FLAT, +#undef NOPERSPECTIVE + NOPERSPECTIVE, +#undef READONLY + READONLY, +#undef WRITEONLY + WRITEONLY, +#undef COHERENT + COHERENT, +#undef VOLATILE + VOLATILE, +#undef RESTRICT + RESTRICT, +#undef BUFFER + BUFFER, +#undef HASSIDEEFFECTS + HASSIDEEFFECTS, +#undef STRUCT + STRUCT, +#undef LAYOUT + LAYOUT, +#undef PRECISION + PRECISION, +#undef IDENTIFIER + IDENTIFIER, +#undef DIRECTIVE + DIRECTIVE, +#undef SECTION + SECTION, +#undef LPAREN + LPAREN, +#undef RPAREN + RPAREN, +#undef LBRACE + LBRACE, +#undef RBRACE + RBRACE, +#undef LBRACKET + LBRACKET, +#undef RBRACKET + RBRACKET, +#undef DOT + DOT, +#undef COMMA + COMMA, +#undef PLUSPLUS + PLUSPLUS, +#undef MINUSMINUS + MINUSMINUS, +#undef PLUS + PLUS, +#undef MINUS + MINUS, +#undef STAR + STAR, +#undef SLASH + SLASH, +#undef PERCENT + PERCENT, +#undef SHL + SHL, +#undef SHR + SHR, +#undef BITWISEOR + BITWISEOR, +#undef BITWISEXOR + BITWISEXOR, +#undef BITWISEAND + BITWISEAND, +#undef BITWISENOT + BITWISENOT, +#undef LOGICALOR + LOGICALOR, +#undef LOGICALXOR + LOGICALXOR, +#undef LOGICALAND + LOGICALAND, +#undef LOGICALNOT + LOGICALNOT, +#undef QUESTION + QUESTION, +#undef COLON + COLON, +#undef EQ + EQ, +#undef EQEQ + EQEQ, +#undef NEQ + NEQ, +#undef GT + GT, +#undef LT + LT, +#undef GTEQ + GTEQ, +#undef LTEQ + LTEQ, +#undef PLUSEQ + PLUSEQ, +#undef MINUSEQ + MINUSEQ, +#undef STAREQ + STAREQ, +#undef SLASHEQ + SLASHEQ, +#undef PERCENTEQ + PERCENTEQ, +#undef SHLEQ + SHLEQ, +#undef SHREQ + SHREQ, +#undef BITWISEOREQ + BITWISEOREQ, +#undef BITWISEXOREQ + BITWISEXOREQ, +#undef BITWISEANDEQ + BITWISEANDEQ, +#undef LOGICALOREQ + LOGICALOREQ, +#undef LOGICALXOREQ + LOGICALXOREQ, +#undef LOGICALANDEQ + LOGICALANDEQ, +#undef SEMICOLON + SEMICOLON, +#undef ARROW + ARROW, +#undef COLONCOLON + COLONCOLON, +#undef WHITESPACE + WHITESPACE, +#undef LINE_COMMENT + LINE_COMMENT, +#undef BLOCK_COMMENT + BLOCK_COMMENT, +#undef INVALID + INVALID, + }; + + Token() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {} + + Token(Kind kind, int offset, int length) : fKind(kind), fOffset(offset), fLength(length) {} + + Kind fKind; + int fOffset; + int fLength; +}; + +class Lexer { +public: + void start(const char* text, size_t length) { + fText = text; + fLength = length; + fOffset = 0; + } + + Token next(); + +private: + const char* fText; + int fLength; + int fOffset; +}; + +} // namespace +#endif diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index f712b34e1a..d8ecc618bc 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -7,26 +7,6 @@ #include "stdio.h" #include "SkSLParser.h" -#include "SkSLToken.h" - -#define register -#include "disable_flex_warnings.h" -#include "lex.sksl.c" -static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 + - YY_FLEX_SUBMINOR_VERSION >= 20601, - "we require Flex 2.6.1 or better for security reasons"); -#undef register -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "lex.layout.h" #include "ast/SkSLASTBinaryExpression.h" #include "ast/SkSLASTBlock.h" #include "ast/SkSLASTBoolLiteral.h" @@ -83,7 +63,7 @@ public: bool checkValid() { if (fParser->fDepth > MAX_PARSE_DEPTH) { - fParser->error(fParser->peek().fPosition, String("exceeded max parse depth")); + fParser->error(fParser->peek(), String("exceeded max parse depth")); return false; } return true; @@ -93,20 +73,12 @@ private: Parser* fParser; }; -Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors) -: fPushback(Position(-1, -1), Token::INVALID_TOKEN, String()) +Parser::Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors) +: fText(text) +, fPushback(Token::INVALID, -1, -1) , fTypes(types) , fErrors(errors) { - sksllex_init(&fScanner); - layoutlex_init(&fLayoutScanner); - fBuffer = sksl_scan_string(text.c_str(), fScanner); - skslset_lineno(1, fScanner); -} - -Parser::~Parser() { - sksl_delete_buffer(fBuffer, fScanner); - sksllex_destroy(fScanner); - layoutlex_destroy(fLayoutScanner); + fLexer.start(text, length); } /* (precision | directive | section | declaration)* END_OF_FILE */ @@ -148,53 +120,39 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } } -Token Parser::nextRawToken(bool needText) { - if (fPushback.fKind != Token::INVALID_TOKEN) { - Token result(std::move(fPushback)); - fPushback.fKind = Token::INVALID_TOKEN; - fPushback.fText.clear(); +Token Parser::nextRawToken() { + if (fPushback.fKind != Token::INVALID) { + Token result = fPushback; + fPushback.fKind = Token::INVALID; return result; } - Token::Kind kind = (Token::Kind) sksllex(fScanner); - if (!needText) { - switch (kind) { - case Token::Kind::DIRECTIVE: // fall through - case Token::Kind::IDENTIFIER: // fall through - case Token::Kind::INT_LITERAL: // fall through - case Token::Kind::FLOAT_LITERAL: // fall through - case Token::Kind::SECTION: - needText = true; - default: - break; - } - } - static String unavailable("<unavailable>"); - return Token(Position(skslget_lineno(fScanner), -1), kind, - needText ? String(skslget_text(fScanner)) : unavailable); + Token result = fLexer.next(); + return result; } Token Parser::nextToken() { - Token token; - do { - token = this->nextRawToken(false); - } while (token.fKind == Token::WHITESPACE); + Token token = this->nextRawToken(); + while (token.fKind == Token::WHITESPACE || token.fKind == Token::LINE_COMMENT || + token.fKind == Token::BLOCK_COMMENT) { + token = this->nextRawToken(); + } return token; } void Parser::pushback(Token t) { - ASSERT(fPushback.fKind == Token::INVALID_TOKEN); + ASSERT(fPushback.fKind == Token::INVALID); fPushback = std::move(t); } Token Parser::peek() { - if (fPushback.fKind == Token::INVALID_TOKEN) { + if (fPushback.fKind == Token::INVALID) { fPushback = this->nextToken(); } return fPushback; } bool Parser::checkNext(Token::Kind kind, Token* result) { - if (fPushback.fKind != Token::INVALID_TOKEN && fPushback.fKind != kind) { + if (fPushback.fKind != Token::INVALID && fPushback.fKind != kind) { return false; } Token next = this->nextToken(); @@ -216,25 +174,25 @@ bool Parser::expect(Token::Kind kind, const char* expected, Token* result) { } return true; } else { - if (next.fText.size()) { - this->error(next.fPosition, "expected " + String(expected) + ", but found '" + - next.fText + "'"); - } else { - this->error(next.fPosition, "parse error, recompile in debug mode for details"); - } + this->error(next, "expected " + String(expected) + ", but found '" + + this->text(next) + "'"); return false; } } -void Parser::error(Position p, const char* msg) { - this->error(p, String(msg)); +StringFragment Parser::text(Token token) { + return StringFragment(fText + token.fOffset, token.fLength); +} + +void Parser::error(Token token, String msg) { + this->error(token.fOffset, msg); } -void Parser::error(Position p, String msg) { - fErrors.error(p, msg); +void Parser::error(int offset, String msg) { + fErrors.error(offset, msg); } -bool Parser::isType(const String& name) { +bool Parser::isType(StringFragment name) { return nullptr != fTypes[name]; } @@ -256,8 +214,8 @@ std::unique_ptr<ASTDeclaration> Parser::precision() { result = Modifiers::kHighp_Flag; break; default: - this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + - p.fText + "'"); + this->error(p, "expected 'lowp', 'mediump', or 'highp', but found '" + + this->text(p) + "'"); return nullptr; } // FIXME handle the type @@ -265,7 +223,7 @@ std::unique_ptr<ASTDeclaration> Parser::precision() { return nullptr; } this->expect(Token::SEMICOLON, "';'"); - return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result)); + return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fOffset, result)); } /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | @@ -275,16 +233,18 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { return nullptr; } - if (start.fText == "#version") { + StringFragment text = this->text(start); + if (text == "#version") { this->expect(Token::INT_LITERAL, "a version number"); Token next = this->peek(); - if (next.fText == "es" || next.fText == "compatibility") { + StringFragment nextText = this->text(next); + if (nextText == "es" || nextText == "compatibility") { this->nextToken(); } // version is ignored for now; it will eventually become an error when we stop pretending // to be GLSL return nullptr; - } else if (start.fText == "#extension") { + } else if (text == "#extension") { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { return nullptr; @@ -296,10 +256,10 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { if (!this->expect(Token::IDENTIFIER, "an identifier")) { return nullptr; } - return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition, - std::move(name.fText))); + return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fOffset, + String(this->text(name)))); } else { - this->error(start.fPosition, "unsupported directive '" + start.fText + "'"); + this->error(start, "unsupported directive '" + this->text(start) + "'"); return nullptr; } } @@ -318,7 +278,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) { return nullptr; } - argument = argToken.fText; + argument = this->text(argToken); if (!this->expect(Token::RPAREN, "')'")) { return nullptr; } @@ -329,7 +289,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { String text; int level = 1; for (;;) { - Token next = this->nextRawToken(true); + Token next = this->nextRawToken(); switch (next.fKind) { case Token::LBRACE: ++level; @@ -338,7 +298,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { --level; break; case Token::END_OF_FILE: - this->error(start.fPosition, "reached end of file while parsing section"); + this->error(start, "reached end of file while parsing section"); return nullptr; default: break; @@ -346,10 +306,13 @@ std::unique_ptr<ASTDeclaration> Parser::section() { if (!level) { break; } - text += next.fText; + text += this->text(next); } - return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition, - String(start.fText.c_str() + 1), + StringFragment name = this->text(start); + ++name.fChars; + --name.fLength; + return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fOffset, + String(name), argument, text)); } @@ -359,7 +322,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() { std::unique_ptr<ASTDeclaration> Parser::declaration() { Modifiers modifiers = this->modifiers(); Token lookahead = this->peek(); - if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) { + if (lookahead.fKind == Token::IDENTIFIER && !this->isType(this->text(lookahead))) { // we have an identifier that's not a type, could be the start of an interface block return this->interfaceBlock(modifiers); } @@ -403,14 +366,14 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() { return nullptr; } } - return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, + return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fOffset, modifiers, std::move(type), - std::move(name.fText), + this->text(name), std::move(parameters), std::move(body))); } else { - return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText)); + return this->varDeclarationEnd(modifiers, std::move(type), this->text(name)); } } @@ -425,7 +388,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() { if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { return nullptr; } - return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText)); + return this->varDeclarationEnd(modifiers, std::move(type), this->text(name)); } /* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */ @@ -450,7 +413,7 @@ 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->fPosition, "array size in struct field must be a constant"); + this->error(decl->fOffset, "array size in struct field must be a constant"); return nullptr; } uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue; @@ -460,15 +423,16 @@ std::unique_ptr<ASTType> Parser::structDeclaration() { } fields.push_back(Type::Field(decl->fModifiers, var.fName, type)); if (var.fValue) { - this->error(decl->fPosition, "initializers are not permitted on struct fields"); + this->error(decl->fOffset, "initializers are not permitted on struct fields"); } } } if (!this->expect(Token::RBRACE, "'}'")) { return nullptr; } - fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields))); - return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText, + fTypes.add(this->text(name), std::unique_ptr<Type>(new Type(name.fOffset, this->text(name), + fields))); + return std::unique_ptr<ASTType>(new ASTType(name.fOffset, this->text(name), ASTType::kStruct_Kind, std::vector<int>())); } @@ -482,11 +446,11 @@ 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), - std::move(name.fText)); + this->text(name)); if (result) { for (const auto& var : result->fVars) { if (var.fValue) { - this->error(var.fValue->fPosition, + this->error(var.fValue->fOffset, "struct variables cannot be initialized"); } } @@ -501,7 +465,7 @@ 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, - String name) { + StringFragment name) { std::vector<ASTVarDeclaration> vars; std::vector<std::unique_ptr<ASTExpression>> currentVarSizes; while (this->checkNext(Token::LBRACKET)) { @@ -525,7 +489,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods, return nullptr; } } - vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value)); + vars.emplace_back(name, std::move(currentVarSizes), std::move(value)); while (this->checkNext(Token::COMMA)) { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { @@ -553,7 +517,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods, return nullptr; } } - vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value)); + vars.emplace_back(this->text(name), std::move(currentVarSizes), std::move(value)); } if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; @@ -580,14 +544,13 @@ std::unique_ptr<ASTParameter> Parser::parameter() { if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) { return nullptr; } - sizes.push_back(SkSL::stoi(sizeToken.fText)); + sizes.push_back(SkSL::stoi(this->text(sizeToken))); if (!this->expect(Token::RBRACKET, "']'")) { return nullptr; } } - return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers, - std::move(type), name.fText, - std::move(sizes))); + return std::unique_ptr<ASTParameter>(new ASTParameter(name.fOffset, modifiers, std::move(type), + this->text(name), std::move(sizes))); } /** (EQ INT_LITERAL)? */ @@ -597,7 +560,7 @@ int Parser::layoutInt() { } Token resultToken; if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) { - return SkSL::stoi(resultToken.fText); + return SkSL::stoi(this->text(resultToken)); } return -1; } @@ -607,13 +570,13 @@ String Parser::layoutCode() { if (!this->expect(Token::EQ, "'='")) { return ""; } - Token start = this->nextRawToken(true); + Token start = this->nextRawToken(); this->pushback(start); String code; int level = 1; bool done = false; while (!done) { - Token next = this->nextRawToken(true); + Token next = this->nextRawToken(); switch (next.fKind) { case Token::LPAREN: ++level; @@ -627,7 +590,7 @@ String Parser::layoutCode() { } break; case Token::END_OF_FILE: - this->error(start.fPosition, "reached end of file while parsing layout"); + this->error(start, "reached end of file while parsing layout"); return nullptr; default: break; @@ -639,7 +602,7 @@ String Parser::layoutCode() { this->pushback(std::move(next)); } else { - code += next.fText; + code += this->text(next); } } return code; @@ -651,10 +614,10 @@ Layout::Key Parser::layoutKey() { this->expect(Token::EQ, "'='"); Token key; if (this->expect(Token::IDENTIFIER, "an identifer", &key)) { - if (key.fText == "identity") { + if (this->text(key) == "identity") { return Layout::kIdentity_Key; } else { - this->error(key.fPosition, "unsupported layout key"); + this->error(key, "unsupported layout key"); } } } @@ -688,84 +651,84 @@ Layout Parser::layout() { } for (;;) { Token t = this->nextToken(); - YY_BUFFER_STATE buffer; - buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner); - int token = layoutlex(fLayoutScanner); - layout_delete_buffer(buffer, fLayoutScanner); - if (token != Token::INVALID_TOKEN) { + String text = this->text(t); + fLayoutLexer.start(text.c_str(), text.size()); + int token = fLayoutLexer.next().fKind; + if (token != LayoutToken::INVALID) { switch (token) { - case Token::LOCATION: + case LayoutToken::LOCATION: location = this->layoutInt(); break; - case Token::OFFSET: + case LayoutToken::OFFSET: offset = this->layoutInt(); break; - case Token::BINDING: + case LayoutToken::BINDING: binding = this->layoutInt(); break; - case Token::INDEX: + case LayoutToken::INDEX: index = this->layoutInt(); break; - case Token::SET: + case LayoutToken::SET: set = this->layoutInt(); break; - case Token::BUILTIN: + case LayoutToken::BUILTIN: builtin = this->layoutInt(); break; - case Token::INPUT_ATTACHMENT_INDEX: + case LayoutToken::INPUT_ATTACHMENT_INDEX: inputAttachmentIndex = this->layoutInt(); break; - case Token::ORIGIN_UPPER_LEFT: + case LayoutToken::ORIGIN_UPPER_LEFT: originUpperLeft = true; break; - case Token::OVERRIDE_COVERAGE: + case LayoutToken::OVERRIDE_COVERAGE: overrideCoverage = true; break; - case Token::BLEND_SUPPORT_ALL_EQUATIONS: + case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS: blendSupportAllEquations = true; break; - case Token::PUSH_CONSTANT: + case LayoutToken::PUSH_CONSTANT: pushConstant = true; break; - case Token::POINTS: + case LayoutToken::POINTS: primitive = Layout::kPoints_Primitive; break; - case Token::LINES: + case LayoutToken::LINES: primitive = Layout::kLines_Primitive; break; - case Token::LINE_STRIP: + case LayoutToken::LINE_STRIP: primitive = Layout::kLineStrip_Primitive; break; - case Token::LINES_ADJACENCY: + case LayoutToken::LINES_ADJACENCY: primitive = Layout::kLinesAdjacency_Primitive; break; - case Token::TRIANGLES: + case LayoutToken::TRIANGLES: primitive = Layout::kTriangles_Primitive; break; - case Token::TRIANGLE_STRIP: + case LayoutToken::TRIANGLE_STRIP: primitive = Layout::kTriangleStrip_Primitive; break; - case Token::TRIANGLES_ADJACENCY: + case LayoutToken::TRIANGLES_ADJACENCY: primitive = Layout::kTrianglesAdjacency_Primitive; break; - case Token::MAX_VERTICES: + case LayoutToken::MAX_VERTICES: maxVertices = this->layoutInt(); break; - case Token::INVOCATIONS: + case LayoutToken::INVOCATIONS: invocations = this->layoutInt(); break; - case Token::WHEN: + case LayoutToken::WHEN: when = this->layoutCode(); break; - case Token::KEY: + case LayoutToken::KEY: key = this->layoutKey(); break; + default: + ASSERT(false); } - } else if (Layout::ReadFormat(t.fText, &format)) { + } else if (Layout::ReadFormat(this->text(t), &format)) { // AST::ReadFormat stored the result in 'format'. } else { - this->error(t.fPosition, ("'" + t.fText + - "' is not a valid layout qualifier").c_str()); + this->error(t, ("'" + this->text(t) + "' is not a valid layout qualifier").c_str()); } if (this->checkNext(Token::RPAREN)) { break; @@ -899,7 +862,7 @@ std::unique_ptr<ASTStatement> Parser::statement() { return this->block(); case Token::SEMICOLON: this->nextToken(); - return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition, + return std::unique_ptr<ASTStatement>(new ASTBlock(start.fOffset, std::vector<std::unique_ptr<ASTStatement>>())); case Token::CONST: // fall through case Token::HIGHP: // fall through @@ -912,7 +875,7 @@ std::unique_ptr<ASTStatement> Parser::statement() { return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl))); } case Token::IDENTIFIER: - if (this->isType(start.fText)) { + if (this->isType(this->text(start))) { auto decl = this->varDeclarations(); if (!decl) { return nullptr; @@ -932,8 +895,8 @@ std::unique_ptr<ASTType> Parser::type() { if (!this->expect(Token::IDENTIFIER, "a type", &type)) { return nullptr; } - if (!this->isType(type.fText)) { - this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str()); + if (!this->isType(this->text(type))) { + this->error(type, ("no type named '" + this->text(type) + "'").c_str()); return nullptr; } std::vector<int> sizes; @@ -950,7 +913,7 @@ std::unique_ptr<ASTType> Parser::type() { } this->expect(Token::RBRACKET, "']'"); } - return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText), + return std::unique_ptr<ASTType>(new ASTType(type.fOffset, this->text(type), ASTType::kIdentifier_Kind, sizes)); } @@ -964,7 +927,7 @@ 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.fPosition, "no type named '" + name.fText + "'"); + this->error(name, "no type named '" + this->text(name) + "'"); return nullptr; } this->nextToken(); @@ -978,8 +941,9 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { } this->nextToken(); std::vector<std::unique_ptr<ASTExpression>> sizes; - Token instanceName; - if (this->checkNext(Token::IDENTIFIER, &instanceName)) { + StringFragment instanceName; + Token instanceNameToken; + if (this->checkNext(Token::IDENTIFIER, &instanceNameToken)) { while (this->checkNext(Token::LBRACKET)) { if (this->peek().fKind != Token::RBRACKET) { std::unique_ptr<ASTExpression> size = this->expression(); @@ -992,12 +956,13 @@ 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.fPosition, mods, - std::move(name.fText), + return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fOffset, mods, + this->text(name), std::move(decls), - std::move(instanceName.fText), + instanceName, std::move(sizes))); } @@ -1029,7 +994,7 @@ std::unique_ptr<ASTIfStatement> Parser::ifStatement() { return nullptr; } } - return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, + return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fOffset, isStatic, std::move(test), std::move(ifTrue), @@ -1062,7 +1027,7 @@ std::unique_ptr<ASTDoStatement> Parser::doStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition, + return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fOffset, std::move(statement), std::move(test))); } @@ -1087,7 +1052,7 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() { if (!statement) { return nullptr; } - return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition, + return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fOffset, std::move(test), std::move(statement))); } @@ -1114,7 +1079,7 @@ std::unique_ptr<ASTSwitchCase> Parser::switchCase() { } statements.push_back(std::move(s)); } - return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value), + return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fOffset, std::move(value), std::move(statements))); } @@ -1162,13 +1127,13 @@ std::unique_ptr<ASTStatement> Parser::switchStatement() { } statements.push_back(std::move(s)); } - cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr, + cases.emplace_back(new ASTSwitchCase(defaultStart.fOffset, nullptr, std::move(statements))); } if (!this->expect(Token::RBRACE, "'}'")) { return nullptr; } - return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition, + return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fOffset, isStatic, std::move(value), std::move(cases))); @@ -1200,7 +1165,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() { break; } case Token::IDENTIFIER: { - if (this->isType(nextToken.fText)) { + if (this->isType(this->text(nextToken))) { std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations(); if (!vd) { return nullptr; @@ -1237,7 +1202,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() { if (!statement) { return nullptr; } - return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition, + return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fOffset, std::move(initializer), std::move(test), std::move(next), std::move(statement))); @@ -1259,7 +1224,7 @@ std::unique_ptr<ASTReturnStatement> Parser::returnStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition, + return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fOffset, std::move(expression))); } @@ -1272,7 +1237,7 @@ std::unique_ptr<ASTBreakStatement> Parser::breakStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition)); + return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fOffset)); } /* CONTINUE SEMICOLON */ @@ -1284,7 +1249,7 @@ std::unique_ptr<ASTContinueStatement> Parser::continueStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition)); + return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fOffset)); } /* DISCARD SEMICOLON */ @@ -1296,7 +1261,7 @@ std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition)); + return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fOffset)); } /* LBRACE statement* RBRACE */ @@ -1314,10 +1279,10 @@ std::unique_ptr<ASTBlock> Parser::block() { switch (this->peek().fKind) { case Token::RBRACE: this->nextToken(); - return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition, + return std::unique_ptr<ASTBlock>(new ASTBlock(start.fOffset, std::move(statements))); case Token::END_OF_FILE: - this->error(this->peek().fPosition, "expected '}', but found end of file"); + this->error(this->peek(), "expected '}', but found end of file"); return nullptr; default: { std::unique_ptr<ASTStatement> statement = this->statement(); @@ -1714,7 +1679,7 @@ 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.fPosition)); + return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fOffset)); } std::unique_ptr<ASTExpression> e = this->expression(); if (!e) { @@ -1724,10 +1689,10 @@ std::unique_ptr<ASTSuffix> Parser::suffix() { return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e))); } case Token::DOT: { - Position pos = this->peek().fPosition; - String text; + int offset = this->peek().fOffset; + StringFragment text; if (this->identifier(&text)) { - return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text))); + return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(offset, std::move(text))); } return nullptr; } @@ -1746,17 +1711,17 @@ std::unique_ptr<ASTSuffix> Parser::suffix() { } } this->expect(Token::RPAREN, "')' to complete function parameters"); - return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition, + return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fOffset, std::move(parameters))); } case Token::PLUSPLUS: - return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, + return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset, ASTSuffix::kPostIncrement_Kind)); case Token::MINUSMINUS: - return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, + return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset, ASTSuffix::kPostDecrement_Kind)); default: { - this->error(next.fPosition, "expected expression suffix, but found '" + next.fText + + this->error(next, "expected expression suffix, but found '" + this->text(next) + "'\n"); return nullptr; } @@ -1769,23 +1734,23 @@ std::unique_ptr<ASTExpression> Parser::term() { Token t = this->peek(); switch (t.fKind) { case Token::IDENTIFIER: { - String text; + StringFragment text; if (this->identifier(&text)) { - result.reset(new ASTIdentifier(t.fPosition, std::move(text))); + result.reset(new ASTIdentifier(t.fOffset, std::move(text))); } break; } case Token::INT_LITERAL: { int64_t i; if (this->intLiteral(&i)) { - result.reset(new ASTIntLiteral(t.fPosition, i)); + result.reset(new ASTIntLiteral(t.fOffset, i)); } break; } case Token::FLOAT_LITERAL: { double f; if (this->floatLiteral(&f)) { - result.reset(new ASTFloatLiteral(t.fPosition, f)); + result.reset(new ASTFloatLiteral(t.fOffset, f)); } break; } @@ -1793,7 +1758,7 @@ std::unique_ptr<ASTExpression> Parser::term() { case Token::FALSE_LITERAL: { bool b; if (this->boolLiteral(&b)) { - result.reset(new ASTBoolLiteral(t.fPosition, b)); + result.reset(new ASTBoolLiteral(t.fOffset, b)); } break; } @@ -1807,7 +1772,7 @@ std::unique_ptr<ASTExpression> Parser::term() { } default: this->nextToken(); - this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n"); + this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'\n"); result = nullptr; } return result; @@ -1817,7 +1782,7 @@ 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(t.fText); + *dest = SkSL::stol(this->text(t)); return true; } return false; @@ -1827,7 +1792,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(t.fText); + *dest = SkSL::stod(this->text(t)); return true; } return false; @@ -1844,16 +1809,16 @@ bool Parser::boolLiteral(bool* dest) { *dest = false; return true; default: - this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n"); + this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'\n"); return false; } } /* IDENTIFIER */ -bool Parser::identifier(String* dest) { +bool Parser::identifier(StringFragment* dest) { Token t; if (this->expect(Token::IDENTIFIER, "identifier", &t)) { - *dest = std::move(t.fText); + *dest = this->text(t); return true; } return false; diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index 4edd8e4e02..5391f6c2ee 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -14,7 +14,8 @@ #include <unordered_set> #include "SkSLErrorReporter.h" #include "ir/SkSLLayout.h" -#include "SkSLToken.h" +#include "SkSLLexer.h" +#include "SkSLLayoutLexer.h" struct yy_buffer_state; #define YY_TYPEDEF_YY_BUFFER_STATE @@ -51,9 +52,7 @@ class SymbolTable; */ class Parser { public: - Parser(String text, SymbolTable& types, ErrorReporter& errors); - - ~Parser(); + Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors); /** * Consumes a complete .sksl file and produces a list of declarations. Errors are reported via @@ -62,13 +61,15 @@ 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. If needText is - * false, the token's text is only filled in if it is a token with variable text (identifiers, - * numbers, etc.). + * Return the next token, including whitespace tokens, from the parse stream. */ - Token nextRawToken(bool needText); + Token nextRawToken(); /** * Return the next non-whitespace token from the parse stream. @@ -103,15 +104,15 @@ 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(Position p, const char* msg); - void error(Position p, String msg); - + void error(Token token, String msg); + void error(int offset, String msg); /** * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will * always return true. */ - bool isType(const String& name); + bool isType(StringFragment name); // these functions parse individual grammar rules from the current parse position; you probably // don't need to call any of these outside of the parser. The function declarations in the .cpp @@ -133,7 +134,7 @@ private: std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers, std::unique_ptr<ASTType> type, - String name); + StringFragment name); std::unique_ptr<ASTParameter> parameter(); @@ -223,10 +224,11 @@ private: bool boolLiteral(bool* dest); - bool identifier(String* dest); + bool identifier(StringFragment* dest); - void* fScanner; - void* fLayoutScanner; + const char* fText; + Lexer fLexer; + LayoutLexer fLayoutLexer; YY_BUFFER_STATE fBuffer; // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the // stack on pathological inputs diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index d367df93cb..7ae3252fe8 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -850,8 +850,7 @@ void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, OutputSt this->writeWord(word1, out); } -void SPIRVCodeGenerator::writeString(const char* string, OutputStream& out) { - size_t length = strlen(string); +void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputStream& out) { out.write(string, length); switch (length % 4) { case 1: @@ -868,28 +867,25 @@ void SPIRVCodeGenerator::writeString(const char* string, OutputStream& 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, StringFragment string, OutputStream& out) { + this->writeOpCode(opCode, 1 + (string.fLength + 4) / 4, out); + this->writeString(string.fChars, string.fLength, out); } -void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, +void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string, OutputStream& out) { - int32_t length = (int32_t) strlen(string); - this->writeOpCode(opCode, 2 + (length + 4) / 4, out); + this->writeOpCode(opCode, 2 + (string.fLength + 4) / 4, out); this->writeWord(word1, out); - this->writeString(string, out); + this->writeString(string.fChars, string.fLength, out); } void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, - const char* string, OutputStream& out) { - int32_t length = (int32_t) strlen(string); - this->writeOpCode(opCode, 3 + (length + 4) / 4, out); + StringFragment string, OutputStream& out) { + this->writeOpCode(opCode, 3 + (string.fLength + 4) / 4, out); this->writeWord(word1, out); this->writeWord(word2, out); - this->writeString(string, out); + this->writeString(string.fChars, string.fLength, out); } void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, @@ -1003,12 +999,12 @@ 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.fPosition, + fErrors.error(type.fOffset, "offset of field '" + type.fields()[i].fName + "' must be at " "least " + to_string((int) offset)); } if (fieldLayout.fOffset % alignment) { - fErrors.error(type.fPosition, + fErrors.error(type.fOffset, "offset of field '" + type.fields()[i].fName + "' must be a multiple" " of " + to_string((int) alignment)); } @@ -1019,8 +1015,7 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor offset += alignment - mod; } } - this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(), - fNameBuffer); + this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName, fNameBuffer); this->writeLayout(fieldLayout, resultId, i); if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset, @@ -1081,7 +1076,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) break; case Type::kArray_Kind: { if (type.columns() > 0) { - IntLiteral count(fContext, Position(), type.columns()); + IntLiteral count(fContext, -1, type.columns()); this->writeInstruction(SpvOpTypeArray, result, this->getType(type.componentType(), layout), this->writeIntLiteral(count), fConstantBuffer); @@ -1331,9 +1326,9 @@ 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, Position(), 0.0)); - args.emplace_back(new FloatLiteral(fContext, Position(), 0.0)); - Constructor ctor(Position(), *fContext.fFloat2_Type, std::move(args)); + args.emplace_back(new FloatLiteral(fContext, -1, 0.0)); + args.emplace_back(new FloatLiteral(fContext, -1, 0.0)); + Constructor ctor(-1, *fContext.fFloat2_Type, std::move(args)); SpvId coords = this->writeConstantVector(ctor); if (1 == c.fArguments.size()) { this->writeInstruction(SpvOpImageRead, @@ -1566,7 +1561,7 @@ SpvId SPIRVCodeGenerator::writeUIntConstructor(const Constructor& c, OutputStrea void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, OutputStream& out) { - FloatLiteral zero(fContext, Position(), 0); + FloatLiteral zero(fContext, -1, 0); SpvId zeroId = this->writeFloatLiteral(zero); std::vector<SpvId> columnIds; for (int column = 0; column < type.columns(); column++) { @@ -1603,10 +1598,10 @@ void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcTyp 1)); SpvId zeroId; if (dstType.componentType() == *fContext.fFloat_Type) { - FloatLiteral zero(fContext, Position(), 0.0); + FloatLiteral zero(fContext, -1, 0.0); zeroId = this->writeFloatLiteral(zero); } else if (dstType.componentType() == *fContext.fInt_Type) { - IntLiteral zero(fContext, Position(), 0); + IntLiteral zero(fContext, -1, 0); zeroId = this->writeIntLiteral(zero); } else { ABORT("unsupported matrix component type"); @@ -1864,7 +1859,7 @@ 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, Position(), fieldExpr.fFieldIndex); + IntLiteral index(fContext, -1, fieldExpr.fFieldIndex); chain.push_back(this->writeIntLiteral(index)); break; } @@ -2010,7 +2005,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, Position(), swizzle.fComponents[0]); + IntLiteral index(fContext, -1, swizzle.fComponents[0]); SpvId member = this->nextId(); this->writeInstruction(SpvOpAccessChain, this->getPointerType(swizzle.fType, @@ -2064,20 +2059,19 @@ 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(), String(SKSL_RTHEIGHT_NAME), - fContext.fFloat_Type.get()); - String name("sksl_synthetic_uniforms"); - Type intfStruct(Position(), name, fields); + fields.emplace_back(Modifiers(), SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get()); + StringFragment name("sksl_synthetic_uniforms"); + Type intfStruct(-1, name, fields); Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1, -1, "", Layout::kNo_Key); - Variable* intfVar = new Variable(Position(), + Variable* intfVar = new Variable(-1, Modifiers(layout, Modifiers::kUniform_Flag), name, intfStruct, Variable::kGlobal_Storage); fSynthetics.takeOwnership(intfVar); - InterfaceBlock intf(Position(), intfVar, name, String(""), + InterfaceBlock intf(-1, intfVar, name, String(""), std::vector<std::unique_ptr<Expression>>(), st); fRTHeightStructId = this->writeInterfaceBlock(intf); fRTHeightFieldIndex = 0; @@ -2087,7 +2081,7 @@ SpvId 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, Position(), fRTHeightFieldIndex); + IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex); SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); SpvId heightPtr = this->nextId(); this->writeOpCode(SpvOpAccessChain, 5, out); @@ -2104,9 +2098,9 @@ SpvId 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, Position(), 0.0); + FloatLiteral zero(fContext, -1, 0.0); SpvId zeroId = writeFloatLiteral(zero); - FloatLiteral one(fContext, Position(), 1.0); + FloatLiteral one(fContext, -1, 1.0); SpvId oneId = writeFloatLiteral(one); SpvId flipped = this->nextId(); this->writeOpCode(SpvOpCompositeConstruct, 7, out); @@ -2509,7 +2503,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) { ASSERT(a.fOperator == Token::LOGICALAND); - BoolLiteral falseLiteral(fContext, Position(), false); + BoolLiteral falseLiteral(fContext, -1, false); SpvId falseConstant = this->writeBoolLiteral(falseLiteral); SpvId lhs = this->writeExpression(*a.fLeft, out); SpvId rhsLabel = this->nextId(); @@ -2530,7 +2524,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) { ASSERT(o.fOperator == Token::LOGICALOR); - BoolLiteral trueLiteral(fContext, Position(), true); + BoolLiteral trueLiteral(fContext, -1, true); SpvId trueConstant = this->writeBoolLiteral(trueLiteral); SpvId lhs = this->writeExpression(*o.fLeft, out); SpvId rhsLabel = this->nextId(); @@ -2584,10 +2578,10 @@ 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, Position(), 1)); + return std::unique_ptr<Expression>(new IntLiteral(context, -1, 1)); } else if (type == *context.fFloat_Type) { - return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0)); + return std::unique_ptr<Expression>(new FloatLiteral(context, -1, 1.0)); } else { ABORT("math is unsupported on type '%s'", type.name().c_str()); } @@ -2747,7 +2741,7 @@ SpvId 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.c_str(), fNameBuffer); + this->writeInstruction(SpvOpName, result, f.fName, fNameBuffer); for (size_t i = 0; i < f.fParameters.size(); i++) { SpvId id = this->nextId(); fVariableMap[f.fParameters[i]] = id; @@ -2844,8 +2838,8 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { std::vector<Type::Field> fields = type->fields(); fRTHeightStructId = result; fRTHeightFieldIndex = fields.size(); - fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); - type = new Type(type->fPosition, type->name(), fields); + fields.emplace_back(Modifiers(), StringFragment(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); + type = new Type(type->fOffset, type->name(), fields); } SpvId typeId = this->getType(*type, layout); if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) { @@ -2922,7 +2916,7 @@ 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.c_str(), fNameBuffer); + this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer); this->writePrecisionModifier(var->fModifiers, id); if (varDecl.fValue) { ASSERT(!fCurrentBlock); @@ -2958,7 +2952,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.c_str(), fNameBuffer); + this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer); if (varDecl.fValue) { SpvId value = this->writeExpression(*varDecl.fValue, out); this->writeInstruction(SpvOpStore, id, value, out); @@ -3086,7 +3080,7 @@ 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.fPosition, "internal error: while loop support has been disabled in SPIR-V, " + fErrors.error(w.fOffset, "internal error: while loop support has been disabled in SPIR-V, " "see SkSLSPIRVCodeGenerator.cpp for details"); SpvId header = this->nextId(); @@ -3118,7 +3112,7 @@ 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.fPosition, "internal error: do loop support has been disabled in SPIR-V, see " + fErrors.error(d.fOffset, "internal error: do loop support has been disabled in SPIR-V, see " "SkSLSPIRVCodeGenerator.cpp for details"); SpvId header = this->nextId(); @@ -3268,7 +3262,7 @@ 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 + (strlen(main->fName.c_str()) + 4) / 4) + + this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->fName.fLength + 4) / 4) + (int32_t) interfaceVars.size(), out); switch (program.fKind) { case Program::kVertex_Kind: @@ -3285,7 +3279,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& } SpvId entryPoint = fFunctionMap[main]; this->writeWord(entryPoint, out); - this->writeString(main->fName.c_str(), out); + this->writeString(main->fName.fChars, main->fName.fLength, out); for (int var : interfaceVars) { this->writeWord(var, out); } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index a532c9a3bc..eb6ec40a3f 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, OutputStream& out); + void writeString(const char* string, size_t length, OutputStream& out); void writeLabel(SpvId id, OutputStream& out); void writeInstruction(SpvOp_ opCode, OutputStream& out); - void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out); + void writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out); void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out); - void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out); + void writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string, OutputStream& out); - void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string, + void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, StringFragment string, OutputStream& out); void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out); diff --git a/src/sksl/SkSLSectionAndParameterHelper.h b/src/sksl/SkSLSectionAndParameterHelper.h index f70b82c439..fccfff473b 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->fPosition, + errors.error(s->fOffset, ("section '@" + s->fName + "' requires one parameter").c_str()); } } else if (s->fArgument.size()) { - errors.error(s->fPosition, + errors.error(s->fOffset, ("section '@" + s->fName + "' has no parameters").c_str()); } } else { - errors.error(s->fPosition, + errors.error(s->fOffset, ("unsupported section '@" + s->fName + "'").c_str()); } if (!SectionPermitsDuplicates(s->fName.c_str()) && fSections.find(s->fName) != fSections.end()) { - errors.error(s->fPosition, + errors.error(s->fOffset, ("duplicate section '@" + s->fName + "'").c_str()); } fSections[s->fName].push_back(s); diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp index ac6d7f85c1..2bbb772672 100644 --- a/src/sksl/SkSLString.cpp +++ b/src/sksl/SkSLString.cpp @@ -77,6 +77,32 @@ 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()); } @@ -107,6 +133,28 @@ 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 !strncmp(fChars, s, fLength); +} + +bool StringFragment::operator!=(const char* s) const { + return strncmp(fChars, s, fLength); +} + String to_string(int32_t value) { return SkSL::String::printf("%d", value); } diff --git a/src/sksl/SkSLString.h b/src/sksl/SkSLString.h index 93bd7a5773..9cfdce4768 100644 --- a/src/sksl/SkSLString.h +++ b/src/sksl/SkSLString.h @@ -8,6 +8,8 @@ #ifndef SKSL_STRING #define SKSL_STRING +#include <cstring> + #define SKSL_USE_STD_STRING #include <stdarg.h> @@ -22,6 +24,33 @@ namespace SkSL { +// Represents a (not necessarily null-terminated) slice of a string. +struct StringFragment { + StringFragment() + : fChars(nullptr) + , fLength(0) {} + + StringFragment(const char* chars) + : fChars(chars) + , fLength(strlen(chars)) {} + + StringFragment(const char* chars, size_t length) + : fChars(chars) + , fLength(length) {} + + char operator[](size_t idx) const { + return fChars[idx]; + } + + bool operator==(const char* s) const; + bool operator!=(const char* s) const; + bool operator==(StringFragment s) const; + bool operator!=(StringFragment s) const; + + const char* fChars; + size_t fLength; +}; + class String : public SKSL_STRING_BASE { public: String() = default; @@ -41,6 +70,9 @@ 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 @@ -53,6 +85,11 @@ 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; @@ -86,6 +123,18 @@ 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 deleted file mode 100644 index 2857a82547..0000000000 --- a/src/sksl/SkSLToken.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SKSL_TOKEN -#define SKSL_TOKEN - -#include "SkSLPosition.h" -#include "SkSLUtil.h" - -namespace SkSL { - -#undef IN -#undef OUT -#undef CONST - -/** - * Represents a lexical analysis token. Token is generally only used during the parse process, but - * Token::Kind is also used to represent operator kinds. - */ -struct Token { - enum Kind { - END_OF_FILE, - WHITESPACE, - IDENTIFIER, - INT_LITERAL, - FLOAT_LITERAL, - TRUE_LITERAL, - FALSE_LITERAL, - LPAREN, - RPAREN, - LBRACE, - RBRACE, - LBRACKET, - RBRACKET, - DOT, - COMMA, - PLUSPLUS, - MINUSMINUS, - PLUS, - MINUS, - STAR, - SLASH, - PERCENT, - SHL, - SHR, - BITWISEOR, - BITWISEXOR, - BITWISEAND, - BITWISENOT, - LOGICALOR, - LOGICALXOR, - LOGICALAND, - LOGICALNOT, - QUESTION, - COLON, - EQ, - EQEQ, - NEQ, - GT, - LT, - GTEQ, - LTEQ, - PLUSEQ, - MINUSEQ, - STAREQ, - SLASHEQ, - PERCENTEQ, - SHLEQ, - SHREQ, - BITWISEOREQ, - BITWISEXOREQ, - BITWISEANDEQ, - LOGICALOREQ, - LOGICALXOREQ, - LOGICALANDEQ, - SEMICOLON, - ARROW, - COLONCOLON, - IF, - STATIC_IF, - ELSE, - FOR, - WHILE, - DO, - SWITCH, - STATIC_SWITCH, - CASE, - DEFAULT, - RETURN, - BREAK, - CONTINUE, - DISCARD, - IN, - OUT, - INOUT, - CONST, - LOWP, - MEDIUMP, - HIGHP, - UNIFORM, - FLAT, - NOPERSPECTIVE, - READONLY, - WRITEONLY, - COHERENT, - VOLATILE, - RESTRICT, - BUFFER, - HASSIDEEFFECTS, - STRUCT, - LAYOUT, - DIRECTIVE, - SECTION, - PRECISION, - LOCATION, - OFFSET, - BINDING, - INDEX, - SET, - BUILTIN, - INPUT_ATTACHMENT_INDEX, - ORIGIN_UPPER_LEFT, - OVERRIDE_COVERAGE, - BLEND_SUPPORT_ALL_EQUATIONS, - PUSH_CONSTANT, - POINTS, - LINES, - LINE_STRIP, - LINES_ADJACENCY, - TRIANGLES, - TRIANGLE_STRIP, - TRIANGLES_ADJACENCY, - MAX_VERTICES, - INVOCATIONS, - WHEN, - KEY, - INVALID_TOKEN - }; - - static String OperatorName(Kind kind) { - switch (kind) { - case Token::PLUS: return String("+"); - case Token::MINUS: return String("-"); - case Token::STAR: return String("*"); - case Token::SLASH: return String("/"); - case Token::PERCENT: return String("%"); - case Token::SHL: return String("<<"); - case Token::SHR: return String(">>"); - case Token::LOGICALNOT: return String("!"); - case Token::LOGICALAND: return String("&&"); - case Token::LOGICALOR: return String("||"); - case Token::LOGICALXOR: return String("^^"); - case Token::BITWISENOT: return String("~"); - case Token::BITWISEAND: return String("&"); - case Token::BITWISEOR: return String("|"); - case Token::BITWISEXOR: return String("^"); - case Token::EQ: return String("="); - case Token::EQEQ: return String("=="); - case Token::NEQ: return String("!="); - case Token::LT: return String("<"); - case Token::GT: return String(">"); - case Token::LTEQ: return String("<="); - case Token::GTEQ: return String(">="); - case Token::PLUSEQ: return String("+="); - case Token::MINUSEQ: return String("-="); - case Token::STAREQ: return String("*="); - case Token::SLASHEQ: return String("/="); - case Token::PERCENTEQ: return String("%="); - case Token::SHLEQ: return String("<<="); - case Token::SHREQ: return String(">>="); - case Token::LOGICALANDEQ: return String("&&="); - case Token::LOGICALOREQ: return String("||="); - case Token::LOGICALXOREQ: return String("^^="); - case Token::BITWISEANDEQ: return String("&="); - case Token::BITWISEOREQ: return String("|="); - case Token::BITWISEXOREQ: return String("^="); - case Token::PLUSPLUS: return String("++"); - case Token::MINUSMINUS: return String("--"); - case Token::COMMA: return String(","); - default: - ABORT("unsupported operator: %d\n", kind); - } - } - - Token() { - } - - Token(Position position, Kind kind, String text) - : fPosition(position) - , fKind(kind) - , fText(std::move(text)) {} - - static bool IsAssignment(Token::Kind op) { - switch (op) { - case Token::EQ: // fall through - case Token::PLUSEQ: // fall through - case Token::MINUSEQ: // fall through - case Token::STAREQ: // fall through - case Token::SLASHEQ: // fall through - case Token::PERCENTEQ: // fall through - case Token::SHLEQ: // fall through - case Token::SHREQ: // fall through - case Token::BITWISEOREQ: // fall through - case Token::BITWISEXOREQ: // fall through - case Token::BITWISEANDEQ: // fall through - case Token::LOGICALOREQ: // fall through - case Token::LOGICALXOREQ: // fall through - case Token::LOGICALANDEQ: - return true; - default: - return false; - } - } - - Position fPosition; - Kind fKind; - // will be the empty string unless the token has variable text content (identifiers, numeric - // literals, and directives) - String fText; -}; - -} // namespace -#endif diff --git a/src/sksl/ast/SkSLASTBinaryExpression.h b/src/sksl/ast/SkSLASTBinaryExpression.h index 9a24970262..c2f7b749a5 100644 --- a/src/sksl/ast/SkSLASTBinaryExpression.h +++ b/src/sksl/ast/SkSLASTBinaryExpression.h @@ -9,7 +9,8 @@ #define SKSL_ASTBINARYEXPRESSION #include "SkSLASTExpression.h" -#include "../SkSLToken.h" +#include "../SkSLCompiler.h" +#include "../SkSLLexer.h" namespace SkSL { @@ -19,13 +20,13 @@ namespace SkSL { struct ASTBinaryExpression : public ASTExpression { ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op, std::unique_ptr<ASTExpression> right) - : INHERITED(op.fPosition, kBinary_Kind) + : INHERITED(op.fOffset, kBinary_Kind) , fLeft(std::move(left)) , fOperator(op.fKind) , fRight(std::move(right)) {} String description() const override { - return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " + + return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " + fRight->description() + ")"; } diff --git a/src/sksl/ast/SkSLASTBlock.h b/src/sksl/ast/SkSLASTBlock.h index 37c0e81a95..df01f62a15 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(Position position, std::vector<std::unique_ptr<ASTStatement>> statements) - : INHERITED(position, kBlock_Kind) + ASTBlock(int offset, std::vector<std::unique_ptr<ASTStatement>> statements) + : INHERITED(offset, kBlock_Kind) , fStatements(std::move(statements)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTBoolLiteral.h b/src/sksl/ast/SkSLASTBoolLiteral.h index 48e916eed5..6782d36e7e 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(Position position, bool value) - : INHERITED(position, kBool_Kind) + ASTBoolLiteral(int offset, bool value) + : INHERITED(offset, kBool_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTBreakStatement.h b/src/sksl/ast/SkSLASTBreakStatement.h index 079ee76d20..2937dae447 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(Position position) - : INHERITED(position, kBreak_Kind) {} + ASTBreakStatement(int offset) + : INHERITED(offset, kBreak_Kind) {} String description() const override { return String("break;"); diff --git a/src/sksl/ast/SkSLASTCallSuffix.h b/src/sksl/ast/SkSLASTCallSuffix.h index 3ba3f0e60f..316a0ae7cc 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(Position position, std::vector<std::unique_ptr<ASTExpression>> arguments) - : INHERITED(position, ASTSuffix::kCall_Kind) + ASTCallSuffix(int offset, std::vector<std::unique_ptr<ASTExpression>> arguments) + : INHERITED(offset, ASTSuffix::kCall_Kind) , fArguments(std::move(arguments)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTContinueStatement.h b/src/sksl/ast/SkSLASTContinueStatement.h index fdfce8598d..30b2dae4ec 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(Position position) - : INHERITED(position, kContinue_Kind) {} + ASTContinueStatement(int offset) + : INHERITED(offset, kContinue_Kind) {} String description() const override { return String("continue;"); diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h index 873c6b2208..53aa65f6f2 100644 --- a/src/sksl/ast/SkSLASTDeclaration.h +++ b/src/sksl/ast/SkSLASTDeclaration.h @@ -26,8 +26,8 @@ struct ASTDeclaration : public ASTPositionNode { kSection_Kind }; - ASTDeclaration(Position position, Kind kind) - : INHERITED(position) + ASTDeclaration(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ast/SkSLASTDiscardStatement.h b/src/sksl/ast/SkSLASTDiscardStatement.h index dcf6b15e64..083c3f82d7 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(Position position) - : INHERITED(position, kDiscard_Kind) {} + ASTDiscardStatement(int offset) + : INHERITED(offset, kDiscard_Kind) {} String description() const override { return String("discard;"); diff --git a/src/sksl/ast/SkSLASTDoStatement.h b/src/sksl/ast/SkSLASTDoStatement.h index fc97d9e142..36324e3685 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(Position position, std::unique_ptr<ASTStatement> statement, + ASTDoStatement(int offset, std::unique_ptr<ASTStatement> statement, std::unique_ptr<ASTExpression> test) - : INHERITED(position, kDo_Kind) + : INHERITED(offset, kDo_Kind) , fStatement(std::move(statement)) , fTest(std::move(test)) {} diff --git a/src/sksl/ast/SkSLASTExpression.h b/src/sksl/ast/SkSLASTExpression.h index 11815aef84..0d8ddc781f 100644 --- a/src/sksl/ast/SkSLASTExpression.h +++ b/src/sksl/ast/SkSLASTExpression.h @@ -27,8 +27,8 @@ struct ASTExpression : public ASTPositionNode { kTernary_Kind }; - ASTExpression(Position position, Kind kind) - : INHERITED(position) + ASTExpression(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} const Kind fKind; diff --git a/src/sksl/ast/SkSLASTExpressionStatement.h b/src/sksl/ast/SkSLASTExpressionStatement.h index 398a16a23a..14f087f57c 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->fPosition, kExpression_Kind) + : INHERITED(expression->fOffset, kExpression_Kind) , fExpression(std::move(expression)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTExtension.h b/src/sksl/ast/SkSLASTExtension.h index a6fde0694c..c394b1d4d0 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(Position position, String name) - : INHERITED(position, kExtension_Kind) + ASTExtension(int offset, String name) + : INHERITED(offset, kExtension_Kind) , fName(std::move(name)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTFieldSuffix.h b/src/sksl/ast/SkSLASTFieldSuffix.h index bde1e4aec5..b29ddf3bda 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(Position position, String field) - : INHERITED(position, ASTSuffix::kField_Kind) - , fField(std::move(field)) {} + ASTFieldSuffix(int offset, StringFragment field) + : INHERITED(offset, ASTSuffix::kField_Kind) + , fField(field) {} String description() const override { return "." + fField; } - String fField; + StringFragment fField; typedef ASTSuffix INHERITED; }; diff --git a/src/sksl/ast/SkSLASTFloatLiteral.h b/src/sksl/ast/SkSLASTFloatLiteral.h index 15fe836049..6e63b4e4ca 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(Position position, double value) - : INHERITED(position, kFloat_Kind) + ASTFloatLiteral(int offset, double value) + : INHERITED(offset, kFloat_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTForStatement.h b/src/sksl/ast/SkSLASTForStatement.h index 326713eb62..713f9522f7 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(Position position, std::unique_ptr<ASTStatement> initializer, + ASTForStatement(int offset, std::unique_ptr<ASTStatement> initializer, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next, std::unique_ptr<ASTStatement> statement) - : INHERITED(position, kFor_Kind) + : INHERITED(offset, kFor_Kind) , fInitializer(std::move(initializer)) , fTest(std::move(test)) , fNext(std::move(next)) diff --git a/src/sksl/ast/SkSLASTFunction.h b/src/sksl/ast/SkSLASTFunction.h index 36d8a3af9f..4fa2482d8b 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(Position position, Modifiers modifiers, std::unique_ptr<ASTType> returnType, - String name, std::vector<std::unique_ptr<ASTParameter>> parameters, + ASTFunction(int offset, Modifiers modifiers, std::unique_ptr<ASTType> returnType, + StringFragment name, std::vector<std::unique_ptr<ASTParameter>> parameters, std::unique_ptr<ASTBlock> body) - : INHERITED(position, kFunction_Kind) + : INHERITED(offset, kFunction_Kind) , fModifiers(modifiers) , fReturnType(std::move(returnType)) - , fName(std::move(name)) + , fName(name) , fParameters(std::move(parameters)) , fBody(std::move(body)) {} @@ -47,7 +47,7 @@ struct ASTFunction : public ASTDeclaration { const Modifiers fModifiers; const std::unique_ptr<ASTType> fReturnType; - const String fName; + const StringFragment fName; const std::vector<std::unique_ptr<ASTParameter>> fParameters; const std::unique_ptr<ASTBlock> fBody; diff --git a/src/sksl/ast/SkSLASTIdentifier.h b/src/sksl/ast/SkSLASTIdentifier.h index 016123cf8c..a84370ec3f 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(Position position, String text) - : INHERITED(position, kIdentifier_Kind) - , fText(std::move(text)) {} + ASTIdentifier(int offset, StringFragment text) + : INHERITED(offset, kIdentifier_Kind) + , fText(text) {} String description() const override { - return fText; + return String(fText); } - const String fText; + const StringFragment fText; typedef ASTExpression INHERITED; }; diff --git a/src/sksl/ast/SkSLASTIfStatement.h b/src/sksl/ast/SkSLASTIfStatement.h index 2752b2b750..85b1239e0b 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(Position position, bool isStatic, std::unique_ptr<ASTExpression> test, + ASTIfStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse) - : INHERITED(position, kIf_Kind) + : INHERITED(offset, kIf_Kind) , fIsStatic(isStatic) , fTest(std::move(test)) , fIfTrue(std::move(ifTrue)) diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h index 31142e3685..cb19e549ef 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(Position position) - : INHERITED(position, ASTSuffix::kIndex_Kind) + ASTIndexSuffix(int offset) + : INHERITED(offset, ASTSuffix::kIndex_Kind) , fExpression(nullptr) {} ASTIndexSuffix(std::unique_ptr<ASTExpression> expression) - : INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind) + : INHERITED(expression ? expression->fOffset : -1, ASTSuffix::kIndex_Kind) , fExpression(std::move(expression)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTIntLiteral.h b/src/sksl/ast/SkSLASTIntLiteral.h index fe04347fd8..927537b250 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(Position position, uint64_t value) - : INHERITED(position, kInt_Kind) + ASTIntLiteral(int offset, uint64_t value) + : INHERITED(offset, kInt_Kind) , fValue(value) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h index f111f73e18..d445ae0398 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(Position position, + ASTInterfaceBlock(int offset, Modifiers modifiers, - String typeName, + StringFragment typeName, std::vector<std::unique_ptr<ASTVarDeclarations>> declarations, - String instanceName, + StringFragment instanceName, std::vector<std::unique_ptr<ASTExpression>> sizes) - : INHERITED(position, kInterfaceBlock_Kind) + : INHERITED(offset, kInterfaceBlock_Kind) , fModifiers(modifiers) - , fTypeName(std::move(typeName)) + , fTypeName(typeName) , fDeclarations(std::move(declarations)) - , fInstanceName(std::move(instanceName)) + , fInstanceName(instanceName) , fSizes(std::move(sizes)) {} String description() const override { @@ -42,7 +42,7 @@ struct ASTInterfaceBlock : public ASTDeclaration { result += fDeclarations[i]->description() + "\n"; } result += "}"; - if (fInstanceName.size()) { + if (fInstanceName.fLength) { result += " " + fInstanceName; for (const auto& size : fSizes) { result += "["; @@ -56,9 +56,9 @@ struct ASTInterfaceBlock : public ASTDeclaration { } const Modifiers fModifiers; - const String fTypeName; + const StringFragment fTypeName; const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations; - const String fInstanceName; + const StringFragment fInstanceName; const std::vector<std::unique_ptr<ASTExpression>> fSizes; typedef ASTDeclaration INHERITED; diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h index ba07f168b2..5269cd54d4 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(Position(), kModifiers_Kind) + : INHERITED(-1, kModifiers_Kind) , fModifiers(modifiers) {} String description() const { diff --git a/src/sksl/ast/SkSLASTParameter.h b/src/sksl/ast/SkSLASTParameter.h index 01227c637e..965e374540 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(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type, - String name, std::vector<int> sizes) - : INHERITED(position) + ASTParameter(int offset, Modifiers modifiers, std::unique_ptr<ASTType> type, + StringFragment name, std::vector<int> sizes) + : INHERITED(offset) , fModifiers(modifiers) , fType(std::move(type)) - , fName(std::move(name)) + , fName(name) , fSizes(std::move(sizes)) {} String description() const override { @@ -38,7 +38,7 @@ struct ASTParameter : public ASTPositionNode { const Modifiers fModifiers; const std::unique_ptr<ASTType> fType; - const String fName; + const StringFragment fName; const std::vector<int> fSizes; typedef ASTPositionNode INHERITED; diff --git a/src/sksl/ast/SkSLASTPositionNode.h b/src/sksl/ast/SkSLASTPositionNode.h index cc435c486c..b8f22a765b 100644 --- a/src/sksl/ast/SkSLASTPositionNode.h +++ b/src/sksl/ast/SkSLASTPositionNode.h @@ -17,10 +17,12 @@ namespace SkSL { * An AST node with an associated position in the source. */ struct ASTPositionNode : public ASTNode { - ASTPositionNode(Position position) - : fPosition(position) {} + ASTPositionNode(int offset) + : fOffset(offset) {} - const Position fPosition; + // character offset of this element within the program being compiled, for error reporting + // purposes + const int fOffset; }; } // namespace diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h index 4b50ed3979..0b81ca3887 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(Position position, Modifiers::Flag precision) - : INHERITED(position, kPrecision_Kind) + ASTPrecision(int offset, Modifiers::Flag precision) + : INHERITED(offset, kPrecision_Kind) , fPrecision(precision) {} String description() const { diff --git a/src/sksl/ast/SkSLASTPrefixExpression.h b/src/sksl/ast/SkSLASTPrefixExpression.h index 08e50f7bf1..0403a2f172 100644 --- a/src/sksl/ast/SkSLASTPrefixExpression.h +++ b/src/sksl/ast/SkSLASTPrefixExpression.h @@ -9,7 +9,8 @@ #define SKSL_ASTPREFIXEXPRESSION #include "SkSLASTExpression.h" -#include "../SkSLToken.h" +#include "../SkSLCompiler.h" +#include "../SkSLLexer.h" namespace SkSL { @@ -18,12 +19,12 @@ namespace SkSL { */ struct ASTPrefixExpression : public ASTExpression { ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand) - : INHERITED(op.fPosition, kPrefix_Kind) + : INHERITED(op.fOffset, kPrefix_Kind) , fOperator(op.fKind) , fOperand(std::move(operand)) {} String description() const override { - return Token::OperatorName(fOperator) + fOperand->description(); + return Compiler::OperatorName(fOperator) + fOperand->description(); } const Token::Kind fOperator; diff --git a/src/sksl/ast/SkSLASTReturnStatement.h b/src/sksl/ast/SkSLASTReturnStatement.h index 6762eb3f90..489658a78b 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(Position position, std::unique_ptr<ASTExpression> expression) - : INHERITED(position, kReturn_Kind) + ASTReturnStatement(int offset, std::unique_ptr<ASTExpression> expression) + : INHERITED(offset, kReturn_Kind) , fExpression(std::move(expression)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTSection.h b/src/sksl/ast/SkSLASTSection.h index d0887e20fe..6c1f8eefa2 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(Position position, String name, String arg, String text) - : INHERITED(position, kSection_Kind) + ASTSection(int offset, String name, String arg, String text) + : INHERITED(offset, kSection_Kind) , fName(std::move(name)) , fArgument(std::move(arg)) , fText(std::move(text)) {} diff --git a/src/sksl/ast/SkSLASTStatement.h b/src/sksl/ast/SkSLASTStatement.h index 1989a1fce6..c22a2fbb0a 100644 --- a/src/sksl/ast/SkSLASTStatement.h +++ b/src/sksl/ast/SkSLASTStatement.h @@ -33,8 +33,8 @@ struct ASTStatement : public ASTPositionNode { kDiscard_Kind }; - ASTStatement(Position position, Kind kind) - : INHERITED(position) + ASTStatement(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ast/SkSLASTSuffix.h b/src/sksl/ast/SkSLASTSuffix.h index f06c6fd362..898855c478 100644 --- a/src/sksl/ast/SkSLASTSuffix.h +++ b/src/sksl/ast/SkSLASTSuffix.h @@ -26,8 +26,8 @@ struct ASTSuffix : public ASTPositionNode { kPostDecrement_Kind }; - ASTSuffix(Position position, Kind kind) - : INHERITED(position) + ASTSuffix(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTSuffixExpression.h b/src/sksl/ast/SkSLASTSuffixExpression.h index 2cff9a865f..31cddb29d1 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->fPosition, kSuffix_Kind) + : INHERITED(base->fOffset, kSuffix_Kind) , fBase(std::move(base)) , fSuffix(std::move(suffix)) {} diff --git a/src/sksl/ast/SkSLASTSwitchCase.h b/src/sksl/ast/SkSLASTSwitchCase.h index 405013a6a7..221e2128ed 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(Position position, std::unique_ptr<ASTExpression> value, + ASTSwitchCase(int offset, std::unique_ptr<ASTExpression> value, std::vector<std::unique_ptr<ASTStatement>> statements) - : INHERITED(position, kSwitch_Kind) + : INHERITED(offset, kSwitch_Kind) , fValue(std::move(value)) , fStatements(std::move(statements)) {} diff --git a/src/sksl/ast/SkSLASTSwitchStatement.h b/src/sksl/ast/SkSLASTSwitchStatement.h index ecd0a6755d..3bee0a4728 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(Position position, bool isStatic, std::unique_ptr<ASTExpression> value, + ASTSwitchStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> value, std::vector<std::unique_ptr<ASTSwitchCase>> cases) - : INHERITED(position, kSwitch_Kind) + : INHERITED(offset, kSwitch_Kind) , fIsStatic(isStatic) , fValue(std::move(value)) , fCases(std::move(cases)) {} diff --git a/src/sksl/ast/SkSLASTTernaryExpression.h b/src/sksl/ast/SkSLASTTernaryExpression.h index 07c92975e0..35795e9f12 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->fPosition, kTernary_Kind) + : INHERITED(test->fOffset, kTernary_Kind) , fTest(std::move(test)) , fIfTrue(std::move(ifTrue)) , fIfFalse(std::move(ifFalse)) {} diff --git a/src/sksl/ast/SkSLASTType.h b/src/sksl/ast/SkSLASTType.h index 57a8025b7b..44fd95bdc7 100644 --- a/src/sksl/ast/SkSLASTType.h +++ b/src/sksl/ast/SkSLASTType.h @@ -21,9 +21,9 @@ struct ASTType : public ASTPositionNode { kStruct_Kind }; - ASTType(Position position, String name, Kind kind, std::vector<int> sizes) - : INHERITED(position) - , fName(std::move(name)) + ASTType(int offset, StringFragment name, Kind kind, std::vector<int> sizes) + : INHERITED(offset) + , fName(name) , fKind(kind) , fSizes(std::move(sizes)) {} @@ -31,7 +31,7 @@ struct ASTType : public ASTPositionNode { return fName; } - const String fName; + const StringFragment fName; const Kind fKind; diff --git a/src/sksl/ast/SkSLASTVarDeclaration.h b/src/sksl/ast/SkSLASTVarDeclaration.h index 2dcb9787ea..38c9104865 100644 --- a/src/sksl/ast/SkSLASTVarDeclaration.h +++ b/src/sksl/ast/SkSLASTVarDeclaration.h @@ -22,7 +22,7 @@ namespace SkSL { * instances. */ struct ASTVarDeclaration { - ASTVarDeclaration(const String name, + ASTVarDeclaration(StringFragment name, std::vector<std::unique_ptr<ASTExpression>> sizes, std::unique_ptr<ASTExpression> value) : fName(name) @@ -30,7 +30,7 @@ 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; } - String fName; + StringFragment fName; // array sizes, if any. e.g. 'foo[3][]' has sizes [3, null] std::vector<std::unique_ptr<ASTExpression>> fSizes; @@ -60,7 +60,7 @@ struct ASTVarDeclarations : public ASTDeclaration { ASTVarDeclarations(Modifiers modifiers, std::unique_ptr<ASTType> type, std::vector<ASTVarDeclaration> vars) - : INHERITED(type->fPosition, kVar_Kind) + : INHERITED(type->fOffset, kVar_Kind) , fModifiers(modifiers) , fType(std::move(type)) , fVars(std::move(vars)) {} diff --git a/src/sksl/ast/SkSLASTVarDeclarationStatement.h b/src/sksl/ast/SkSLASTVarDeclarationStatement.h index c3a4069ba0..8ec5bf6789 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->fPosition, kVarDeclaration_Kind) + : INHERITED(decl->fOffset, kVarDeclaration_Kind) , fDeclarations(std::move(decl)) {} String description() const override { diff --git a/src/sksl/ast/SkSLASTWhileStatement.h b/src/sksl/ast/SkSLASTWhileStatement.h index e63c50293a..c0da0afb7d 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(Position position, std::unique_ptr<ASTExpression> test, + ASTWhileStatement(int offset, std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTStatement> statement) - : INHERITED(position, kWhile_Kind) + : INHERITED(offset, kWhile_Kind) , fTest(std::move(test)) , fStatement(std::move(statement)) {} diff --git a/src/sksl/disable_flex_warnings.h b/src/sksl/disable_flex_warnings.h deleted file mode 100644 index ad73b63583..0000000000 --- a/src/sksl/disable_flex_warnings.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -// useless include to avoid "#if before #include" complaint from Skia presubmit -#include "SkSLUtil.h" -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunneeded-internal-declaration" -#pragma clang diagnostic ignored "-Wnull-conversion" -#pragma clang diagnostic ignored "-Wsign-compare" -#pragma clang diagnostic ignored "-Wunused-function" -#pragma clang diagnostic ignored "-Wdeprecated-register" -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4018) -#endif - -#define YY_NO_UNPUT diff --git a/src/sksl/ir/SkSLBinaryExpression.h b/src/sksl/ir/SkSLBinaryExpression.h index 789db5783b..c26994edf2 100644 --- a/src/sksl/ir/SkSLBinaryExpression.h +++ b/src/sksl/ir/SkSLBinaryExpression.h @@ -11,7 +11,7 @@ #include "SkSLExpression.h" #include "SkSLExpression.h" #include "../SkSLIRGenerator.h" -#include "../SkSLToken.h" +#include "../SkSLLexer.h" namespace SkSL { @@ -19,9 +19,9 @@ namespace SkSL { * A binary operation. */ struct BinaryExpression : public Expression { - BinaryExpression(Position position, std::unique_ptr<Expression> left, Token::Kind op, + BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op, std::unique_ptr<Expression> right, const Type& type) - : INHERITED(position, kBinary_Kind, type) + : INHERITED(offset, kBinary_Kind, type) , fLeft(std::move(left)) , fOperator(op) , fRight(std::move(right)) {} @@ -34,12 +34,12 @@ struct BinaryExpression : public Expression { } bool hasSideEffects() const override { - return Token::IsAssignment(fOperator) || fLeft->hasSideEffects() || + return Compiler::IsAssignment(fOperator) || fLeft->hasSideEffects() || fRight->hasSideEffects(); } String description() const override { - return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " + + return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " + fRight->description() + ")"; } diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h index bcd4bb1b59..af1975396e 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(Position position, std::vector<std::unique_ptr<Statement>> statements, + Block(int offset, std::vector<std::unique_ptr<Statement>> statements, const std::shared_ptr<SymbolTable> symbols = nullptr) - : INHERITED(position, kBlock_Kind) + : INHERITED(offset, kBlock_Kind) , fSymbols(std::move(symbols)) , fStatements(std::move(statements)) {} diff --git a/src/sksl/ir/SkSLBoolLiteral.h b/src/sksl/ir/SkSLBoolLiteral.h index a4151b8b35..9a69f0f138 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, Position position, bool value) - : INHERITED(position, kBoolLiteral_Kind, *context.fBool_Type) + BoolLiteral(const Context& context, int offset, bool value) + : INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type) , fValue(value) {} String description() const override { diff --git a/src/sksl/ir/SkSLBreakStatement.h b/src/sksl/ir/SkSLBreakStatement.h index f6edc558e5..da392f5960 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(Position position) - : INHERITED(position, kBreak_Kind) {} + BreakStatement(int offset) + : INHERITED(offset, kBreak_Kind) {} String description() const override { return String("break;"); diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h index beed0f702d..32fc0fb2e7 100644 --- a/src/sksl/ir/SkSLConstructor.h +++ b/src/sksl/ir/SkSLConstructor.h @@ -16,7 +16,7 @@ namespace SkSL { /** - * Represents the construction of a compound type, such as "float2x, y)". + * Represents the construction of a compound type, such as "float2(x, y)". * * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors * and scalars totalling exactly the right number of scalar components. @@ -25,9 +25,8 @@ namespace SkSL { * collection of vectors and scalars totalling exactly the right number of scalar components. */ struct Constructor : public Expression { - Constructor(Position position, const Type& type, - std::vector<std::unique_ptr<Expression>> arguments) - : INHERITED(position, kConstructor_Kind, type) + Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments) + : INHERITED(offset, kConstructor_Kind, type) , fArguments(std::move(arguments)) {} std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, @@ -37,13 +36,13 @@ 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, - fPosition, + fOffset, intValue)); } else if (fType == *irGenerator.fContext.fUInt_Type) { // promote uint(1) to 1u int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue; return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, - fPosition, + fOffset, intValue, &fType)); } @@ -96,8 +95,8 @@ 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, Position(), 0); - const IntLiteral izero(context, Position(), 0); + const FloatLiteral fzero(context, -1, 0); + const IntLiteral izero(context, -1, 0); const Expression* zero; if (fType.componentType() == *context.fFloat_Type) { zero = &fzero; diff --git a/src/sksl/ir/SkSLContinueStatement.h b/src/sksl/ir/SkSLContinueStatement.h index 3f5bc1d4bb..6ed40c404f 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(Position position) - : INHERITED(position, kContinue_Kind) {} + ContinueStatement(int offset) + : INHERITED(offset, kContinue_Kind) {} String description() const override { return String("continue;"); diff --git a/src/sksl/ir/SkSLDiscardStatement.h b/src/sksl/ir/SkSLDiscardStatement.h index 62124668ee..b62530e6f3 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(Position position) - : INHERITED(position, kDiscard_Kind) {} + DiscardStatement(int offset) + : INHERITED(offset, kDiscard_Kind) {} String description() const override { return String("discard;"); diff --git a/src/sksl/ir/SkSLDoStatement.h b/src/sksl/ir/SkSLDoStatement.h index f1ecd9a8bf..3abec550eb 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(Position position, std::unique_ptr<Statement> statement, + DoStatement(int offset, std::unique_ptr<Statement> statement, std::unique_ptr<Expression> test) - : INHERITED(position, kDo_Kind) + : INHERITED(offset, kDo_Kind) , fStatement(std::move(statement)) , fTest(std::move(test)) {} diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h index 286610f078..555e66061d 100644 --- a/src/sksl/ir/SkSLExpression.h +++ b/src/sksl/ir/SkSLExpression.h @@ -44,8 +44,8 @@ struct Expression : public IRNode { kDefined_Kind }; - Expression(Position position, Kind kind, const Type& type) - : INHERITED(position) + Expression(int offset, Kind kind, const Type& type) + : INHERITED(offset) , fKind(kind) , fType(std::move(type)) {} diff --git a/src/sksl/ir/SkSLExpressionStatement.h b/src/sksl/ir/SkSLExpressionStatement.h index d1ab8e9ed9..215763b8fd 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->fPosition, kExpression_Kind) + : INHERITED(expression->fOffset, kExpression_Kind) , fExpression(std::move(expression)) {} String description() const override { diff --git a/src/sksl/ir/SkSLExtension.h b/src/sksl/ir/SkSLExtension.h index 70dc6b3eaf..b5a48b94ab 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(Position position, String name) - : INHERITED(position, kExtension_Kind) + Extension(int offset, String name) + : INHERITED(offset, kExtension_Kind) , fName(std::move(name)) {} String description() const override { diff --git a/src/sksl/ir/SkSLField.h b/src/sksl/ir/SkSLField.h index abea730da1..fe2af7fa6e 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(Position position, const Variable& owner, int fieldIndex) - : INHERITED(position, kField_Kind, owner.fType.fields()[fieldIndex].fName) + Field(int offset, const Variable& owner, int fieldIndex) + : INHERITED(offset, kField_Kind, owner.fType.fields()[fieldIndex].fName) , fOwner(owner) , fFieldIndex(fieldIndex) {} diff --git a/src/sksl/ir/SkSLFieldAccess.h b/src/sksl/ir/SkSLFieldAccess.h index e0a335f528..0f66dec5a4 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->fPosition, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType) + : INHERITED(base->fOffset, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType) , fBase(std::move(base)) , fFieldIndex(fieldIndex) , fOwnerKind(ownerKind) {} diff --git a/src/sksl/ir/SkSLFloatLiteral.h b/src/sksl/ir/SkSLFloatLiteral.h index 21a485fb0a..e6a3062f36 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, Position position, double value, + FloatLiteral(const Context& context, int offset, double value, const Type* type = nullptr) - : INHERITED(position, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type) + : INHERITED(offset, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type) , fValue(value) {} String description() const override { diff --git a/src/sksl/ir/SkSLForStatement.h b/src/sksl/ir/SkSLForStatement.h index ca3e6cfb7a..6896ceb902 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(Position position, std::unique_ptr<Statement> initializer, + ForStatement(int offset, std::unique_ptr<Statement> initializer, std::unique_ptr<Expression> test, std::unique_ptr<Expression> next, std::unique_ptr<Statement> statement, std::shared_ptr<SymbolTable> symbols) - : INHERITED(position, kFor_Kind) + : INHERITED(offset, kFor_Kind) , fSymbols(symbols) , fInitializer(std::move(initializer)) , fTest(std::move(test)) diff --git a/src/sksl/ir/SkSLFunctionCall.h b/src/sksl/ir/SkSLFunctionCall.h index 44f8c7ed5a..115281d63d 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(Position position, const Type& type, const FunctionDeclaration& function, + FunctionCall(int offset, const Type& type, const FunctionDeclaration& function, std::vector<std::unique_ptr<Expression>> arguments) - : INHERITED(position, kFunctionCall_Kind, type) + : INHERITED(offset, kFunctionCall_Kind, type) , fFunction(std::move(function)) , fArguments(std::move(arguments)) {} @@ -33,7 +33,7 @@ struct FunctionCall : public Expression { } String description() const override { - String result = fFunction.fName + "("; + String result = String(fFunction.fName) + "("; String separator; for (size_t i = 0; i < fArguments.size(); i++) { result += separator; diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h index 64236d3980..d0f9d240d7 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(Position position, Modifiers modifiers, String name, + FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name, std::vector<const Variable*> parameters, const Type& returnType) - : INHERITED(position, kFunctionDeclaration_Kind, std::move(name)) + : INHERITED(offset, kFunctionDeclaration_Kind, std::move(name)) , fDefined(false) , fBuiltin(false) , fModifiers(modifiers) diff --git a/src/sksl/ir/SkSLFunctionDefinition.h b/src/sksl/ir/SkSLFunctionDefinition.h index 0277db1f07..e0dabc5791 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(Position position, const FunctionDeclaration& declaration, + FunctionDefinition(int offset, const FunctionDeclaration& declaration, std::unique_ptr<Statement> body) - : INHERITED(position, kFunction_Kind) + : INHERITED(offset, kFunction_Kind) , fDeclaration(declaration) , fBody(std::move(body)) {} diff --git a/src/sksl/ir/SkSLFunctionReference.h b/src/sksl/ir/SkSLFunctionReference.h index ee761c2639..58831c5e99 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, Position position, + FunctionReference(const Context& context, int offset, std::vector<const FunctionDeclaration*> function) - : INHERITED(position, kFunctionReference_Kind, *context.fInvalid_Type) + : INHERITED(offset, kFunctionReference_Kind, *context.fInvalid_Type) , fFunctions(function) {} bool hasSideEffects() const override { diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h index 139be32f44..5ada50607e 100644 --- a/src/sksl/ir/SkSLIRNode.h +++ b/src/sksl/ir/SkSLIRNode.h @@ -8,7 +8,7 @@ #ifndef SKSL_IRNODE #define SKSL_IRNODE -#include "../SkSLPosition.h" +#include "../SkSLLexer.h" namespace SkSL { @@ -17,14 +17,16 @@ namespace SkSL { * version of the program (all types determined, everything validated), ready for code generation. */ struct IRNode { - IRNode(Position position) - : fPosition(position) {} + IRNode(int offset) + : fOffset(offset) {} virtual ~IRNode() {} virtual String description() const = 0; - const Position fPosition; + // character offset of this element within the program being compiled, for error reporting + // purposes + const int fOffset; }; } // namespace diff --git a/src/sksl/ir/SkSLIfStatement.h b/src/sksl/ir/SkSLIfStatement.h index b09c10ee95..4c2ca0b1fa 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(Position position, bool isStatic, std::unique_ptr<Expression> test, + IfStatement(int offset, bool isStatic, std::unique_ptr<Expression> test, std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse) - : INHERITED(position, kIf_Kind) + : INHERITED(offset, kIf_Kind) , fIsStatic(isStatic) , fTest(std::move(test)) , fIfTrue(std::move(ifTrue)) diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h index c305365049..2daf1b552a 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->fPosition, kIndex_Kind, index_type(context, base->fType)) + : INHERITED(base->fOffset, kIndex_Kind, index_type(context, base->fType)) , fBase(std::move(base)) , fIndex(std::move(index)) { ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type); diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h index 6199f96610..da2b4082de 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, Position position, int64_t value, const Type* type = nullptr) - : INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type) + IntLiteral(const Context& context, int offset, int64_t value, const Type* type = nullptr) + : INHERITED(offset, kIntLiteral_Kind, type ? *type : *context.fInt_Type) , fValue(value) {} String description() const override { diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h index a28a6a1b54..03986b87cd 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(Position position, const Variable* var, String typeName, String instanceName, + InterfaceBlock(int offset, const Variable* var, String typeName, String instanceName, std::vector<std::unique_ptr<Expression>> sizes, std::shared_ptr<SymbolTable> typeOwner) - : INHERITED(position, kInterfaceBlock_Kind) + : INHERITED(offset, kInterfaceBlock_Kind) , fVariable(*var) , fTypeName(std::move(typeName)) , fInstanceName(std::move(instanceName)) diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h index a0ce74852d..5c9608f02f 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(Position(), kModifiers_Kind) + : INHERITED(-1, kModifiers_Kind) , fModifiers(modifiers) {} String description() const { diff --git a/src/sksl/ir/SkSLNop.h b/src/sksl/ir/SkSLNop.h index 5ebea40583..e7aae9b7b8 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(Position(), kNop_Kind) {} + : INHERITED(-1, kNop_Kind) {} virtual bool isEmpty() const override { return true; diff --git a/src/sksl/ir/SkSLPostfixExpression.h b/src/sksl/ir/SkSLPostfixExpression.h index e02555db70..c53f1de507 100644 --- a/src/sksl/ir/SkSLPostfixExpression.h +++ b/src/sksl/ir/SkSLPostfixExpression.h @@ -9,7 +9,7 @@ #define SKSL_POSTFIXEXPRESSION #include "SkSLExpression.h" -#include "SkSLToken.h" +#include "SkSLLexer.h" namespace SkSL { @@ -18,7 +18,7 @@ namespace SkSL { */ struct PostfixExpression : public Expression { PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op) - : INHERITED(operand->fPosition, kPostfix_Kind, operand->fType) + : INHERITED(operand->fOffset, kPostfix_Kind, operand->fType) , fOperand(std::move(operand)) , fOperator(op) {} @@ -27,7 +27,7 @@ struct PostfixExpression : public Expression { } String description() const override { - return fOperand->description() + Token::OperatorName(fOperator); + return fOperand->description() + Compiler::OperatorName(fOperator); } std::unique_ptr<Expression> fOperand; diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h index 5ac84c66b1..d5d97b2517 100644 --- a/src/sksl/ir/SkSLPrefixExpression.h +++ b/src/sksl/ir/SkSLPrefixExpression.h @@ -11,7 +11,7 @@ #include "SkSLExpression.h" #include "SkSLFloatLiteral.h" #include "SkSLIRGenerator.h" -#include "SkSLToken.h" +#include "SkSLLexer.h" namespace SkSL { @@ -20,7 +20,7 @@ namespace SkSL { */ struct PrefixExpression : public Expression { PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand) - : INHERITED(operand->fPosition, kPrefix_Kind, operand->fType) + : INHERITED(operand->fOffset, kPrefix_Kind, operand->fType) , fOperand(std::move(operand)) , fOperator(op) {} @@ -38,7 +38,7 @@ struct PrefixExpression : public Expression { if (fOperand->fKind == Expression::kFloatLiteral_Kind) { return std::unique_ptr<Expression>(new FloatLiteral( irGenerator.fContext, - Position(), + fOffset, -((FloatLiteral&) *fOperand).fValue)); } @@ -46,7 +46,7 @@ struct PrefixExpression : public Expression { } String description() const override { - return Token::OperatorName(fOperator) + fOperand->description(); + return Compiler::OperatorName(fOperator) + fOperand->description(); } std::unique_ptr<Expression> fOperand; diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index a3eeaa3612..639e09b16a 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, Position position) const { + std::unique_ptr<Expression> literal(const Context& context, int offset) const { switch (fKind) { case Program::Settings::Value::kBool_Kind: return std::unique_ptr<Expression>(new BoolLiteral(context, - position, + offset, fValue)); case Program::Settings::Value::kInt_Kind: return std::unique_ptr<Expression>(new IntLiteral(context, - position, + offset, fValue)); default: ASSERT(false); @@ -103,6 +103,7 @@ struct Program { }; Program(Kind kind, + std::unique_ptr<String> source, Settings settings, Modifiers::Flag defaultPrecision, Context* context, @@ -110,6 +111,7 @@ struct Program { std::shared_ptr<SymbolTable> symbols, Inputs inputs) : fKind(kind) + , fSource(std::move(source)) , fSettings(settings) , fDefaultPrecision(defaultPrecision) , fContext(context) @@ -118,6 +120,7 @@ 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 1e2bb48641..4a3566d287 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -25,8 +25,8 @@ struct ProgramElement : public IRNode { kSection_Kind }; - ProgramElement(Position position, Kind kind) - : INHERITED(position) + ProgramElement(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} Kind fKind; diff --git a/src/sksl/ir/SkSLReturnStatement.h b/src/sksl/ir/SkSLReturnStatement.h index 841db94669..1b479b8097 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(Position position) - : INHERITED(position, kReturn_Kind) {} + ReturnStatement(int offset) + : INHERITED(offset, kReturn_Kind) {} ReturnStatement(std::unique_ptr<Expression> expression) - : INHERITED(expression->fPosition, kReturn_Kind) + : INHERITED(expression->fOffset, kReturn_Kind) , fExpression(std::move(expression)) {} String description() const override { diff --git a/src/sksl/ir/SkSLSection.h b/src/sksl/ir/SkSLSection.h index f9815b1caa..96c257b1f8 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(Position position, String name, String arg, String text) - : INHERITED(position, kSection_Kind) + Section(int offset, String name, String arg, String text) + : INHERITED(offset, kSection_Kind) , fName(std::move(name)) , fArgument(std::move(arg)) , fText(std::move(text)) {} diff --git a/src/sksl/ir/SkSLSetting.h b/src/sksl/ir/SkSLSetting.h index 995fcf55bf..f479ad167b 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(Position position, String name, std::unique_ptr<Expression> value) - : INHERITED(position, kSetting_Kind, value->fType) + Setting(int offset, String name, std::unique_ptr<Expression> value) + : INHERITED(offset, kSetting_Kind, value->fType) , fName(std::move(name)) , fValue(std::move(value)) { ASSERT(fValue->isConstant()); diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h index 1bc524451b..a116cc1c4c 100644 --- a/src/sksl/ir/SkSLStatement.h +++ b/src/sksl/ir/SkSLStatement.h @@ -35,8 +35,8 @@ struct Statement : public IRNode { kWhile_Kind }; - Statement(Position position, Kind kind) - : INHERITED(position) + Statement(int offset, Kind kind) + : INHERITED(offset) , fKind(kind) {} virtual bool isEmpty() const { diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h index 8043f2e787..c33224bdbb 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(Position position, std::unique_ptr<Expression> value, + SwitchCase(int offset, std::unique_ptr<Expression> value, std::vector<std::unique_ptr<Statement>> statements) - : INHERITED(position, kSwitch_Kind) + : INHERITED(offset, kSwitch_Kind) , fValue(std::move(value)) , fStatements(std::move(statements)) {} diff --git a/src/sksl/ir/SkSLSwitchStatement.h b/src/sksl/ir/SkSLSwitchStatement.h index dec5b749a5..68d0ef02df 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(Position position, bool isStatic, std::unique_ptr<Expression> value, + SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value, std::vector<std::unique_ptr<SwitchCase>> cases, const std::shared_ptr<SymbolTable> symbols) - : INHERITED(position, kSwitch_Kind) + : INHERITED(offset, kSwitch_Kind) , fIsStatic(isStatic) , fValue(std::move(value)) , fSymbols(std::move(symbols)) diff --git a/src/sksl/ir/SkSLSwizzle.h b/src/sksl/ir/SkSLSwizzle.h index 9d7ca37bdc..3256ef211a 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->fPosition, kSwizzle_Kind, get_type(context, *base, components.size())) + : INHERITED(base->fOffset, kSwizzle_Kind, get_type(context, *base, components.size())) , fBase(std::move(base)) , fComponents(std::move(components)) { ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4); @@ -80,13 +80,13 @@ 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, - Position(), - value)); + -1, + value)); } else if (fType == *irGenerator.fContext.fFloat_Type) { ASSERT(fComponents.size() == 1); double value = ((Constructor&) *fBase).getFVecComponent(fComponents[0]); return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext, - Position(), + -1, value)); } } diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h index e883ea7555..f4c675319b 100644 --- a/src/sksl/ir/SkSLSymbol.h +++ b/src/sksl/ir/SkSLSymbol.h @@ -24,13 +24,13 @@ struct Symbol : public IRNode { kField_Kind }; - Symbol(Position position, Kind kind, String name) - : INHERITED(position) + Symbol(int offset, Kind kind, StringFragment name) + : INHERITED(offset) , fKind(kind) - , fName(std::move(name)) {} + , fName(name) {} const Kind fKind; - const String fName; + StringFragment fName; typedef IRNode INHERITED; }; diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp index 4d39e8bc9d..40e8e66c9f 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[](const String& name) { +const Symbol* SymbolTable::operator[](StringFragment name) { const auto& entry = fSymbols.find(name); if (entry == fSymbols.end()) { if (fParent) { @@ -64,12 +64,12 @@ Symbol* SymbolTable::takeOwnership(Symbol* s) { return s; } -void SymbolTable::add(const String& name, std::unique_ptr<Symbol> symbol) { +void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) { this->addWithoutOwnership(name, symbol.get()); fOwnedPointers.push_back(std::move(symbol)); } -void SymbolTable::addWithoutOwnership(const String& name, const Symbol* symbol) { +void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) { const auto& existing = fSymbols.find(name); if (existing == fSymbols.end()) { fSymbols[name] = symbol; @@ -93,7 +93,7 @@ void SymbolTable::addWithoutOwnership(const String& name, const Symbol* symbol) this->takeOwnership(u); } } else { - fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined"); + fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined"); } } diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h index 6bafef259d..241631db80 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[](const String& name); + const Symbol* operator[](StringFragment name); - void add(const String& name, std::unique_ptr<Symbol> symbol); + void add(StringFragment name, std::unique_ptr<Symbol> symbol); - void addWithoutOwnership(const String& name, const Symbol* symbol); + void addWithoutOwnership(StringFragment name, const Symbol* symbol); Symbol* takeOwnership(Symbol* s); @@ -48,7 +48,7 @@ private: std::vector<std::unique_ptr<Symbol>> fOwnedPointers; - std::unordered_map<String, const Symbol*> fSymbols; + std::unordered_map<StringFragment, const Symbol*> fSymbols; ErrorReporter& fErrorReporter; }; diff --git a/src/sksl/ir/SkSLTernaryExpression.h b/src/sksl/ir/SkSLTernaryExpression.h index 567af56e8e..282a3221db 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(Position position, std::unique_ptr<Expression> test, + TernaryExpression(int offset, std::unique_ptr<Expression> test, std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse) - : INHERITED(position, kTernary_Kind, ifTrue->fType) + : INHERITED(offset, kTernary_Kind, ifTrue->fType) , fTest(std::move(test)) , fIfTrue(std::move(ifTrue)) , fIfFalse(std::move(ifFalse)) { diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h index 6ea4c5694c..b0474216c1 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, String name, const Type* type) + Field(Modifiers modifiers, StringFragment name, const Type* type) : fModifiers(modifiers) - , fName(std::move(name)) + , fName(name) , fType(std::move(type)) {} const String description() const { @@ -37,7 +37,7 @@ public: } Modifiers fModifiers; - String fName; + StringFragment fName; const Type* fType; }; @@ -62,40 +62,60 @@ public: // Create an "other" (special) type with the given name. These types cannot be directly // referenced from user code. Type(String name) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kOther_Kind) - , fNumberKind(kNonnumeric_NumberKind) {} + , fNumberKind(kNonnumeric_NumberKind) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a generic type which maps to the listed types. Type(String name, std::vector<const Type*> types) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kGeneric_Kind) , fNumberKind(kNonnumeric_NumberKind) - , fCoercibleTypes(std::move(types)) {} + , fCoercibleTypes(std::move(types)) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a struct type with the given fields. - Type(Position position, String name, std::vector<Field> fields) - : INHERITED(position, kType_Kind, std::move(name)) + Type(int offset, String name, std::vector<Field> fields) + : INHERITED(offset, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kStruct_Kind) , fNumberKind(kNonnumeric_NumberKind) - , fFields(std::move(fields)) {} + , fFields(std::move(fields)) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a scalar type. Type(String name, NumberKind numberKind) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kScalar_Kind) , fNumberKind(numberKind) , fColumns(1) - , fRows(1) {} + , fRows(1) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a scalar type which can be coerced to the listed types. Type(String name, NumberKind numberKind, std::vector<const Type*> coercibleTypes) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kScalar_Kind) , fNumberKind(numberKind) , fCoercibleTypes(std::move(coercibleTypes)) , fColumns(1) - , fRows(1) {} + , fRows(1) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a vector type. Type(String name, const Type& componentType, int columns) @@ -103,42 +123,54 @@ public: // Create a vector or array type. Type(String name, Kind kind, const Type& componentType, int columns) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kind) , fNumberKind(kNonnumeric_NumberKind) , fComponentType(&componentType) , fColumns(columns) , fRows(1) - , fDimensions(SpvDim1D) {} + , fDimensions(SpvDim1D) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a matrix type. Type(String name, const Type& componentType, int columns, int rows) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kMatrix_Kind) , fNumberKind(kNonnumeric_NumberKind) , fComponentType(&componentType) , fColumns(columns) , fRows(rows) - , fDimensions(SpvDim1D) {} + , fDimensions(SpvDim1D) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } // Create a sampler type. Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, bool isSampled) - : INHERITED(Position(), kType_Kind, std::move(name)) + : INHERITED(-1, kType_Kind, StringFragment()) + , fNameString(std::move(name)) , fTypeKind(kSampler_Kind) , fNumberKind(kNonnumeric_NumberKind) , fDimensions(dimensions) , fIsDepth(isDepth) , fIsArrayed(isArrayed) , fIsMultisampled(isMultisampled) - , fIsSampled(isSampled) {} + , fIsSampled(isSampled) { + fName.fChars = fNameString.c_str(); + fName.fLength = fNameString.size(); + } const String& name() const { - return fName; + return fNameString; } String description() const override { - return fName; + return fNameString; } bool operator==(const Type& other) const { @@ -283,6 +315,7 @@ 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 eae19897c7..f7065b7c3f 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, Position position, const Type& type) - : INHERITED(position, kTypeReference_Kind, *context.fInvalid_Type) + TypeReference(const Context& context, int offset, const Type& type) + : INHERITED(offset, kTypeReference_Kind, *context.fInvalid_Type) , fValue(type) {} bool hasSideEffects() const override { @@ -27,7 +27,7 @@ struct TypeReference : public Expression { } String description() const override { - return fValue.name(); + return String(fValue.fName); } const Type& fValue; diff --git a/src/sksl/ir/SkSLUnresolvedFunction.h b/src/sksl/ir/SkSLUnresolvedFunction.h index b222bc3053..62035da3a3 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(Position(), kUnresolvedFunction_Kind, funcs[0]->fName) + : INHERITED(-1, kUnresolvedFunction_Kind, funcs[0]->fName) , fFunctions(std::move(funcs)) { #ifdef DEBUG for (auto func : funcs) { diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h index 1eda87e979..707715f6dc 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->fPosition, Statement::kVarDeclaration_Kind) + : INHERITED(var->fOffset, 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(Position position, const Type* baseType, + VarDeclarations(int offset, const Type* baseType, std::vector<std::unique_ptr<VarDeclaration>> vars) - : INHERITED(position, kVar_Kind) + : INHERITED(offset, kVar_Kind) , fBaseType(*baseType) { for (auto& var : vars) { fVars.push_back(std::unique_ptr<Statement>(var.release())); diff --git a/src/sksl/ir/SkSLVarDeclarationsStatement.h b/src/sksl/ir/SkSLVarDeclarationsStatement.h index a6a95a9c08..0258e66c6e 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->fPosition, kVarDeclarations_Kind) + : INHERITED(decl->fOffset, kVarDeclarations_Kind) , fDeclaration(std::move(decl)) {} bool isEmpty() const override { diff --git a/src/sksl/ir/SkSLVariable.h b/src/sksl/ir/SkSLVariable.h index 05bba20a83..536d1e6b6d 100644 --- a/src/sksl/ir/SkSLVariable.h +++ b/src/sksl/ir/SkSLVariable.h @@ -27,9 +27,9 @@ struct Variable : public Symbol { kParameter_Storage }; - Variable(Position position, Modifiers modifiers, String name, const Type& type, + Variable(int offset, Modifiers modifiers, StringFragment name, const Type& type, Storage storage) - : INHERITED(position, kVariable_Kind, std::move(name)) + : INHERITED(offset, kVariable_Kind, name) , fModifiers(modifiers) , fType(type) , fStorage(storage) diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index ba17437e24..54917b0431 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -32,8 +32,8 @@ struct VariableReference : public Expression { kReadWrite_RefKind }; - VariableReference(Position position, const Variable& variable, RefKind refKind = kRead_RefKind) - : INHERITED(position, kVariableReference_Kind, variable.fType) + VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind) + : INHERITED(offset, kVariableReference_Kind, variable.fType) , fVariable(variable) , fRefKind(refKind) { if (refKind != kRead_RefKind) { @@ -83,18 +83,17 @@ struct VariableReference : public Expression { ASSERT(expr->isConstant()); switch (expr->fKind) { case Expression::kIntLiteral_Kind: - return std::unique_ptr<Expression>(new IntLiteral( - irGenerator.fContext, - Position(), - ((IntLiteral*) expr)->fValue)); + return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, + -1, + ((IntLiteral*) expr)->fValue)); case Expression::kFloatLiteral_Kind: return std::unique_ptr<Expression>(new FloatLiteral( - irGenerator.fContext, - Position(), - ((FloatLiteral*) expr)->fValue)); + irGenerator.fContext, + -1, + ((FloatLiteral*) expr)->fValue)); case Expression::kBoolLiteral_Kind: return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext, - Position(), + -1, ((BoolLiteral*) expr)->fValue)); case Expression::kConstructor_Kind: { const Constructor* c = (const Constructor*) expr; @@ -102,12 +101,12 @@ 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(Position(), c->fType, + return std::unique_ptr<Expression>(new Constructor(-1, c->fType, std::move(args))); } case Expression::kSetting_Kind: { const Setting* s = (const Setting*) expr; - return std::unique_ptr<Expression>(new Setting(Position(), s->fName, + return std::unique_ptr<Expression>(new Setting(-1, s->fName, copy_constant(irGenerator, s->fValue.get()))); } diff --git a/src/sksl/ir/SkSLWhileStatement.h b/src/sksl/ir/SkSLWhileStatement.h index 6df1619a56..aed6494999 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(Position position, std::unique_ptr<Expression> test, + WhileStatement(int offset, std::unique_ptr<Expression> test, std::unique_ptr<Statement> statement) - : INHERITED(position, kWhile_Kind) + : INHERITED(offset, kWhile_Kind) , fTest(std::move(test)) , fStatement(std::move(statement)) {} diff --git a/src/sksl/layout.flex b/src/sksl/layout.flex deleted file mode 100644 index 4e6695cfdc..0000000000 --- a/src/sksl/layout.flex +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - - This file is IGNORED during the build process! - - As this file is updated so infrequently and flex is not universally present on build machines, - the lex.layout.c file must be manually regenerated if you make any changes to this file. Just - run: - - flex layout.flex - - You will have to manually add a copyright notice to the top of lex.layout.c. - -*/ - -%option prefix="layout" -%option reentrant -%option yylineno -%option never-interactive -%option nounistd - -%{ -#include "SkSLToken.h" -%} - -%% - -"location" { return SkSL::Token::LOCATION; } -"offset" { return SkSL::Token::OFFSET; } -"binding" { return SkSL::Token::BINDING; } -"index" { return SkSL::Token::INDEX; } -"set" { return SkSL::Token::SET; } -"builtin" { return SkSL::Token::BUILTIN; } -"input_attachment_index" { return SkSL::Token::INPUT_ATTACHMENT_INDEX; } -"origin_upper_left" { return SkSL::Token::ORIGIN_UPPER_LEFT; } -"override_coverage" { return SkSL::Token::OVERRIDE_COVERAGE; } -"blend_support_all_equations" { return SkSL::Token::BLEND_SUPPORT_ALL_EQUATIONS; } -"push_constant" { return SkSL::Token::PUSH_CONSTANT; } -"points" { return SkSL::Token::POINTS; } -"lines" { return SkSL::Token::LINES; } -"line_strip" { return SkSL::Token::LINE_STRIP; } -"lines_adjacency" { return SkSL::Token::LINES_ADJACENCY; } -"triangles" { return SkSL::Token::TRIANGLES; } -"triangle_strip" { return SkSL::Token::TRIANGLE_STRIP; } -"triangles_adjacency" { return SkSL::Token::TRIANGLES_ADJACENCY; } -"max_vertices" { return SkSL::Token::MAX_VERTICES; } -"invocations" { return SkSL::Token::INVOCATIONS; } -"when" { return SkSL::Token::WHEN; } -"key" { return SkSL::Token::KEY; } - -. { return SkSL::Token::INVALID_TOKEN; } - -%% - -int layoutwrap(yyscan_t scanner) { - return 1; // terminate -} diff --git a/src/sksl/lex.layout.c b/src/sksl/lex.layout.c deleted file mode 100644 index 63369fe93b..0000000000 --- a/src/sksl/lex.layout.c +++ /dev/null @@ -1,2239 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#line 3 "lex.layout.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 1 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* An opaque pointer. */ -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; -#endif - -/* For convenience, these vars (plus the bison vars far below) - are macros in the reentrant scanner. */ -#define yyin yyg->yyin_r -#define yyout yyg->yyout_r -#define yyextra yyg->yyextra_r -#define yyleng yyg->yyleng_r -#define yytext yyg->yytext_r -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) -#define yy_flex_debug yyg->yy_flex_debug_r - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yyg->yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yyg->yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE layoutrestart(yyin ,yyscanner ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE layoutlex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - #define YY_LINENO_REWIND_TO(dst) \ - do {\ - const char *p;\ - for ( p = yy_cp-1; p >= (dst); --p)\ - if ( *p == '\n' )\ - --yylineno;\ - }while(0) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = yyg->yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via layoutrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ - ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] - -void layoutrestart (FILE *input_file ,yyscan_t yyscanner ); -void layout_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE layout_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void layout_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void layout_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void layoutpop_buffer_state (yyscan_t yyscanner ); - -static void layoutensure_buffer_stack (yyscan_t yyscanner ); -static void layout_load_buffer_state (yyscan_t yyscanner ); -static void layout_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); - -#define YY_FLUSH_BUFFER layout_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) - -YY_BUFFER_STATE layout_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE layout_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE layout_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); - -void *layoutalloc (yy_size_t ,yyscan_t yyscanner ); -void *layoutrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void layoutfree (void * ,yyscan_t yyscanner ); - -#define yy_new_buffer layout_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - layoutensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - layoutensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -typedef unsigned char YY_CHAR; - -typedef int yy_state_type; - -#define yytext_ptr yytext_r - -static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); -static int yy_get_next_buffer (yyscan_t yyscanner ); -static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yyg->yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yyg->yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yyg->yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 24 -#define YY_END_OF_BUFFER 25 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[211] = - { 0, - 0, 0, 25, 23, 24, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, - 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 21, 0, 0, 0, 4, 0, - 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 12, 0, 0, 3, 0, 6, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 14, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 15, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, - 9, 0, 0, 0, 0, 0, 0, 18, 0, 0, - - 0, 0, 0, 7, 0, 0, 0, 0, 10, 0 - } ; - -static yyconst YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 1, 4, 5, 6, 7, - - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst YY_CHAR yy_meta[29] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 - } ; - -static yyconst flex_uint16_t yy_base[212] = - { 0, - 0, 25, 227, 228, 228, 5, 209, 217, 13, 220, - 24, 10, 215, 201, 210, 203, 211, 206, 17, 189, - 199, 209, 187, 204, 200, 203, 198, 187, 185, 195, - 198, 198, 187, 188, 194, 177, 182, 228, 191, 194, - 194, 174, 185, 173, 176, 181, 228, 187, 173, 177, - 181, 164, 159, 162, 178, 10, 160, 157, 173, 168, - 158, 155, 174, 159, 228, 158, 171, 161, 228, 169, - 167, 148, 166, 156, 159, 143, 148, 152, 141, 156, - 151, 150, 137, 141, 153, 133, 132, 150, 135, 131, - 228, 148, 143, 228, 131, 133, 228, 123, 228, 123, - - 133, 123, 136, 125, 118, 116, 131, 121, 129, 117, - 112, 116, 121, 119, 228, 119, 111, 126, 106, 32, - 108, 122, 108, 105, 119, 116, 102, 114, 96, 96, - 114, 98, 109, 92, 228, 107, 104, 103, 92, 105, - 85, 103, 85, 94, 228, 96, 81, 81, 76, 83, - 78, 91, 74, 80, 78, 228, 91, 85, 69, 79, - 77, 86, 80, 81, 71, 64, 228, 65, 79, 78, - 64, 52, 71, 74, 228, 71, 61, 52, 228, 65, - 63, 64, 56, 67, 46, 60, 50, 63, 53, 228, - 228, 58, 55, 45, 33, 40, 52, 228, 34, 49, - - 52, 28, 30, 228, 40, 32, 29, 16, 228, 228, - 0 - } ; - -static yyconst flex_int16_t yy_def[212] = - { 0, - 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - - 210, 210, 210, 210, 210, 210, 210, 210, 210, 0, - 210 - } ; - -static yyconst flex_uint16_t yy_nxt[257] = - { 0, - 4, 5, 210, 210, 6, 210, 210, 210, 210, 210, - 210, 7, 72, 8, 9, 10, 16, 11, 12, 17, - 210, 13, 14, 35, 21, 15, 5, 27, 18, 6, - 22, 73, 24, 28, 130, 36, 7, 209, 8, 9, - 10, 37, 11, 12, 25, 208, 13, 14, 26, 207, - 15, 206, 205, 131, 204, 203, 202, 201, 200, 199, - 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, - 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, - 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, - 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, - - 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, - 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, - 138, 137, 136, 135, 134, 133, 132, 129, 128, 127, - 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, - 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, - 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, - 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, - 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, - 76, 75, 74, 71, 70, 69, 68, 67, 66, 65, - 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, - - 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, - 44, 43, 42, 41, 40, 39, 38, 34, 33, 32, - 31, 30, 29, 23, 20, 19, 210, 3, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210 - } ; - -static yyconst flex_int16_t yy_chk[257] = - { 0, - 211, 1, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 1, 56, 1, 1, 1, 6, 1, 1, 6, - 0, 1, 1, 19, 9, 1, 2, 12, 6, 2, - 9, 56, 11, 12, 120, 19, 2, 208, 2, 2, - 2, 19, 2, 2, 11, 207, 2, 2, 11, 206, - 2, 205, 203, 120, 202, 201, 200, 199, 197, 196, - 195, 194, 193, 192, 189, 188, 187, 186, 185, 184, - 183, 182, 181, 180, 178, 177, 176, 174, 173, 172, - 171, 170, 169, 168, 166, 165, 164, 163, 162, 161, - 160, 159, 158, 157, 155, 154, 153, 152, 151, 150, - - 149, 148, 147, 146, 144, 143, 142, 141, 140, 139, - 138, 137, 136, 134, 133, 132, 131, 130, 129, 128, - 127, 126, 125, 124, 123, 122, 121, 119, 118, 117, - 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, - 105, 104, 103, 102, 101, 100, 98, 96, 95, 93, - 92, 90, 89, 88, 87, 86, 85, 84, 83, 82, - 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, - 71, 70, 68, 67, 66, 64, 63, 62, 61, 60, - 59, 58, 57, 55, 54, 53, 52, 51, 50, 49, - 48, 46, 45, 44, 43, 42, 41, 40, 39, 37, - - 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, - 26, 25, 24, 23, 22, 21, 20, 18, 17, 16, - 15, 14, 13, 10, 8, 7, 3, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210 - } ; - -/* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[25] = - { 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, }; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -#line 1 "layout.flex" -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* - - This file is IGNORED during the build process! - - As this file is updated so infrequently and flex is not universally present on build machines, - the lex.layout.c file must be manually regenerated if you make any changes to this file. Just - run: - - flex layout.flex - - You will have to manually add a copyright notice to the top of lex.layout.c. - -*/ -#define YY_NO_UNISTD_H 1 -#line 29 "layout.flex" -#include "SkSLToken.h" -#line 597 "lex.layout.c" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -/* Holds the entire state of the reentrant scanner. */ -struct yyguts_t - { - - /* User-defined. Not touched by flex. */ - YY_EXTRA_TYPE yyextra_r; - - /* The rest are the same as the globals declared in the non-reentrant scanner. */ - FILE *yyin_r, *yyout_r; - size_t yy_buffer_stack_top; /**< index of top of stack. */ - size_t yy_buffer_stack_max; /**< capacity of stack. */ - YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ - char yy_hold_char; - int yy_n_chars; - int yyleng_r; - char *yy_c_buf_p; - int yy_init; - int yy_start; - int yy_did_buffer_switch_on_eof; - int yy_start_stack_ptr; - int yy_start_stack_depth; - int *yy_start_stack; - yy_state_type yy_last_accepting_state; - char* yy_last_accepting_cpos; - - int yylineno_r; - int yy_flex_debug_r; - - char *yytext_r; - int yy_more_flag; - int yy_more_len; - - }; /* end struct yyguts_t */ - -static int yy_init_globals (yyscan_t yyscanner ); - -int layoutlex_init (yyscan_t* scanner); - -int layoutlex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int layoutlex_destroy (yyscan_t yyscanner ); - -int layoutget_debug (yyscan_t yyscanner ); - -void layoutset_debug (int debug_flag ,yyscan_t yyscanner ); - -YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner ); - -void layoutset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); - -FILE *layoutget_in (yyscan_t yyscanner ); - -void layoutset_in (FILE * _in_str ,yyscan_t yyscanner ); - -FILE *layoutget_out (yyscan_t yyscanner ); - -void layoutset_out (FILE * _out_str ,yyscan_t yyscanner ); - - int layoutget_leng (yyscan_t yyscanner ); - -char *layoutget_text (yyscan_t yyscanner ); - -int layoutget_lineno (yyscan_t yyscanner ); - -void layoutset_lineno (int _line_number ,yyscan_t yyscanner ); - -int layoutget_column (yyscan_t yyscanner ); - -void layoutset_column (int _column_no ,yyscan_t yyscanner ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int layoutwrap (yyscan_t yyscanner ); -#else -extern int layoutwrap (yyscan_t yyscanner ); -#endif -#endif - -#ifndef YY_NO_UNPUT - - static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); - -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (yyscan_t yyscanner ); -#else -static int input (yyscan_t yyscanner ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int layoutlex (yyscan_t yyscanner); - -#define YY_DECL int layoutlex (yyscan_t yyscanner) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( !yyg->yy_init ) - { - yyg->yy_init = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yyg->yy_start ) - yyg->yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - layoutensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - layout_load_buffer_state(yyscanner ); - } - - { -#line 32 "layout.flex" - - -#line 861 "lex.layout.c" - - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - yy_cp = yyg->yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yyg->yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yyg->yy_start; -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 211 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - ++yy_cp; - } - while ( yy_current_state != 210 ); - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - - YY_DO_BEFORE_ACTION; - - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - yy_size_t yyl; - for ( yyl = 0; yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - } - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yyg->yy_hold_char; - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 34 "layout.flex" -{ return SkSL::Token::LOCATION; } - YY_BREAK -case 2: -YY_RULE_SETUP -#line 35 "layout.flex" -{ return SkSL::Token::OFFSET; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 36 "layout.flex" -{ return SkSL::Token::BINDING; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 37 "layout.flex" -{ return SkSL::Token::INDEX; } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 38 "layout.flex" -{ return SkSL::Token::SET; } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 39 "layout.flex" -{ return SkSL::Token::BUILTIN; } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 40 "layout.flex" -{ return SkSL::Token::INPUT_ATTACHMENT_INDEX; } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 41 "layout.flex" -{ return SkSL::Token::ORIGIN_UPPER_LEFT; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 42 "layout.flex" -{ return SkSL::Token::OVERRIDE_COVERAGE; } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 43 "layout.flex" -{ return SkSL::Token::BLEND_SUPPORT_ALL_EQUATIONS; } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 44 "layout.flex" -{ return SkSL::Token::PUSH_CONSTANT; } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 45 "layout.flex" -{ return SkSL::Token::POINTS; } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 46 "layout.flex" -{ return SkSL::Token::LINES; } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 47 "layout.flex" -{ return SkSL::Token::LINE_STRIP; } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 48 "layout.flex" -{ return SkSL::Token::LINES_ADJACENCY; } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 49 "layout.flex" -{ return SkSL::Token::TRIANGLES; } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 50 "layout.flex" -{ return SkSL::Token::TRIANGLE_STRIP; } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 51 "layout.flex" -{ return SkSL::Token::TRIANGLES_ADJACENCY; } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 52 "layout.flex" -{ return SkSL::Token::MAX_VERTICES; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 53 "layout.flex" -{ return SkSL::Token::INVOCATIONS; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 54 "layout.flex" -{ return SkSL::Token::WHEN; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 55 "layout.flex" -{ return SkSL::Token::KEY; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 57 "layout.flex" -{ return SkSL::Token::INVALID_TOKEN; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 59 "layout.flex" -ECHO; - YY_BREAK -#line 1046 "lex.layout.c" -case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yyg->yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * layoutlex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); - - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yyg->yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_END_OF_FILE: - { - yyg->yy_did_buffer_switch_on_eof = 0; - - if ( layoutwrap(yyscanner ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = - yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yyg->yy_c_buf_p = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of layoutlex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = yyg->yytext_ptr; - yy_size_t number_to_move, i; - int ret_val; - - if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; - - int yy_c_buf_p_offset = - (int) (yyg->yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - layoutrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - yyg->yy_n_chars, num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - if ( yyg->yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - layoutrestart(yyin ,yyscanner); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - yyg->yy_n_chars += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (yyscan_t yyscanner) -{ - yy_state_type yy_current_state; - char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_current_state = yyg->yy_start; - - for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 211 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) -{ - int yy_is_jam; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - char *yy_cp = yyg->yy_c_buf_p; - - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 211 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - yy_is_jam = (yy_current_state == 210); - - (void)yyg; - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_UNPUT - - static void yyunput (int c, char * yy_bp , yyscan_t yyscanner) -{ - char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_cp = yyg->yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yyg->yy_hold_char; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - int number_to_move = yyg->yy_n_chars + 2; - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - if ( c == '\n' ){ - --yylineno; - } - - yyg->yytext_ptr = yy_bp; - yyg->yy_hold_char = *yy_cp; - yyg->yy_c_buf_p = yy_cp; -} - -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (yyscan_t yyscanner) -#else - static int input (yyscan_t yyscanner) -#endif - -{ - int c; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - *yyg->yy_c_buf_p = yyg->yy_hold_char; - - if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - /* This was really a NUL. */ - *yyg->yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; - ++yyg->yy_c_buf_p; - - switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - layoutrestart(yyin ,yyscanner); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( layoutwrap(yyscanner ) ) - return 0; - - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(yyscanner); -#else - return input(yyscanner); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = yyg->yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ - *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ - yyg->yy_hold_char = *++yyg->yy_c_buf_p; - - if ( c == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * @param yyscanner The scanner object. - * @note This function does not reset the start condition to @c INITIAL . - */ - void layoutrestart (FILE * input_file , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! YY_CURRENT_BUFFER ){ - layoutensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - layout_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - layout_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - layout_load_buffer_state(yyscanner ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * @param yyscanner The scanner object. - */ - void layout_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* TODO. We should be able to replace this entire function body - * with - * layoutpop_buffer_state(); - * layoutpush_buffer_state(new_buffer); - */ - layoutensure_buffer_stack (yyscanner); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - layout_load_buffer_state(yyscanner ); - - /* We don't actually know whether we did this switch during - * EOF (layoutwrap()) processing, but the only time this flag - * is looked at is after layoutwrap() is called, so it's safe - * to go ahead and always set it. - */ - yyg->yy_did_buffer_switch_on_eof = 1; -} - -static void layout_load_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - yyg->yy_hold_char = *yyg->yy_c_buf_p; -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * @param yyscanner The scanner object. - * @return the allocated buffer state. - */ - YY_BUFFER_STATE layout_create_buffer (FILE * file, int size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) layoutalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" ); - - b->yy_buf_size = (yy_size_t)size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) layoutalloc(b->yy_buf_size + 2 ,yyscanner ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - layout_init_buffer(b,file ,yyscanner); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with layout_create_buffer() - * @param yyscanner The scanner object. - */ - void layout_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - layoutfree((void *) b->yy_ch_buf ,yyscanner ); - - layoutfree((void *) b ,yyscanner ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a layoutrestart() or at EOF. - */ - static void layout_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) - -{ - int oerrno = errno; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - layout_flush_buffer(b ,yyscanner); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then layout_init_buffer was _probably_ - * called from layoutrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * @param yyscanner The scanner object. - */ - void layout_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - layout_load_buffer_state(yyscanner ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * @param yyscanner The scanner object. - */ -void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (new_buffer == NULL) - return; - - layoutensure_buffer_stack(yyscanner); - - /* This block is copied from layout_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - yyg->yy_buffer_stack_top++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from layout_switch_to_buffer. */ - layout_load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * @param yyscanner The scanner object. - */ -void layoutpop_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (!YY_CURRENT_BUFFER) - return; - - layout_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); - YY_CURRENT_BUFFER_LVALUE = NULL; - if (yyg->yy_buffer_stack_top > 0) - --yyg->yy_buffer_stack_top; - - if (YY_CURRENT_BUFFER) { - layout_load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void layoutensure_buffer_stack (yyscan_t yyscanner) -{ - int num_to_alloc; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (!yyg->yy_buffer_stack) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - yyg->yy_buffer_stack = (struct yy_buffer_state**)layoutalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" ); - - memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - yyg->yy_buffer_stack_max = num_to_alloc; - yyg->yy_buffer_stack_top = 0; - return; - } - - if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)layoutrealloc - (yyg->yy_buffer_stack, - num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); - yyg->yy_buffer_stack_max = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return NULL; - - b = (YY_BUFFER_STATE) layoutalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in layout_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - layout_switch_to_buffer(b ,yyscanner ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to layoutlex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * layout_scan_bytes() instead. - */ -YY_BUFFER_STATE layout_scan_string (yyconst char * yystr , yyscan_t yyscanner) -{ - - return layout_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner); -} - -/** Setup the input buffer state to scan the given bytes. The next call to layoutlex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE layout_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - yy_size_t i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) _yybytes_len + 2; - buf = (char *) layoutalloc(n ,yyscanner ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in layout_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = layout_scan_buffer(buf,n ,yyscanner); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in layout_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = yyg->yy_hold_char; \ - yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ - yyg->yy_hold_char = *yyg->yy_c_buf_p; \ - *yyg->yy_c_buf_p = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the user-defined data for this scanner. - * @param yyscanner The scanner object. - */ -YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyextra; -} - -/** Get the current line number. - * @param yyscanner The scanner object. - */ -int layoutget_lineno (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yylineno; -} - -/** Get the current column number. - * @param yyscanner The scanner object. - */ -int layoutget_column (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yycolumn; -} - -/** Get the input stream. - * @param yyscanner The scanner object. - */ -FILE *layoutget_in (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyin; -} - -/** Get the output stream. - * @param yyscanner The scanner object. - */ -FILE *layoutget_out (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyout; -} - -/** Get the length of the current token. - * @param yyscanner The scanner object. - */ -int layoutget_leng (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyleng; -} - -/** Get the current token. - * @param yyscanner The scanner object. - */ - -char *layoutget_text (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yytext; -} - -/** Set the user-defined data. This data is never touched by the scanner. - * @param user_defined The data to be associated with this scanner. - * @param yyscanner The scanner object. - */ -void layoutset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyextra = user_defined ; -} - -/** Set the current line number. - * @param _line_number line number - * @param yyscanner The scanner object. - */ -void layoutset_lineno (int _line_number , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* lineno is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "layoutset_lineno called with no buffer" ); - - yylineno = _line_number; -} - -/** Set the current column. - * @param _column_no column number - * @param yyscanner The scanner object. - */ -void layoutset_column (int _column_no , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* column is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "layoutset_column called with no buffer" ); - - yycolumn = _column_no; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param _in_str A readable stream. - * @param yyscanner The scanner object. - * @see layout_switch_to_buffer - */ -void layoutset_in (FILE * _in_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyin = _in_str ; -} - -void layoutset_out (FILE * _out_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyout = _out_str ; -} - -int layoutget_debug (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yy_flex_debug; -} - -void layoutset_debug (int _bdebug , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_flex_debug = _bdebug ; -} - -/* Accessor methods for yylval and yylloc */ - -/* User-visible API */ - -/* layoutlex_init is special because it creates the scanner itself, so it is - * the ONLY reentrant function that doesn't take the scanner as the last argument. - * That's why we explicitly handle the declaration, instead of using our macros. - */ - -int layoutlex_init(yyscan_t* ptr_yy_globals) - -{ - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), NULL ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - return yy_init_globals ( *ptr_yy_globals ); -} - -/* layoutlex_init_extra has the same functionality as layoutlex_init, but follows the - * convention of taking the scanner as the last argument. Note however, that - * this is a *pointer* to a scanner, as it will be allocated by this call (and - * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to layoutalloc in - * the yyextra field. - */ - -int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) - -{ - struct yyguts_t dummy_yyguts; - - layoutset_extra (yy_user_defined, &dummy_yyguts); - - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in - yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - layoutset_extra (yy_user_defined, *ptr_yy_globals); - - return yy_init_globals ( *ptr_yy_globals ); -} - -static int yy_init_globals (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from layoutlex_destroy(), so don't allocate here. - */ - - yyg->yy_buffer_stack = NULL; - yyg->yy_buffer_stack_top = 0; - yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = NULL; - yyg->yy_init = 0; - yyg->yy_start = 0; - - yyg->yy_start_stack_ptr = 0; - yyg->yy_start_stack_depth = 0; - yyg->yy_start_stack = NULL; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = NULL; - yyout = NULL; -#endif - - /* For future reference: Set errno on error, since we are called by - * layoutlex_init() - */ - return 0; -} - -/* layoutlex_destroy is for both reentrant and non-reentrant scanners. */ -int layoutlex_destroy (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - layout_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); - YY_CURRENT_BUFFER_LVALUE = NULL; - layoutpop_buffer_state(yyscanner); - } - - /* Destroy the stack itself. */ - layoutfree(yyg->yy_buffer_stack ,yyscanner); - yyg->yy_buffer_stack = NULL; - - /* Destroy the start condition stack. */ - layoutfree(yyg->yy_start_stack ,yyscanner ); - yyg->yy_start_stack = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * layoutlex() is called, initialization will occur. */ - yy_init_globals( yyscanner); - - /* Destroy the main struct (reentrant only). */ - layoutfree ( yyscanner , yyscanner ); - yyscanner = NULL; - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *layoutalloc (yy_size_t size , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - return malloc(size); -} - -void *layoutrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return realloc(ptr, size); -} - -void layoutfree (void * ptr , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - free( (char *) ptr ); /* see layoutrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 59 "layout.flex" - - - -int layoutwrap(yyscan_t scanner) { - return 1; // terminate -} - diff --git a/src/sksl/lex.layout.cpp b/src/sksl/lex.layout.cpp deleted file mode 100644 index 937c93190e..0000000000 --- a/src/sksl/lex.layout.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "disable_flex_warnings.h" -#include "lex.layout.c" -static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 + - YY_FLEX_SUBMINOR_VERSION >= 20601, - "we require Flex 2.6.1 or better for security reasons"); diff --git a/src/sksl/lex.layout.h b/src/sksl/lex.layout.h deleted file mode 100644 index 345b336253..0000000000 --- a/src/sksl/lex.layout.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -int layoutlex_init(yyscan_t* ptr_yy_globals); -int layoutlex_destroy(void* scanner); -YY_BUFFER_STATE layout_scan_string(const char* s, void* scanner); -int layoutlex(void* yyscanner); -void layout_delete_buffer(YY_BUFFER_STATE b, void* yyscanner); diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c deleted file mode 100644 index 6e44f5aea7..0000000000 --- a/src/sksl/lex.sksl.c +++ /dev/null @@ -1,2682 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#line 3 "lex.sksl.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 1 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* An opaque pointer. */ -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; -#endif - -/* For convenience, these vars (plus the bison vars far below) - are macros in the reentrant scanner. */ -#define yyin yyg->yyin_r -#define yyout yyg->yyout_r -#define yyextra yyg->yyextra_r -#define yyleng yyg->yyleng_r -#define yytext yyg->yytext_r -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) -#define yy_flex_debug yyg->yy_flex_debug_r - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yyg->yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yyg->yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE skslrestart(yyin ,yyscanner ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE sksllex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - #define YY_LINENO_REWIND_TO(dst) \ - do {\ - const char *p;\ - for ( p = yy_cp-1; p >= (dst); --p)\ - if ( *p == '\n' )\ - --yylineno;\ - }while(0) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = yyg->yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via skslrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ - ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] - -void skslrestart (FILE *input_file ,yyscan_t yyscanner ); -void sksl_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE sksl_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void sksl_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void sksl_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void skslpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void skslpop_buffer_state (yyscan_t yyscanner ); - -static void skslensure_buffer_stack (yyscan_t yyscanner ); -static void sksl_load_buffer_state (yyscan_t yyscanner ); -static void sksl_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); - -#define YY_FLUSH_BUFFER sksl_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) - -YY_BUFFER_STATE sksl_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE sksl_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE sksl_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); - -void *skslalloc (yy_size_t ,yyscan_t yyscanner ); -void *skslrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void skslfree (void * ,yyscan_t yyscanner ); - -#define yy_new_buffer sksl_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - skslensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - skslensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ - -typedef unsigned char YY_CHAR; - -typedef int yy_state_type; - -#define yytext_ptr yytext_r - -static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); -static int yy_get_next_buffer (yyscan_t yyscanner ); -static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yyg->yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yyg->yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yyg->yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 99 -#define YY_END_OF_BUFFER 100 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[289] = - { 0, - 0, 0, 100, 98, 95, 95, 69, 98, 42, 59, - 64, 45, 46, 57, 55, 52, 56, 51, 58, 4, - 4, 71, 92, 76, 72, 75, 70, 98, 49, 50, - 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, - 62, 48, 65, 95, 74, 43, 42, 83, 68, 88, - 81, 53, 79, 54, 80, 93, 1, 0, 96, 82, - 2, 4, 0, 0, 94, 60, 78, 73, 77, 61, - 44, 44, 44, 87, 67, 42, 42, 42, 42, 42, - 42, 13, 42, 42, 42, 42, 42, 8, 22, 42, - - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 86, 66, 43, 91, 0, 0, - 0, 96, 1, 0, 0, 3, 5, 84, 85, 44, - 9, 44, 90, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 11, 42, 42, 42, 42, 42, 42, - 23, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 89, 0, 1, 97, 0, 0, 2, - 44, 42, 42, 16, 42, 42, 42, 42, 42, 10, - 42, 30, 42, 42, 42, 27, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 6, 42, 42, 42, 42, - - 0, 1, 44, 18, 42, 42, 26, 42, 42, 42, - 7, 29, 24, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 12, 42, 44, 37, 42, - 42, 42, 42, 40, 42, 42, 42, 42, 42, 21, - 42, 39, 14, 42, 42, 42, 15, 42, 42, 17, - 20, 28, 42, 42, 42, 42, 42, 25, 42, 42, - 34, 19, 42, 42, 32, 36, 42, 35, 42, 42, - 41, 42, 33, 42, 42, 42, 42, 42, 42, 31, - 42, 42, 42, 42, 42, 42, 38, 0 - } ; - -static yyconst YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 1, 5, 6, 7, 8, 1, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 26, 26, 26, 27, 26, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 28, 1, 29, 30, 31, 1, 32, 33, 34, 35, - - 36, 37, 38, 39, 40, 6, 41, 42, 43, 44, - 45, 46, 6, 47, 48, 49, 50, 51, 52, 53, - 54, 6, 55, 56, 57, 58, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst YY_CHAR yy_meta[59] = - { 0, - 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, - 1, 1, 1, 1, 1, 5, 5, 1, 1, 1, - 3, 5, 5, 5, 5, 5, 5, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 1, 1, 1, 1 - } ; - -static yyconst flex_uint16_t yy_base[297] = - { 0, - 0, 0, 360, 361, 57, 59, 337, 0, 0, 336, - 55, 361, 361, 335, 52, 361, 53, 48, 57, 54, - 65, 337, 361, 63, 333, 64, 361, 30, 361, 361, - 66, 44, 57, 59, 312, 61, 313, 61, 65, 316, - 306, 300, 302, 312, 59, 300, 302, 300, 70, 361, - 90, 361, 361, 111, 361, 0, 0, 361, 322, 361, - 361, 361, 361, 361, 361, 361, 98, 332, 0, 361, - 101, 105, 112, 0, 361, 320, 361, 361, 361, 319, - 0, 303, 287, 361, 316, 301, 299, 287, 92, 297, - 285, 0, 284, 289, 298, 282, 290, 0, 282, 272, - - 273, 289, 277, 273, 285, 95, 289, 272, 278, 267, - 276, 273, 274, 273, 361, 290, 0, 361, 121, 300, - 294, 0, 130, 137, 135, 141, 0, 361, 361, 0, - 0, 269, 361, 276, 270, 270, 269, 112, 272, 269, - 266, 253, 251, 0, 260, 248, 252, 250, 255, 258, - 0, 259, 257, 242, 240, 250, 238, 238, 250, 248, - 252, 241, 233, 361, 145, 147, 361, 155, 153, 157, - 232, 239, 243, 0, 231, 228, 236, 225, 242, 0, - 237, 0, 226, 222, 220, 0, 219, 221, 227, 221, - 218, 217, 231, 228, 227, 0, 215, 210, 222, 221, - - 159, 161, 222, 0, 208, 218, 0, 209, 210, 204, - 0, 0, 0, 201, 206, 200, 199, 202, 205, 200, - 195, 193, 202, 193, 199, 0, 193, 198, 0, 192, - 185, 185, 198, 0, 186, 185, 190, 187, 194, 0, - 196, 0, 0, 183, 183, 180, 0, 174, 186, 0, - 0, 0, 185, 175, 165, 169, 169, 0, 180, 173, - 0, 0, 180, 169, 0, 0, 172, 0, 157, 161, - 0, 174, 0, 168, 171, 147, 156, 145, 132, 0, - 119, 113, 109, 108, 91, 73, 0, 361, 177, 180, - 183, 186, 191, 196, 198, 201 - - } ; - -static yyconst flex_int16_t yy_def[297] = - { 0, - 288, 1, 288, 288, 288, 288, 288, 289, 290, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 291, 288, 288, - 288, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 288, - 288, 288, 288, 288, 288, 292, 290, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 293, 294, 288, - 288, 288, 288, 295, 288, 288, 288, 288, 288, 288, - 296, 296, 296, 288, 288, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 288, 288, 292, 288, 288, 293, - 293, 294, 288, 288, 288, 288, 295, 288, 288, 296, - 296, 296, 288, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 288, 288, 288, 288, 288, 288, 288, - 296, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - - 288, 288, 296, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 296, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 296, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 0, 288, 288, - 288, 288, 288, 288, 288, 288 - - } ; - -static yyconst flex_uint16_t yy_nxt[420] = - { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 9, 9, 29, 30, 31, - 9, 9, 32, 33, 34, 35, 36, 9, 37, 38, - 9, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 9, 9, 50, 51, 52, 53, 54, 54, - 54, 54, 59, 62, 67, 67, 64, 68, 71, 82, - 72, 72, 69, 63, 65, 66, 60, 83, 70, 71, - 73, 72, 72, 76, 77, 79, 80, 84, 88, 73, - 86, 73, 94, 87, 90, 85, 100, 98, 91, 107, - - 73, 89, 95, 92, 99, 96, 74, 108, 113, 101, - 109, 115, 54, 54, 67, 67, 114, 123, 123, 71, - 287, 72, 72, 125, 119, 125, 153, 124, 126, 126, - 137, 73, 165, 119, 165, 138, 124, 166, 166, 286, - 73, 285, 154, 155, 284, 116, 123, 123, 169, 283, - 169, 126, 126, 170, 170, 282, 168, 126, 126, 176, - 177, 166, 166, 166, 166, 168, 201, 281, 201, 170, - 170, 202, 202, 170, 170, 202, 202, 202, 202, 56, - 280, 56, 57, 57, 57, 81, 279, 81, 117, 117, - 117, 120, 120, 120, 120, 120, 122, 278, 122, 122, - - 122, 127, 127, 130, 130, 130, 277, 276, 275, 274, - 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, - 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, - 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, - 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, - 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, - 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, - 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, - 203, 200, 199, 198, 197, 196, 195, 194, 193, 192, - 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, - - 181, 180, 179, 178, 175, 174, 173, 172, 171, 167, - 121, 164, 163, 162, 161, 160, 159, 158, 157, 156, - 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, - 142, 141, 140, 139, 136, 135, 134, 133, 132, 131, - 129, 128, 121, 118, 112, 111, 110, 106, 105, 104, - 103, 102, 97, 93, 78, 75, 61, 58, 55, 288, - 3, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288 - } ; - -static yyconst flex_int16_t yy_chk[420] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, - 6, 6, 11, 15, 18, 18, 17, 19, 20, 28, - 20, 20, 19, 15, 17, 17, 11, 28, 19, 21, - 20, 21, 21, 24, 24, 26, 26, 31, 33, 20, - 32, 21, 36, 32, 34, 31, 39, 38, 34, 45, - - 21, 33, 36, 34, 38, 36, 20, 45, 49, 39, - 45, 51, 54, 54, 67, 67, 49, 71, 71, 72, - 286, 72, 72, 73, 67, 73, 106, 71, 73, 73, - 89, 72, 119, 67, 119, 89, 71, 119, 119, 285, - 72, 284, 106, 106, 283, 51, 123, 123, 124, 282, - 124, 125, 125, 124, 124, 281, 123, 126, 126, 138, - 138, 165, 165, 166, 166, 123, 168, 279, 168, 169, - 169, 168, 168, 170, 170, 201, 201, 202, 202, 289, - 278, 289, 290, 290, 290, 291, 277, 291, 292, 292, - 292, 293, 293, 293, 293, 293, 294, 276, 294, 294, - - 294, 295, 295, 296, 296, 296, 275, 274, 272, 270, - 269, 267, 264, 263, 260, 259, 257, 256, 255, 254, - 253, 249, 248, 246, 245, 244, 241, 239, 238, 237, - 236, 235, 233, 232, 231, 230, 228, 227, 225, 224, - 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, - 210, 209, 208, 206, 205, 203, 200, 199, 198, 197, - 195, 194, 193, 192, 191, 190, 189, 188, 187, 185, - 184, 183, 181, 179, 178, 177, 176, 175, 173, 172, - 171, 163, 162, 161, 160, 159, 158, 157, 156, 155, - 154, 153, 152, 150, 149, 148, 147, 146, 145, 143, - - 142, 141, 140, 139, 137, 136, 135, 134, 132, 121, - 120, 116, 114, 113, 112, 111, 110, 109, 108, 107, - 105, 104, 103, 102, 101, 100, 99, 97, 96, 95, - 94, 93, 91, 90, 88, 87, 86, 85, 83, 82, - 80, 76, 68, 59, 48, 47, 46, 44, 43, 42, - 41, 40, 37, 35, 25, 22, 14, 10, 7, 3, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - - 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 288, 288, 288, 288, 288, 288, 288 - } ; - -/* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[100] = - { 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, - }; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -#line 1 "sksl.flex" -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* - - This file is IGNORED during the build process! - - As this file is updated so infrequently and flex is not universally present on build machines, - the lex.sksl.c file must be manually regenerated if you make any changes to this file. Just run: - - flex sksl.flex - - You will have to manually add a copyright notice to the top of lex.sksl.c. - -*/ -#define YY_NO_UNISTD_H 1 -#line 663 "lex.sksl.c" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -/* Holds the entire state of the reentrant scanner. */ -struct yyguts_t - { - - /* User-defined. Not touched by flex. */ - YY_EXTRA_TYPE yyextra_r; - - /* The rest are the same as the globals declared in the non-reentrant scanner. */ - FILE *yyin_r, *yyout_r; - size_t yy_buffer_stack_top; /**< index of top of stack. */ - size_t yy_buffer_stack_max; /**< capacity of stack. */ - YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ - char yy_hold_char; - int yy_n_chars; - int yyleng_r; - char *yy_c_buf_p; - int yy_init; - int yy_start; - int yy_did_buffer_switch_on_eof; - int yy_start_stack_ptr; - int yy_start_stack_depth; - int *yy_start_stack; - yy_state_type yy_last_accepting_state; - char* yy_last_accepting_cpos; - - int yylineno_r; - int yy_flex_debug_r; - - char *yytext_r; - int yy_more_flag; - int yy_more_len; - - }; /* end struct yyguts_t */ - -static int yy_init_globals (yyscan_t yyscanner ); - -int sksllex_init (yyscan_t* scanner); - -int sksllex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int sksllex_destroy (yyscan_t yyscanner ); - -int skslget_debug (yyscan_t yyscanner ); - -void skslset_debug (int debug_flag ,yyscan_t yyscanner ); - -YY_EXTRA_TYPE skslget_extra (yyscan_t yyscanner ); - -void skslset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); - -FILE *skslget_in (yyscan_t yyscanner ); - -void skslset_in (FILE * _in_str ,yyscan_t yyscanner ); - -FILE *skslget_out (yyscan_t yyscanner ); - -void skslset_out (FILE * _out_str ,yyscan_t yyscanner ); - - int skslget_leng (yyscan_t yyscanner ); - -char *skslget_text (yyscan_t yyscanner ); - -int skslget_lineno (yyscan_t yyscanner ); - -void skslset_lineno (int _line_number ,yyscan_t yyscanner ); - -int skslget_column (yyscan_t yyscanner ); - -void skslset_column (int _column_no ,yyscan_t yyscanner ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int skslwrap (yyscan_t yyscanner ); -#else -extern int skslwrap (yyscan_t yyscanner ); -#endif -#endif - -#ifndef YY_NO_UNPUT - - static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); - -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (yyscan_t yyscanner ); -#else -static int input (yyscan_t yyscanner ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int sksllex (yyscan_t yyscanner); - -#define YY_DECL int sksllex (yyscan_t yyscanner) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( !yyg->yy_init ) - { - yyg->yy_init = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yyg->yy_start ) - yyg->yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - skslensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - sksl_load_buffer_state(yyscanner ); - } - - { -#line 30 "sksl.flex" - - -#line 927 "lex.sksl.c" - - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - yy_cp = yyg->yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yyg->yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yyg->yy_start; -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 289 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - ++yy_cp; - } - while ( yy_current_state != 288 ); - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - - YY_DO_BEFORE_ACTION; - - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - yy_size_t yyl; - for ( yyl = 0; yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - } - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yyg->yy_hold_char; - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 32 "sksl.flex" -{ return SkSL::Token::FLOAT_LITERAL; } - YY_BREAK -case 2: -YY_RULE_SETUP -#line 34 "sksl.flex" -{ return SkSL::Token::FLOAT_LITERAL; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 36 "sksl.flex" -{ return SkSL::Token::FLOAT_LITERAL; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 38 "sksl.flex" -{ return SkSL::Token::INT_LITERAL; } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 40 "sksl.flex" -{ return SkSL::Token::INT_LITERAL; } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 42 "sksl.flex" -{ return SkSL::Token::TRUE_LITERAL; } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 44 "sksl.flex" -{ return SkSL::Token::FALSE_LITERAL; } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 46 "sksl.flex" -{ return SkSL::Token::IF; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 48 "sksl.flex" -{ return SkSL::Token::STATIC_IF; } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 50 "sksl.flex" -{ return SkSL::Token::ELSE; } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 52 "sksl.flex" -{ return SkSL::Token::FOR; } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 54 "sksl.flex" -{ return SkSL::Token::WHILE; } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 56 "sksl.flex" -{ return SkSL::Token::DO; } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 58 "sksl.flex" -{ return SkSL::Token::SWITCH; } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 60 "sksl.flex" -{ return SkSL::Token::STATIC_SWITCH; } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 62 "sksl.flex" -{ return SkSL::Token::CASE; } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 64 "sksl.flex" -{ return SkSL::Token::DEFAULT; } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 66 "sksl.flex" -{ return SkSL::Token::BREAK; } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 68 "sksl.flex" -{ return SkSL::Token::CONTINUE; } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 70 "sksl.flex" -{ return SkSL::Token::DISCARD; } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 72 "sksl.flex" -{ return SkSL::Token::RETURN; } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 74 "sksl.flex" -{ return SkSL::Token::IN; } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 76 "sksl.flex" -{ return SkSL::Token::OUT; } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 78 "sksl.flex" -{ return SkSL::Token::INOUT; } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 80 "sksl.flex" -{ return SkSL::Token::UNIFORM; } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 82 "sksl.flex" -{ return SkSL::Token::CONST; } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 84 "sksl.flex" -{ return SkSL::Token::LOWP; } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 86 "sksl.flex" -{ return SkSL::Token::MEDIUMP; } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 88 "sksl.flex" -{ return SkSL::Token::HIGHP; } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 90 "sksl.flex" -{ return SkSL::Token::FLAT; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 92 "sksl.flex" -{ return SkSL::Token::NOPERSPECTIVE; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 94 "sksl.flex" -{ return SkSL::Token::READONLY; } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 96 "sksl.flex" -{ return SkSL::Token::WRITEONLY; } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 98 "sksl.flex" -{ return SkSL::Token::COHERENT; } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 100 "sksl.flex" -{ return SkSL::Token::VOLATILE; } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 102 "sksl.flex" -{ return SkSL::Token::RESTRICT; } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 104 "sksl.flex" -{ return SkSL::Token::BUFFER; } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 106 "sksl.flex" -{ return SkSL::Token::HASSIDEEFFECTS; } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 108 "sksl.flex" -{ return SkSL::Token::STRUCT; } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 110 "sksl.flex" -{ return SkSL::Token::LAYOUT; } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 112 "sksl.flex" -{ return SkSL::Token::PRECISION; } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 114 "sksl.flex" -{ return SkSL::Token::IDENTIFIER; } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 116 "sksl.flex" -{ return SkSL::Token::DIRECTIVE; } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 118 "sksl.flex" -{ return SkSL::Token::SECTION; } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 120 "sksl.flex" -{ return SkSL::Token::LPAREN; } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 122 "sksl.flex" -{ return SkSL::Token::RPAREN; } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 124 "sksl.flex" -{ return SkSL::Token::LBRACE; } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 126 "sksl.flex" -{ return SkSL::Token::RBRACE; } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 128 "sksl.flex" -{ return SkSL::Token::LBRACKET; } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 130 "sksl.flex" -{ return SkSL::Token::RBRACKET; } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 132 "sksl.flex" -{ return SkSL::Token::DOT; } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 134 "sksl.flex" -{ return SkSL::Token::COMMA; } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 136 "sksl.flex" -{ return SkSL::Token::PLUSPLUS; } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 138 "sksl.flex" -{ return SkSL::Token::MINUSMINUS; } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 140 "sksl.flex" -{ return SkSL::Token::PLUS; } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 142 "sksl.flex" -{ return SkSL::Token::MINUS; } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 144 "sksl.flex" -{ return SkSL::Token::STAR; } - YY_BREAK -case 58: -YY_RULE_SETUP -#line 146 "sksl.flex" -{ return SkSL::Token::SLASH; } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 148 "sksl.flex" -{ return SkSL::Token::PERCENT; } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 150 "sksl.flex" -{ return SkSL::Token::SHL; } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 152 "sksl.flex" -{ return SkSL::Token::SHR; } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 154 "sksl.flex" -{ return SkSL::Token::BITWISEOR; } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 156 "sksl.flex" -{ return SkSL::Token::BITWISEXOR; } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 158 "sksl.flex" -{ return SkSL::Token::BITWISEAND; } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 160 "sksl.flex" -{ return SkSL::Token::BITWISENOT; } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 162 "sksl.flex" -{ return SkSL::Token::LOGICALOR; } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 164 "sksl.flex" -{ return SkSL::Token::LOGICALXOR; } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 166 "sksl.flex" -{ return SkSL::Token::LOGICALAND; } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 168 "sksl.flex" -{ return SkSL::Token::LOGICALNOT; } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 170 "sksl.flex" -{ return SkSL::Token::QUESTION; } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 172 "sksl.flex" -{ return SkSL::Token::COLON; } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 174 "sksl.flex" -{ return SkSL::Token::EQ; } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 176 "sksl.flex" -{ return SkSL::Token::EQEQ; } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 178 "sksl.flex" -{ return SkSL::Token::NEQ; } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 180 "sksl.flex" -{ return SkSL::Token::GT; } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 182 "sksl.flex" -{ return SkSL::Token::LT; } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 184 "sksl.flex" -{ return SkSL::Token::GTEQ; } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 186 "sksl.flex" -{ return SkSL::Token::LTEQ; } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 188 "sksl.flex" -{ return SkSL::Token::PLUSEQ; } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 190 "sksl.flex" -{ return SkSL::Token::MINUSEQ; } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 192 "sksl.flex" -{ return SkSL::Token::STAREQ; } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 194 "sksl.flex" -{ return SkSL::Token::SLASHEQ; } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 196 "sksl.flex" -{ return SkSL::Token::PERCENTEQ; } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 198 "sksl.flex" -{ return SkSL::Token::SHLEQ; } - YY_BREAK -case 85: -YY_RULE_SETUP -#line 200 "sksl.flex" -{ return SkSL::Token::SHREQ; } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 202 "sksl.flex" -{ return SkSL::Token::BITWISEOREQ; } - YY_BREAK -case 87: -YY_RULE_SETUP -#line 204 "sksl.flex" -{ return SkSL::Token::BITWISEXOREQ; } - YY_BREAK -case 88: -YY_RULE_SETUP -#line 206 "sksl.flex" -{ return SkSL::Token::BITWISEANDEQ; } - YY_BREAK -case 89: -YY_RULE_SETUP -#line 208 "sksl.flex" -{ return SkSL::Token::LOGICALOREQ; } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 210 "sksl.flex" -{ return SkSL::Token::LOGICALXOREQ; } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 212 "sksl.flex" -{ return SkSL::Token::LOGICALANDEQ; } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 214 "sksl.flex" -{ return SkSL::Token::SEMICOLON; } - YY_BREAK -case 93: -YY_RULE_SETUP -#line 216 "sksl.flex" -{ return SkSL::Token::ARROW; } - YY_BREAK -case 94: -YY_RULE_SETUP -#line 218 "sksl.flex" -{ return SkSL::Token::COLONCOLON; } - YY_BREAK -case 95: -/* rule 95 can match eol */ -YY_RULE_SETUP -#line 220 "sksl.flex" -{ return SkSL::Token::WHITESPACE; } - YY_BREAK -case 96: -YY_RULE_SETUP -#line 222 "sksl.flex" -/* line comment */ - YY_BREAK -case 97: -/* rule 97 can match eol */ -YY_RULE_SETUP -#line 224 "sksl.flex" -/* block comment */ - YY_BREAK -case 98: -YY_RULE_SETUP -#line 226 "sksl.flex" -{ return SkSL::Token::INVALID_TOKEN; } - YY_BREAK -case 99: -YY_RULE_SETUP -#line 228 "sksl.flex" -ECHO; - YY_BREAK -#line 1489 "lex.sksl.c" -case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yyg->yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * sksllex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); - - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yyg->yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_END_OF_FILE: - { - yyg->yy_did_buffer_switch_on_eof = 0; - - if ( skslwrap(yyscanner ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = - yyg->yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yyg->yy_c_buf_p = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; - - yy_current_state = yy_get_previous_state( yyscanner ); - - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of sksllex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = yyg->yytext_ptr; - yy_size_t number_to_move, i; - int ret_val; - - if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; - - int yy_c_buf_p_offset = - (int) (yyg->yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - skslrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - yyg->yy_n_chars, num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - if ( yyg->yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - skslrestart(yyin ,yyscanner); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) skslrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - yyg->yy_n_chars += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (yyscan_t yyscanner) -{ - yy_state_type yy_current_state; - char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_current_state = yyg->yy_start; - - for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 289 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) -{ - int yy_is_jam; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - char *yy_cp = yyg->yy_c_buf_p; - - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 289 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - yy_is_jam = (yy_current_state == 288); - - (void)yyg; - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_UNPUT - - static void yyunput (int c, char * yy_bp , yyscan_t yyscanner) -{ - char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_cp = yyg->yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yyg->yy_hold_char; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - int number_to_move = yyg->yy_n_chars + 2; - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - if ( c == '\n' ){ - --yylineno; - } - - yyg->yytext_ptr = yy_bp; - yyg->yy_hold_char = *yy_cp; - yyg->yy_c_buf_p = yy_cp; -} - -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (yyscan_t yyscanner) -#else - static int input (yyscan_t yyscanner) -#endif - -{ - int c; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - *yyg->yy_c_buf_p = yyg->yy_hold_char; - - if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - /* This was really a NUL. */ - *yyg->yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; - ++yyg->yy_c_buf_p; - - switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - skslrestart(yyin ,yyscanner); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( skslwrap(yyscanner ) ) - return 0; - - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(yyscanner); -#else - return input(yyscanner); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = yyg->yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ - *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ - yyg->yy_hold_char = *++yyg->yy_c_buf_p; - - if ( c == '\n' ) - - do{ yylineno++; - yycolumn=0; - }while(0) -; - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * @param yyscanner The scanner object. - * @note This function does not reset the start condition to @c INITIAL . - */ - void skslrestart (FILE * input_file , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! YY_CURRENT_BUFFER ){ - skslensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - sksl_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); - } - - sksl_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - sksl_load_buffer_state(yyscanner ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * @param yyscanner The scanner object. - */ - void sksl_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* TODO. We should be able to replace this entire function body - * with - * skslpop_buffer_state(); - * skslpush_buffer_state(new_buffer); - */ - skslensure_buffer_stack (yyscanner); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - sksl_load_buffer_state(yyscanner ); - - /* We don't actually know whether we did this switch during - * EOF (skslwrap()) processing, but the only time this flag - * is looked at is after skslwrap() is called, so it's safe - * to go ahead and always set it. - */ - yyg->yy_did_buffer_switch_on_eof = 1; -} - -static void sksl_load_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - yyg->yy_hold_char = *yyg->yy_c_buf_p; -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * @param yyscanner The scanner object. - * @return the allocated buffer state. - */ - YY_BUFFER_STATE sksl_create_buffer (FILE * file, int size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) skslalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in sksl_create_buffer()" ); - - b->yy_buf_size = (yy_size_t)size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) skslalloc(b->yy_buf_size + 2 ,yyscanner ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in sksl_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - sksl_init_buffer(b,file ,yyscanner); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with sksl_create_buffer() - * @param yyscanner The scanner object. - */ - void sksl_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - skslfree((void *) b->yy_ch_buf ,yyscanner ); - - skslfree((void *) b ,yyscanner ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a skslrestart() or at EOF. - */ - static void sksl_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) - -{ - int oerrno = errno; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - sksl_flush_buffer(b ,yyscanner); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then sksl_init_buffer was _probably_ - * called from skslrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * @param yyscanner The scanner object. - */ - void sksl_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - sksl_load_buffer_state(yyscanner ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * @param yyscanner The scanner object. - */ -void skslpush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (new_buffer == NULL) - return; - - skslensure_buffer_stack(yyscanner); - - /* This block is copied from sksl_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - yyg->yy_buffer_stack_top++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from sksl_switch_to_buffer. */ - sksl_load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * @param yyscanner The scanner object. - */ -void skslpop_buffer_state (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (!YY_CURRENT_BUFFER) - return; - - sksl_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); - YY_CURRENT_BUFFER_LVALUE = NULL; - if (yyg->yy_buffer_stack_top > 0) - --yyg->yy_buffer_stack_top; - - if (YY_CURRENT_BUFFER) { - sksl_load_buffer_state(yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void skslensure_buffer_stack (yyscan_t yyscanner) -{ - int num_to_alloc; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (!yyg->yy_buffer_stack) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - yyg->yy_buffer_stack = (struct yy_buffer_state**)skslalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in skslensure_buffer_stack()" ); - - memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - yyg->yy_buffer_stack_max = num_to_alloc; - yyg->yy_buffer_stack_top = 0; - return; - } - - if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)skslrealloc - (yyg->yy_buffer_stack, - num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in skslensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); - yyg->yy_buffer_stack_max = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE sksl_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return NULL; - - b = (YY_BUFFER_STATE) skslalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in sksl_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - sksl_switch_to_buffer(b ,yyscanner ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to sksllex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * sksl_scan_bytes() instead. - */ -YY_BUFFER_STATE sksl_scan_string (yyconst char * yystr , yyscan_t yyscanner) -{ - - return sksl_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner); -} - -/** Setup the input buffer state to scan the given bytes. The next call to sksllex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE sksl_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - yy_size_t i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) _yybytes_len + 2; - buf = (char *) skslalloc(n ,yyscanner ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in sksl_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = sksl_scan_buffer(buf,n ,yyscanner); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in sksl_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = yyg->yy_hold_char; \ - yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ - yyg->yy_hold_char = *yyg->yy_c_buf_p; \ - *yyg->yy_c_buf_p = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the user-defined data for this scanner. - * @param yyscanner The scanner object. - */ -YY_EXTRA_TYPE skslget_extra (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyextra; -} - -/** Get the current line number. - * @param yyscanner The scanner object. - */ -int skslget_lineno (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yylineno; -} - -/** Get the current column number. - * @param yyscanner The scanner object. - */ -int skslget_column (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if (! YY_CURRENT_BUFFER) - return 0; - - return yycolumn; -} - -/** Get the input stream. - * @param yyscanner The scanner object. - */ -FILE *skslget_in (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyin; -} - -/** Get the output stream. - * @param yyscanner The scanner object. - */ -FILE *skslget_out (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyout; -} - -/** Get the length of the current token. - * @param yyscanner The scanner object. - */ -int skslget_leng (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyleng; -} - -/** Get the current token. - * @param yyscanner The scanner object. - */ - -char *skslget_text (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yytext; -} - -/** Set the user-defined data. This data is never touched by the scanner. - * @param user_defined The data to be associated with this scanner. - * @param yyscanner The scanner object. - */ -void skslset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyextra = user_defined ; -} - -/** Set the current line number. - * @param _line_number line number - * @param yyscanner The scanner object. - */ -void skslset_lineno (int _line_number , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* lineno is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "skslset_lineno called with no buffer" ); - - yylineno = _line_number; -} - -/** Set the current column. - * @param _column_no column number - * @param yyscanner The scanner object. - */ -void skslset_column (int _column_no , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* column is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "skslset_column called with no buffer" ); - - yycolumn = _column_no; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param _in_str A readable stream. - * @param yyscanner The scanner object. - * @see sksl_switch_to_buffer - */ -void skslset_in (FILE * _in_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyin = _in_str ; -} - -void skslset_out (FILE * _out_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyout = _out_str ; -} - -int skslget_debug (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yy_flex_debug; -} - -void skslset_debug (int _bdebug , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_flex_debug = _bdebug ; -} - -/* Accessor methods for yylval and yylloc */ - -/* User-visible API */ - -/* sksllex_init is special because it creates the scanner itself, so it is - * the ONLY reentrant function that doesn't take the scanner as the last argument. - * That's why we explicitly handle the declaration, instead of using our macros. - */ - -int sksllex_init(yyscan_t* ptr_yy_globals) - -{ - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) skslalloc ( sizeof( struct yyguts_t ), NULL ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - return yy_init_globals ( *ptr_yy_globals ); -} - -/* sksllex_init_extra has the same functionality as sksllex_init, but follows the - * convention of taking the scanner as the last argument. Note however, that - * this is a *pointer* to a scanner, as it will be allocated by this call (and - * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to skslalloc in - * the yyextra field. - */ - -int sksllex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) - -{ - struct yyguts_t dummy_yyguts; - - skslset_extra (yy_user_defined, &dummy_yyguts); - - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) skslalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - /* By setting to 0xAA, we expose bugs in - yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - skslset_extra (yy_user_defined, *ptr_yy_globals); - - return yy_init_globals ( *ptr_yy_globals ); -} - -static int yy_init_globals (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from sksllex_destroy(), so don't allocate here. - */ - - yyg->yy_buffer_stack = NULL; - yyg->yy_buffer_stack_top = 0; - yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = NULL; - yyg->yy_init = 0; - yyg->yy_start = 0; - - yyg->yy_start_stack_ptr = 0; - yyg->yy_start_stack_depth = 0; - yyg->yy_start_stack = NULL; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = NULL; - yyout = NULL; -#endif - - /* For future reference: Set errno on error, since we are called by - * sksllex_init() - */ - return 0; -} - -/* sksllex_destroy is for both reentrant and non-reentrant scanners. */ -int sksllex_destroy (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - sksl_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); - YY_CURRENT_BUFFER_LVALUE = NULL; - skslpop_buffer_state(yyscanner); - } - - /* Destroy the stack itself. */ - skslfree(yyg->yy_buffer_stack ,yyscanner); - yyg->yy_buffer_stack = NULL; - - /* Destroy the start condition stack. */ - skslfree(yyg->yy_start_stack ,yyscanner ); - yyg->yy_start_stack = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * sksllex() is called, initialization will occur. */ - yy_init_globals( yyscanner); - - /* Destroy the main struct (reentrant only). */ - skslfree ( yyscanner , yyscanner ); - yyscanner = NULL; - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *skslalloc (yy_size_t size , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - return malloc(size); -} - -void *skslrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return realloc(ptr, size); -} - -void skslfree (void * ptr , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - free( (char *) ptr ); /* see skslrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 228 "sksl.flex" - - - -int skslwrap(yyscan_t scanner) { - return 1; // terminate -} - diff --git a/src/sksl/lex/layout.lex b/src/sksl/lex/layout.lex new file mode 100644 index 0000000000..66d30881c1 --- /dev/null +++ b/src/sksl/lex/layout.lex @@ -0,0 +1,23 @@ +LOCATION = "location" +OFFSET = "offset" +BINDING = "binding" +INDEX = "index" +SET = "set" +BUILTIN = "builtin" +INPUT_ATTACHMENT_INDEX = "input_attachment_index" +ORIGIN_UPPER_LEFT = "origin_upper_left" +OVERRIDE_COVERAGE = "override_coverage" +BLEND_SUPPORT_ALL_EQUATIONS = "blend_support_all_equations" +PUSH_CONSTANT = "push_constant" +POINTS = "points" +LINES = "lines" +LINE_STRIP = "line_strip" +LINES_ADJACENCY = "lines_adjacency" +TRIANGLES = "triangles" +TRIANGLE_STRIP = "triangle_strip" +TRIANGLES_ADJACENCY = "triangles_adjacency" +MAX_VERTICES = "max_vertices" +INVOCATIONS = "invocations" +WHEN = "when" +KEY = "key" +INVALID = . diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex deleted file mode 100644 index 275a4e6633..0000000000 --- a/src/sksl/sksl.flex +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - - This file is IGNORED during the build process! - - As this file is updated so infrequently and flex is not universally present on build machines, - the lex.sksl.c file must be manually regenerated if you make any changes to this file. Just run: - - flex sksl.flex - - You will have to manually add a copyright notice to the top of lex.sksl.c. - -*/ - -%option prefix="sksl" -%option reentrant -%option yylineno -%option never-interactive -%option nounistd - -DIGIT [0-9] -LETTER [a-zA-Z_$] - -%% - -{DIGIT}*"."{DIGIT}+([eE][+-]?{DIGIT}+)? { return SkSL::Token::FLOAT_LITERAL; } - -{DIGIT}+"."{DIGIT}*([eE][+-]?{DIGIT}+)? { return SkSL::Token::FLOAT_LITERAL; } - -{DIGIT}+([eE][+-]?{DIGIT}+) { return SkSL::Token::FLOAT_LITERAL; } - -{DIGIT}+ { return SkSL::Token::INT_LITERAL; } - -"0x"[0-9a-fA-F]+ { return SkSL::Token::INT_LITERAL; } - -true { return SkSL::Token::TRUE_LITERAL; } - -false { return SkSL::Token::FALSE_LITERAL; } - -if { return SkSL::Token::IF; } - -@if { return SkSL::Token::STATIC_IF; } - -else { return SkSL::Token::ELSE; } - -for { return SkSL::Token::FOR; } - -while { return SkSL::Token::WHILE; } - -do { return SkSL::Token::DO; } - -switch { return SkSL::Token::SWITCH; } - -@switch { return SkSL::Token::STATIC_SWITCH; } - -case { return SkSL::Token::CASE; } - -default { return SkSL::Token::DEFAULT; } - -break { return SkSL::Token::BREAK; } - -continue { return SkSL::Token::CONTINUE; } - -discard { return SkSL::Token::DISCARD; } - -return { return SkSL::Token::RETURN; } - -in { return SkSL::Token::IN; } - -out { return SkSL::Token::OUT; } - -inout { return SkSL::Token::INOUT; } - -uniform { return SkSL::Token::UNIFORM; } - -const { return SkSL::Token::CONST; } - -lowp { return SkSL::Token::LOWP; } - -mediump { return SkSL::Token::MEDIUMP; } - -highp { return SkSL::Token::HIGHP; } - -flat { return SkSL::Token::FLAT; } - -noperspective { return SkSL::Token::NOPERSPECTIVE; } - -readonly { return SkSL::Token::READONLY; } - -writeonly { return SkSL::Token::WRITEONLY; } - -coherent { return SkSL::Token::COHERENT; } - -volatile { return SkSL::Token::VOLATILE; } - -restrict { return SkSL::Token::RESTRICT; } - -buffer { return SkSL::Token::BUFFER; } - -sk_has_side_effects { return SkSL::Token::HASSIDEEFFECTS; } - -struct { return SkSL::Token::STRUCT; } - -layout { return SkSL::Token::LAYOUT; } - -precision { return SkSL::Token::PRECISION; } - -{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::IDENTIFIER; } - -"#"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::DIRECTIVE; } - -"@"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::SECTION; } - -"(" { return SkSL::Token::LPAREN; } - -")" { return SkSL::Token::RPAREN; } - -"{" { return SkSL::Token::LBRACE; } - -"}" { return SkSL::Token::RBRACE; } - -"[" { return SkSL::Token::LBRACKET; } - -"]" { return SkSL::Token::RBRACKET; } - -"." { return SkSL::Token::DOT; } - -"," { return SkSL::Token::COMMA; } - -"++" { return SkSL::Token::PLUSPLUS; } - -"--" { return SkSL::Token::MINUSMINUS; } - -"+" { return SkSL::Token::PLUS; } - -"-" { return SkSL::Token::MINUS; } - -"*" { return SkSL::Token::STAR; } - -"/" { return SkSL::Token::SLASH; } - -"%" { return SkSL::Token::PERCENT; } - -"<<" { return SkSL::Token::SHL; } - -">>" { return SkSL::Token::SHR; } - -"|" { return SkSL::Token::BITWISEOR; } - -"^" { return SkSL::Token::BITWISEXOR; } - -"&" { return SkSL::Token::BITWISEAND; } - -"~" { return SkSL::Token::BITWISENOT; } - -"||" { return SkSL::Token::LOGICALOR; } - -"^^" { return SkSL::Token::LOGICALXOR; } - -"&&" { return SkSL::Token::LOGICALAND; } - -"!" { return SkSL::Token::LOGICALNOT; } - -"?" { return SkSL::Token::QUESTION; } - -":" { return SkSL::Token::COLON; } - -"=" { return SkSL::Token::EQ; } - -"==" { return SkSL::Token::EQEQ; } - -"!=" { return SkSL::Token::NEQ; } - -">" { return SkSL::Token::GT; } - -"<" { return SkSL::Token::LT; } - -">=" { return SkSL::Token::GTEQ; } - -"<=" { return SkSL::Token::LTEQ; } - -"+=" { return SkSL::Token::PLUSEQ; } - -"-=" { return SkSL::Token::MINUSEQ; } - -"*=" { return SkSL::Token::STAREQ; } - -"/=" { return SkSL::Token::SLASHEQ; } - -"%=" { return SkSL::Token::PERCENTEQ; } - -"<<=" { return SkSL::Token::SHLEQ; } - -">>=" { return SkSL::Token::SHREQ; } - -"|=" { return SkSL::Token::BITWISEOREQ; } - -"^=" { return SkSL::Token::BITWISEXOREQ; } - -"&=" { return SkSL::Token::BITWISEANDEQ; } - -"||=" { return SkSL::Token::LOGICALOREQ; } - -"^^=" { return SkSL::Token::LOGICALXOREQ; } - -"&&=" { return SkSL::Token::LOGICALANDEQ; } - -";" { return SkSL::Token::SEMICOLON; } - -"->" { return SkSL::Token::ARROW; } - -"::" { return SkSL::Token::COLONCOLON; } - -[ \t\r\n]+ { return SkSL::Token::WHITESPACE; } - -"//".* /* line comment */ - -"/*"([^*]|"*"[^/])*"*/" /* block comment */ - -. { return SkSL::Token::INVALID_TOKEN; } - -%% - -int skslwrap(yyscan_t scanner) { - return 1; // terminate -} |