aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-02-27 13:26:45 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-27 19:01:55 +0000
commitaf19769831f1c4c3b90c85aa9f8851cd8bbf86d5 (patch)
tree5dd063830d41aff45eefcb524c868ac210016467
parent578f064a60b63ddfb00831e9e59a47060bfcefe0 (diff)
Re-land of skslc switch support
This reverts commit 7d975fc200bbbea991ec4c04c08f3a5ea7b847af. BUG=skia: Change-Id: I57521f7a291a35cfed58d623ea4f8da29582d2c5 Reviewed-on: https://skia-review.googlesource.com/8993 Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
-rw-r--r--src/sksl/SkSLCFGGenerator.cpp39
-rw-r--r--src/sksl/SkSLCompiler.cpp6
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp27
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h3
-rw-r--r--src/sksl/SkSLIRGenerator.cpp78
-rw-r--r--src/sksl/SkSLIRGenerator.h4
-rw-r--r--src/sksl/SkSLParser.cpp84
-rw-r--r--src/sksl/SkSLParser.h6
-rw-r--r--src/sksl/SkSLToken.h3
-rw-r--r--src/sksl/ast/SkSLASTStatement.h1
-rw-r--r--src/sksl/ast/SkSLASTSwitchCase.h48
-rw-r--r--src/sksl/ast/SkSLASTSwitchStatement.h43
-rw-r--r--src/sksl/ir/SkSLStatement.h1
-rw-r--r--src/sksl/ir/SkSLSwitchCase.h47
-rw-r--r--src/sksl/ir/SkSLSwitchStatement.h43
-rw-r--r--src/sksl/lex.sksl.c634
-rw-r--r--src/sksl/sksl.flex6
-rw-r--r--tests/SkSLErrorTest.cpp30
-rw-r--r--tests/SkSLGLSLTest.cpp87
19 files changed, 865 insertions, 325 deletions
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index 31bace9fb7..28533df557 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -20,6 +20,7 @@
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLSwizzle.h"
+#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclarationsStatement.h"
#include "ir/SkSLWhileStatement.h"
@@ -152,13 +153,17 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
- case Expression::kPrefix_Kind:
- this->addExpression(cfg, &((PrefixExpression*) e->get())->fOperand, constantPropagate);
+ case Expression::kPrefix_Kind: {
+ PrefixExpression* p = (PrefixExpression*) e->get();
+ this->addExpression(cfg, &p->fOperand, constantPropagate &&
+ p->fOperator != Token::PLUSPLUS &&
+ p->fOperator != Token::MINUSMINUS);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
+ }
case Expression::kPostfix_Kind:
- this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, constantPropagate);
+ this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, false);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr });
break;
@@ -345,6 +350,34 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
cfg.fCurrent = loopExit;
break;
}
+ case Statement::kSwitch_Kind: {
+ SwitchStatement* ss = (SwitchStatement*) s;
+ this->addExpression(cfg, &ss->fValue, true);
+ BlockId start = cfg.fCurrent;
+ BlockId switchExit = cfg.newIsolatedBlock();
+ fLoopExits.push(switchExit);
+ for (const auto& c : ss->fCases) {
+ cfg.newBlock();
+ cfg.addExit(start, cfg.fCurrent);
+ if (c->fValue) {
+ // technically this should go in the start block, but it doesn't actually matter
+ // because it must be constant. Not worth running two loops for.
+ this->addExpression(cfg, &c->fValue, true);
+ }
+ for (const auto& caseStatement : c->fStatements) {
+ this->addStatement(cfg, caseStatement.get());
+ }
+ }
+ cfg.addExit(cfg.fCurrent, switchExit);
+ // note that unlike GLSL, our grammar requires the default case to be last
+ if (0 == ss->fCases.size() || ss->fCases[ss->fCases.size() - 1]->fValue) {
+ // switch does not have a default clause, mark that it can skip straight to the end
+ cfg.addExit(start, switchExit);
+ }
+ fLoopExits.pop();
+ cfg.fCurrent = switchExit;
+ break;
+ }
default:
printf("statement: %s\n", s->description().c_str());
ABORT("unsupported statement kind");
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 004eab7053..d5742390a9 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -286,8 +286,12 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
if (e1 != e2) {
// definition has changed, merge and add exit block to worklist
workList->insert(exitId);
- exit.fBefore[pair.first] =
+ if (e1 && e2) {
+ exit.fBefore[pair.first] =
(std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
+ } else {
+ exit.fBefore[pair.first] = nullptr;
+ }
}
}
}
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 3f5f9d1b39..35a2f62b08 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -681,6 +681,9 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
case Statement::kDo_Kind:
this->writeDoStatement((DoStatement&) s);
break;
+ case Statement::kSwitch_Kind:
+ this->writeSwitchStatement((SwitchStatement&) s);
+ break;
case Statement::kBreak_Kind:
this->write("break;");
break;
@@ -750,6 +753,30 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
this->write(");");
}
+void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
+ this->write("switch (");
+ this->writeExpression(*s.fValue, kTopLevel_Precedence);
+ this->writeLine(") {");
+ fIndentation++;
+ for (const auto& c : s.fCases) {
+ if (c->fValue) {
+ this->write("case ");
+ this->writeExpression(*c->fValue, kTopLevel_Precedence);
+ this->writeLine(":");
+ } else {
+ this->writeLine("default:");
+ }
+ fIndentation++;
+ for (const auto& stmt : c->fStatements) {
+ this->writeStatement(*stmt);
+ this->writeLine();
+ }
+ fIndentation--;
+ }
+ fIndentation--;
+ this->write("}");
+}
+
void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->write("return");
if (r.fExpression) {
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 0ae2c5c585..907c3053c6 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -34,6 +34,7 @@
#include "ir/SkSLProgramElement.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLStatement.h"
+#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclarations.h"
@@ -155,6 +156,8 @@ private:
void writeDoStatement(const DoStatement& d);
+ void writeSwitchStatement(const SwitchStatement& s);
+
void writeReturnStatement(const ReturnStatement& r);
const Context& fContext;
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 247766f51e..ae2a90f899 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -8,6 +8,7 @@
#include "SkSLIRGenerator.h"
#include "limits.h"
+#include <unordered_set>
#include "SkSLCompiler.h"
#include "ast/SkSLASTBoolLiteral.h"
@@ -39,6 +40,8 @@
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLReturnStatement.h"
+#include "ir/SkSLSwitchCase.h"
+#include "ir/SkSLSwitchStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLUnresolvedFunction.h"
@@ -81,12 +84,27 @@ public:
IRGenerator* fIR;
};
+class AutoSwitchLevel {
+public:
+ AutoSwitchLevel(IRGenerator* ir)
+ : fIR(ir) {
+ fIR->fSwitchLevel++;
+ }
+
+ ~AutoSwitchLevel() {
+ fIR->fSwitchLevel--;
+ }
+
+ IRGenerator* fIR;
+};
+
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ErrorReporter& errorReporter)
: fContext(*context)
, fCurrentFunction(nullptr)
, fSymbolTable(std::move(symbolTable))
, fLoopLevel(0)
+, fSwitchLevel(0)
, fErrors(errorReporter) {}
void IRGenerator::pushSymbolTable() {
@@ -153,6 +171,8 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta
return this->convertWhile((ASTWhileStatement&) statement);
case ASTStatement::kDo_Kind:
return this->convertDo((ASTDoStatement&) statement);
+ case ASTStatement::kSwitch_Kind:
+ return this->convertSwitch((ASTSwitchStatement&) statement);
case ASTStatement::kReturn_Kind:
return this->convertReturn((ASTReturnStatement&) statement);
case ASTStatement::kBreak_Kind:
@@ -357,6 +377,60 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
std::move(test)));
}
+std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
+ AutoSwitchLevel level(this);
+ std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
+ if (!value) {
+ return nullptr;
+ }
+ if (value->fType != *fContext.fUInt_Type) {
+ value = this->coerce(std::move(value), *fContext.fInt_Type);
+ if (!value) {
+ return nullptr;
+ }
+ }
+ AutoSymbolTable table(this);
+ std::unordered_set<int> caseValues;
+ std::vector<std::unique_ptr<SwitchCase>> cases;
+ for (const auto& c : s.fCases) {
+ std::unique_ptr<Expression> caseValue;
+ if (c->fValue) {
+ caseValue = this->convertExpression(*c->fValue);
+ if (!caseValue) {
+ return nullptr;
+ }
+ if (caseValue->fType != *fContext.fUInt_Type) {
+ caseValue = this->coerce(std::move(caseValue), *fContext.fInt_Type);
+ if (!caseValue) {
+ return nullptr;
+ }
+ }
+ if (!caseValue->isConstant()) {
+ fErrors.error(caseValue->fPosition, "case value must be a constant");
+ return nullptr;
+ }
+ ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind);
+ int64_t v = ((IntLiteral&) *caseValue).fValue;
+ if (caseValues.find(v) != caseValues.end()) {
+ fErrors.error(caseValue->fPosition, "duplicate case value");
+ }
+ caseValues.insert(v);
+ }
+ std::vector<std::unique_ptr<Statement>> statements;
+ for (const auto& s : c->fStatements) {
+ std::unique_ptr<Statement> converted = this->convertStatement(*s);
+ if (!converted) {
+ return nullptr;
+ }
+ statements.push_back(std::move(converted));
+ }
+ cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue),
+ std::move(statements)));
+ }
+ return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, std::move(value),
+ std::move(cases)));
+}
+
std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
const ASTExpressionStatement& s) {
std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
@@ -393,10 +467,10 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement&
}
std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
- if (fLoopLevel > 0) {
+ if (fLoopLevel > 0 || fSwitchLevel > 0) {
return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
} else {
- fErrors.error(b.fPosition, "break statement must be inside a loop");
+ fErrors.error(b.fPosition, "break statement must be inside a loop or switch");
return nullptr;
}
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 1336b68c88..fb79cda9b5 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -29,6 +29,7 @@
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
+#include "ast/SkSLASTSwitchStatement.h"
#include "ast/SkSLASTTernaryExpression.h"
#include "ast/SkSLASTVarDeclaration.h"
#include "ast/SkSLASTVarDeclarationStatement.h"
@@ -140,6 +141,7 @@ private:
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
+ std::unique_ptr<Statement> convertSwitch(const ASTSwitchStatement& s);
std::unique_ptr<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
std::unique_ptr<Extension> convertExtension(const ASTExtension& e);
std::unique_ptr<Statement> convertExpressionStatement(const ASTExpressionStatement& s);
@@ -170,10 +172,12 @@ private:
std::unordered_map<SkString, CapValue> fCapsMap;
std::shared_ptr<SymbolTable> fSymbolTable;
int fLoopLevel;
+ int fSwitchLevel;
ErrorReporter& fErrors;
friend class AutoSymbolTable;
friend class AutoLoopLevel;
+ friend class AutoSwitchLevel;
friend class Compiler;
};
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index cc47577e93..478d6fd673 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -63,6 +63,8 @@
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
+#include "ast/SkSLASTSwitchCase.h"
+#include "ast/SkSLASTSwitchStatement.h"
#include "ast/SkSLASTTernaryExpression.h"
#include "ast/SkSLASTType.h"
#include "ast/SkSLASTVarDeclaration.h"
@@ -770,6 +772,8 @@ std::unique_ptr<ASTStatement> Parser::statement() {
return this->doStatement();
case Token::WHILE:
return this->whileStatement();
+ case Token::SWITCH:
+ return this->switchStatement();
case Token::RETURN:
return this->returnStatement();
case Token::BREAK:
@@ -975,6 +979,86 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
std::move(statement)));
}
+/* CASE expression COLON statement* */
+std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
+ Token start;
+ if (!this->expect(Token::CASE, "'case'", &start)) {
+ return nullptr;
+ }
+ std::unique_ptr<ASTExpression> value = this->expression();
+ if (!value) {
+ return nullptr;
+ }
+ if (!this->expect(Token::COLON, "':'")) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<ASTStatement>> statements;
+ while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
+ this->peek().fKind != Token::DEFAULT) {
+ std::unique_ptr<ASTStatement> s = this->statement();
+ if (!s) {
+ return nullptr;
+ }
+ statements.push_back(std::move(s));
+ }
+ return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
+ std::move(statements)));
+}
+
+/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
+std::unique_ptr<ASTStatement> Parser::switchStatement() {
+ Token start;
+ if (!this->expect(Token::SWITCH, "'switch'", &start)) {
+ return nullptr;
+ }
+ if (!this->expect(Token::LPAREN, "'('")) {
+ return nullptr;
+ }
+ std::unique_ptr<ASTExpression> value(this->expression());
+ if (!value) {
+ return nullptr;
+ }
+ if (!this->expect(Token::RPAREN, "')'")) {
+ return nullptr;
+ }
+ if (!this->expect(Token::LBRACE, "'{'")) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<ASTSwitchCase>> cases;
+ while (this->peek().fKind == Token::CASE) {
+ std::unique_ptr<ASTSwitchCase> c = this->switchCase();
+ if (!c) {
+ return nullptr;
+ }
+ cases.push_back(std::move(c));
+ }
+ // Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
+ // parts of the compiler may rely upon this assumption.
+ if (this->peek().fKind == Token::DEFAULT) {
+ Token defaultStart;
+ SkAssertResult(this->expect(Token::DEFAULT, "'default'", &defaultStart));
+ if (!this->expect(Token::COLON, "':'")) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<ASTStatement>> statements;
+ while (this->peek().fKind != Token::RBRACE) {
+ std::unique_ptr<ASTStatement> s = this->statement();
+ if (!s) {
+ return nullptr;
+ }
+ statements.push_back(std::move(s));
+ }
+ cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
+ std::move(statements)));
+ }
+ if (!this->expect(Token::RBRACE, "'}'")) {
+ return nullptr;
+ }
+ return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
+ std::move(value),
+ std::move(cases)));
+}
+
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
STATEMENT */
std::unique_ptr<ASTForStatement> Parser::forStatement() {
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 78d9933871..63894e0227 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -37,6 +37,8 @@ struct ASTPrecision;
struct ASTReturnStatement;
struct ASTStatement;
struct ASTSuffix;
+struct ASTSwitchCase;
+struct ASTSwitchStatement;
struct ASTType;
struct ASTWhileStatement;
struct ASTVarDeclarations;
@@ -143,6 +145,10 @@ private:
std::unique_ptr<ASTForStatement> forStatement();
+ std::unique_ptr<ASTSwitchCase> switchCase();
+
+ std::unique_ptr<ASTStatement> switchStatement();
+
std::unique_ptr<ASTReturnStatement> returnStatement();
std::unique_ptr<ASTBreakStatement> breakStatement();
diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h
index 197781f2a0..70b4ed298e 100644
--- a/src/sksl/SkSLToken.h
+++ b/src/sksl/SkSLToken.h
@@ -82,6 +82,9 @@ struct Token {
FOR,
WHILE,
DO,
+ SWITCH,
+ CASE,
+ DEFAULT,
RETURN,
BREAK,
CONTINUE,
diff --git a/src/sksl/ast/SkSLASTStatement.h b/src/sksl/ast/SkSLASTStatement.h
index 9ddde063ea..6ce320e343 100644
--- a/src/sksl/ast/SkSLASTStatement.h
+++ b/src/sksl/ast/SkSLASTStatement.h
@@ -26,6 +26,7 @@ struct ASTStatement : public ASTPositionNode {
kFor_Kind,
kWhile_Kind,
kDo_Kind,
+ kSwitch_Kind,
kReturn_Kind,
kBreak_Kind,
kContinue_Kind,
diff --git a/src/sksl/ast/SkSLASTSwitchCase.h b/src/sksl/ast/SkSLASTSwitchCase.h
new file mode 100644
index 0000000000..2c0a01c7fa
--- /dev/null
+++ b/src/sksl/ast/SkSLASTSwitchCase.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTSWITCHCASE
+#define SKSL_ASTSWITCHCASE
+
+#include "SkSLASTStatement.h"
+
+namespace SkSL {
+
+/**
+ * A single case of a 'switch' statement.
+ */
+struct ASTSwitchCase : public ASTStatement {
+ // a null value means "default:"
+ ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value,
+ std::vector<std::unique_ptr<ASTStatement>> statements)
+ : INHERITED(position, kSwitch_Kind)
+ , fValue(std::move(value))
+ , fStatements(std::move(statements)) {}
+
+ SkString description() const override {
+ SkString result;
+ if (fValue) {
+ result.appendf("case %s:\n", fValue->description().c_str());
+ } else {
+ result += "default:\n";
+ }
+ for (const auto& s : fStatements) {
+ result += s->description() + "\n";
+ }
+ return result;
+ }
+
+ // null value implies "default" case
+ const std::unique_ptr<ASTExpression> fValue;
+ const std::vector<std::unique_ptr<ASTStatement>> fStatements;
+
+ typedef ASTStatement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ast/SkSLASTSwitchStatement.h b/src/sksl/ast/SkSLASTSwitchStatement.h
new file mode 100644
index 0000000000..3031a7d2b1
--- /dev/null
+++ b/src/sksl/ast/SkSLASTSwitchStatement.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTSWITCHSTATEMENT
+#define SKSL_ASTSWITCHSTATEMENT
+
+#include "SkSLASTStatement.h"
+#include "SkSLASTSwitchCase.h"
+
+namespace SkSL {
+
+/**
+ * A 'switch' statement.
+ */
+struct ASTSwitchStatement : public ASTStatement {
+ ASTSwitchStatement(Position position, std::unique_ptr<ASTExpression> value,
+ std::vector<std::unique_ptr<ASTSwitchCase>> cases)
+ : INHERITED(position, kSwitch_Kind)
+ , fValue(std::move(value))
+ , fCases(std::move(cases)) {}
+
+ SkString description() const override {
+ SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
+ for (const auto& c : fCases) {
+ result += c->description();
+ }
+ result += "}";
+ return result;
+ }
+
+ const std::unique_ptr<ASTExpression> fValue;
+ const std::vector<std::unique_ptr<ASTSwitchCase>> fCases;
+
+ typedef ASTStatement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h
index 012311fdd3..c3a6f9539e 100644
--- a/src/sksl/ir/SkSLStatement.h
+++ b/src/sksl/ir/SkSLStatement.h
@@ -27,6 +27,7 @@ struct Statement : public IRNode {
kFor_Kind,
kIf_Kind,
kReturn_Kind,
+ kSwitch_Kind,
kVarDeclarations_Kind,
kWhile_Kind
};
diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h
new file mode 100644
index 0000000000..3f1c3acbd3
--- /dev/null
+++ b/src/sksl/ir/SkSLSwitchCase.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_SWITCHCASE
+#define SKSL_SWITCHCASE
+
+#include "SkSLStatement.h"
+
+namespace SkSL {
+
+/**
+ * A single case of a 'switch' statement.
+ */
+struct SwitchCase : public Statement {
+ SwitchCase(Position position, std::unique_ptr<Expression> value,
+ std::vector<std::unique_ptr<Statement>> statements)
+ : INHERITED(position, kSwitch_Kind)
+ , fValue(std::move(value))
+ , fStatements(std::move(statements)) {}
+
+ SkString description() const override {
+ SkString result;
+ if (fValue) {
+ result.appendf("case %s:\n", fValue->description().c_str());
+ } else {
+ result += "default:\n";
+ }
+ for (const auto& s : fStatements) {
+ result += s->description() + "\n";
+ }
+ return result;
+ }
+
+ // null value implies "default" case
+ std::unique_ptr<Expression> fValue;
+ std::vector<std::unique_ptr<Statement>> fStatements;
+
+ typedef Statement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLSwitchStatement.h b/src/sksl/ir/SkSLSwitchStatement.h
new file mode 100644
index 0000000000..31765c4e04
--- /dev/null
+++ b/src/sksl/ir/SkSLSwitchStatement.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_SWITCHSTATEMENT
+#define SKSL_SWITCHSTATEMENT
+
+#include "SkSLStatement.h"
+#include "SkSLSwitchCase.h"
+
+namespace SkSL {
+
+/**
+ * A 'switch' statement.
+ */
+struct SwitchStatement : public Statement {
+ SwitchStatement(Position position, std::unique_ptr<Expression> value,
+ std::vector<std::unique_ptr<SwitchCase>> cases)
+ : INHERITED(position, kSwitch_Kind)
+ , fValue(std::move(value))
+ , fCases(std::move(cases)) {}
+
+ SkString description() const override {
+ SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
+ for (const auto& c : fCases) {
+ result += c->description();
+ }
+ result += "}";
+ return result;
+ }
+
+ std::unique_ptr<Expression> fValue;
+ std::vector<std::unique_ptr<SwitchCase>> fCases;
+
+ typedef Statement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c
index 4cff376fa5..2c5eb73402 100644
--- a/src/sksl/lex.sksl.c
+++ b/src/sksl/lex.sksl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Google Inc.
+ * Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
@@ -13,8 +13,8 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 0
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 39
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -248,7 +248,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
- int yy_n_chars;
+ yy_size_t 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
@@ -368,9 +368,6 @@ typedef int yy_state_type;
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 );
-#if defined(__GNUC__) && __GNUC__ >= 3
-__attribute__((__noreturn__))
-#endif
static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
@@ -383,8 +380,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 89
-#define YY_END_OF_BUFFER 90
+#define YY_NUM_RULES 92
+#define YY_END_OF_BUFFER 93
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -392,37 +389,39 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[239] =
+static yyconst flex_int16_t yy_accept[253] =
{ 0,
- 0, 0, 90, 88, 87, 87, 61, 88, 35, 51,
- 56, 37, 38, 49, 47, 44, 48, 43, 50, 4,
- 4, 63, 84, 68, 64, 67, 62, 41, 42, 55,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 39, 54,
- 40, 57, 87, 66, 36, 35, 75, 60, 80, 73,
- 45, 71, 46, 72, 1, 0, 85, 74, 2, 4,
- 0, 0, 52, 70, 65, 69, 53, 79, 59, 35,
- 35, 35, 12, 35, 35, 35, 35, 35, 8, 17,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-
- 35, 35, 35, 78, 58, 36, 83, 0, 0, 0,
- 85, 1, 0, 0, 3, 5, 76, 77, 82, 35,
- 35, 35, 35, 35, 35, 35, 10, 35, 35, 35,
- 35, 35, 35, 18, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 81, 0, 1, 86, 0, 0,
- 2, 35, 35, 35, 35, 35, 9, 35, 25, 35,
- 35, 35, 22, 35, 35, 35, 35, 35, 35, 35,
- 6, 35, 35, 35, 35, 0, 1, 13, 35, 21,
- 35, 35, 7, 24, 19, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 11, 35, 35, 35, 35,
-
- 33, 35, 35, 35, 35, 35, 16, 32, 35, 35,
- 35, 35, 35, 15, 23, 35, 35, 35, 35, 20,
- 35, 35, 29, 14, 35, 35, 27, 31, 30, 35,
- 35, 34, 28, 35, 35, 35, 26, 0
+ 0, 0, 93, 91, 90, 90, 64, 91, 38, 54,
+ 59, 40, 41, 52, 50, 47, 51, 46, 53, 4,
+ 4, 66, 87, 71, 67, 70, 65, 44, 45, 58,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 42, 57,
+ 43, 60, 90, 69, 39, 38, 78, 63, 83, 76,
+ 48, 74, 49, 75, 1, 0, 88, 77, 2, 4,
+ 0, 0, 55, 73, 68, 72, 56, 82, 62, 38,
+ 38, 38, 38, 38, 12, 38, 38, 38, 38, 38,
+ 8, 20, 38, 38, 38, 38, 38, 38, 38, 38,
+
+ 38, 38, 38, 38, 38, 38, 81, 61, 39, 86,
+ 0, 0, 0, 88, 1, 0, 0, 3, 5, 79,
+ 80, 85, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 10, 38, 38, 38, 38, 38, 38, 21, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 84, 0, 1, 89, 0, 0, 2, 38, 14, 38,
+ 38, 38, 38, 38, 9, 38, 28, 38, 38, 38,
+ 25, 38, 38, 38, 38, 38, 38, 38, 38, 6,
+ 38, 38, 38, 38, 0, 1, 16, 38, 24, 38,
+ 38, 38, 7, 27, 22, 38, 38, 38, 38, 38,
+
+ 38, 38, 38, 38, 38, 38, 11, 38, 38, 38,
+ 38, 38, 36, 38, 38, 38, 38, 38, 19, 35,
+ 13, 38, 38, 38, 38, 38, 15, 18, 26, 38,
+ 38, 38, 38, 23, 38, 38, 32, 17, 38, 38,
+ 30, 34, 33, 38, 38, 37, 31, 38, 38, 38,
+ 29, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static yyconst flex_int32_t yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
@@ -454,7 +453,7 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[57] =
+static yyconst flex_int32_t yy_meta[57] =
{ 0,
1, 1, 2, 1, 1, 3, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 4, 4, 1, 1,
@@ -464,69 +463,71 @@ static yyconst YY_CHAR yy_meta[57] =
3, 3, 1, 1, 1, 1
} ;
-static yyconst flex_uint16_t yy_base[245] =
+static yyconst flex_int16_t yy_base[259] =
{ 0,
- 0, 0, 306, 307, 55, 57, 283, 0, 0, 282,
- 53, 307, 307, 281, 50, 307, 49, 47, 57, 52,
- 59, 307, 307, 59, 280, 60, 307, 307, 307, 62,
- 256, 257, 49, 259, 58, 260, 54, 64, 263, 253,
- 247, 249, 259, 245, 246, 248, 246, 60, 307, 68,
- 307, 307, 97, 307, 0, 0, 307, 266, 307, 307,
- 307, 307, 307, 307, 91, 276, 0, 307, 93, 97,
- 112, 0, 264, 307, 307, 307, 263, 307, 262, 249,
- 76, 236, 0, 235, 240, 249, 233, 241, 0, 233,
- 223, 224, 240, 228, 224, 236, 74, 224, 220, 229,
-
- 226, 227, 226, 307, 241, 0, 307, 120, 251, 245,
- 0, 118, 128, 130, 132, 0, 307, 307, 307, 230,
- 225, 107, 226, 223, 210, 208, 0, 217, 205, 209,
- 207, 212, 215, 0, 216, 214, 199, 197, 196, 209,
- 207, 211, 200, 192, 307, 138, 140, 307, 147, 145,
- 149, 199, 192, 189, 197, 204, 0, 199, 0, 188,
- 184, 182, 0, 181, 183, 189, 183, 180, 179, 191,
- 0, 179, 174, 186, 185, 151, 153, 0, 184, 0,
- 175, 171, 0, 0, 0, 168, 173, 167, 166, 169,
- 172, 167, 161, 162, 168, 0, 162, 162, 155, 169,
-
- 0, 157, 156, 161, 158, 165, 0, 0, 155, 155,
- 152, 146, 153, 0, 0, 139, 117, 99, 96, 0,
- 107, 99, 0, 0, 101, 86, 0, 0, 0, 64,
- 59, 0, 0, 64, 46, 32, 0, 307, 169, 172,
- 175, 180, 185, 187
+ 0, 0, 320, 321, 55, 57, 297, 0, 0, 296,
+ 53, 321, 321, 295, 50, 321, 49, 47, 57, 52,
+ 59, 321, 321, 59, 294, 60, 321, 321, 321, 62,
+ 270, 57, 54, 274, 59, 275, 59, 65, 278, 268,
+ 262, 264, 274, 57, 262, 264, 262, 53, 321, 74,
+ 321, 321, 103, 321, 0, 0, 321, 282, 321, 321,
+ 321, 321, 321, 321, 92, 292, 0, 321, 95, 99,
+ 118, 0, 280, 321, 321, 321, 279, 321, 278, 265,
+ 252, 78, 262, 250, 0, 249, 254, 263, 247, 255,
+ 0, 247, 237, 238, 254, 242, 238, 250, 92, 238,
+
+ 244, 233, 242, 239, 240, 239, 321, 254, 0, 321,
+ 128, 264, 258, 0, 126, 136, 106, 138, 0, 321,
+ 321, 321, 243, 238, 237, 111, 240, 237, 234, 221,
+ 219, 0, 228, 216, 220, 218, 223, 226, 0, 227,
+ 225, 210, 208, 207, 207, 219, 217, 221, 210, 202,
+ 321, 144, 146, 321, 153, 151, 155, 209, 0, 202,
+ 199, 207, 196, 213, 0, 208, 0, 197, 193, 191,
+ 0, 190, 192, 198, 192, 189, 188, 200, 199, 0,
+ 187, 182, 194, 193, 157, 159, 0, 192, 0, 183,
+ 184, 178, 0, 0, 0, 175, 180, 174, 173, 176,
+
+ 179, 174, 168, 177, 168, 174, 0, 168, 168, 161,
+ 161, 174, 0, 162, 161, 166, 163, 170, 0, 0,
+ 0, 160, 160, 157, 146, 145, 0, 0, 0, 132,
+ 116, 99, 102, 0, 113, 101, 0, 0, 105, 92,
+ 0, 0, 0, 79, 80, 0, 0, 81, 62, 32,
+ 0, 321, 175, 178, 181, 186, 191, 193
} ;
-static yyconst flex_int16_t yy_def[245] =
+static yyconst flex_int16_t yy_def[259] =
{ 0,
- 238, 1, 238, 238, 238, 238, 238, 239, 240, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 238, 238,
- 238, 238, 238, 238, 241, 240, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 242, 243, 238, 238, 238,
- 238, 244, 238, 238, 238, 238, 238, 238, 238, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
-
- 240, 240, 240, 238, 238, 241, 238, 238, 242, 242,
- 243, 238, 238, 238, 238, 244, 238, 238, 238, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 238, 238, 238, 238, 238, 238,
- 238, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 238, 238, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
-
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 0, 238, 238,
- 238, 238, 238, 238
+ 252, 1, 252, 252, 252, 252, 252, 253, 254, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 252, 252,
+ 252, 252, 252, 252, 255, 254, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 256, 257, 252, 252, 252,
+ 252, 258, 252, 252, 252, 252, 252, 252, 252, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+
+ 254, 254, 254, 254, 254, 254, 252, 252, 255, 252,
+ 252, 256, 256, 257, 252, 252, 252, 252, 258, 252,
+ 252, 252, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 252, 252, 252, 252, 252, 252, 252, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 252, 252, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 0, 252, 252, 252, 252, 252, 252
} ;
-static yyconst flex_uint16_t yy_nxt[364] =
+static yyconst flex_int16_t yy_nxt[378] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
@@ -534,43 +535,44 @@ static yyconst flex_uint16_t yy_nxt[364] =
31, 32, 33, 34, 35, 9, 36, 37, 9, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
9, 9, 49, 50, 51, 52, 53, 53, 53, 53,
- 58, 61, 63, 65, 65, 237, 69, 66, 70, 70,
+ 58, 61, 63, 65, 65, 251, 69, 66, 70, 70,
64, 62, 67, 69, 59, 70, 70, 71, 68, 73,
- 74, 76, 77, 78, 71, 71, 82, 85, 89, 104,
- 79, 83, 71, 91, 236, 90, 102, 86, 53, 53,
-
- 87, 235, 72, 136, 103, 234, 92, 65, 65, 112,
- 112, 69, 121, 70, 70, 233, 108, 122, 113, 137,
- 138, 105, 71, 114, 108, 114, 113, 232, 115, 115,
- 71, 146, 231, 146, 112, 112, 147, 147, 230, 150,
- 229, 150, 228, 149, 151, 151, 115, 115, 115, 115,
- 227, 149, 154, 155, 147, 147, 147, 147, 176, 226,
- 176, 151, 151, 177, 177, 151, 151, 177, 177, 177,
- 177, 55, 225, 55, 56, 56, 56, 106, 106, 106,
- 109, 109, 109, 109, 109, 111, 224, 111, 111, 111,
- 116, 116, 223, 222, 221, 220, 219, 218, 217, 216,
-
- 215, 214, 213, 212, 211, 210, 209, 208, 207, 206,
- 205, 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, 175, 174,
- 173, 172, 171, 170, 169, 168, 167, 166, 165, 164,
- 163, 162, 161, 160, 159, 158, 157, 156, 153, 152,
- 148, 110, 145, 144, 143, 142, 141, 140, 139, 135,
- 134, 133, 132, 131, 130, 129, 128, 127, 126, 125,
- 124, 123, 120, 119, 118, 117, 110, 107, 101, 100,
- 99, 98, 97, 96, 95, 94, 93, 88, 84, 81,
-
- 80, 75, 60, 57, 54, 238, 3, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238
+ 74, 76, 77, 78, 71, 71, 81, 83, 87, 105,
+ 79, 84, 71, 91, 93, 107, 85, 106, 88, 82,
+
+ 92, 89, 72, 100, 53, 53, 101, 94, 65, 65,
+ 250, 115, 115, 69, 125, 70, 70, 111, 249, 126,
+ 116, 141, 118, 118, 71, 111, 248, 108, 116, 117,
+ 247, 117, 71, 246, 118, 118, 245, 142, 143, 152,
+ 244, 152, 115, 115, 153, 153, 243, 156, 242, 156,
+ 241, 155, 157, 157, 118, 118, 161, 162, 240, 155,
+ 153, 153, 153, 153, 185, 239, 185, 157, 157, 186,
+ 186, 157, 157, 186, 186, 186, 186, 55, 238, 55,
+ 56, 56, 56, 109, 109, 109, 112, 112, 112, 112,
+ 112, 114, 237, 114, 114, 114, 119, 119, 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, 202, 201, 200, 199, 198, 197, 196, 195,
+ 194, 193, 192, 191, 190, 189, 188, 187, 184, 183,
+ 182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
+ 172, 171, 170, 169, 168, 167, 166, 165, 164, 163,
+ 160, 159, 158, 154, 113, 151, 150, 149, 148, 147,
+ 146, 145, 144, 140, 139, 138, 137, 136, 135, 134,
+ 133, 132, 131, 130, 129, 128, 127, 124, 123, 122,
+
+ 121, 120, 113, 110, 104, 103, 102, 99, 98, 97,
+ 96, 95, 90, 86, 80, 75, 60, 57, 54, 252,
+ 3, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252
} ;
-static yyconst flex_int16_t yy_chk[364] =
+static yyconst flex_int16_t yy_chk[378] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -578,50 +580,51 @@ static yyconst flex_int16_t yy_chk[364] =
1, 1, 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, 17, 18, 18, 236, 20, 19, 20, 20,
+ 11, 15, 17, 18, 18, 250, 20, 19, 20, 20,
17, 15, 19, 21, 11, 21, 21, 20, 19, 24,
- 24, 26, 26, 30, 21, 20, 33, 35, 37, 50,
- 30, 33, 21, 38, 235, 37, 48, 35, 53, 53,
-
- 35, 234, 20, 97, 48, 231, 38, 65, 65, 69,
- 69, 70, 81, 70, 70, 230, 65, 81, 69, 97,
- 97, 50, 70, 71, 65, 71, 69, 226, 71, 71,
- 70, 108, 225, 108, 112, 112, 108, 108, 222, 113,
- 221, 113, 219, 112, 113, 113, 114, 114, 115, 115,
- 218, 112, 122, 122, 146, 146, 147, 147, 149, 217,
- 149, 150, 150, 149, 149, 151, 151, 176, 176, 177,
- 177, 239, 216, 239, 240, 240, 240, 241, 241, 241,
- 242, 242, 242, 242, 242, 243, 213, 243, 243, 243,
- 244, 244, 212, 211, 210, 209, 206, 205, 204, 203,
-
- 202, 200, 199, 198, 197, 195, 194, 193, 192, 191,
- 190, 189, 188, 187, 186, 182, 181, 179, 175, 174,
- 173, 172, 170, 169, 168, 167, 166, 165, 164, 162,
- 161, 160, 158, 156, 155, 154, 153, 152, 144, 143,
- 142, 141, 140, 139, 138, 137, 136, 135, 133, 132,
- 131, 130, 129, 128, 126, 125, 124, 123, 121, 120,
- 110, 109, 105, 103, 102, 101, 100, 99, 98, 96,
- 95, 94, 93, 92, 91, 90, 88, 87, 86, 85,
- 84, 82, 80, 79, 77, 73, 66, 58, 47, 46,
- 45, 44, 43, 42, 41, 40, 39, 36, 34, 32,
-
- 31, 25, 14, 10, 7, 3, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
- 238, 238, 238
+ 24, 26, 26, 30, 21, 20, 32, 33, 35, 48,
+ 30, 33, 21, 37, 38, 50, 33, 48, 35, 32,
+
+ 37, 35, 20, 44, 53, 53, 44, 38, 65, 65,
+ 249, 69, 69, 70, 82, 70, 70, 65, 248, 82,
+ 69, 99, 117, 117, 70, 65, 245, 50, 69, 71,
+ 244, 71, 70, 240, 71, 71, 239, 99, 99, 111,
+ 236, 111, 115, 115, 111, 111, 235, 116, 233, 116,
+ 232, 115, 116, 116, 118, 118, 126, 126, 231, 115,
+ 152, 152, 153, 153, 155, 230, 155, 156, 156, 155,
+ 155, 157, 157, 185, 185, 186, 186, 253, 226, 253,
+ 254, 254, 254, 255, 255, 255, 256, 256, 256, 256,
+ 256, 257, 225, 257, 257, 257, 258, 258, 224, 223,
+
+ 222, 218, 217, 216, 215, 214, 212, 211, 210, 209,
+ 208, 206, 205, 204, 203, 202, 201, 200, 199, 198,
+ 197, 196, 192, 191, 190, 188, 184, 183, 182, 181,
+ 179, 178, 177, 176, 175, 174, 173, 172, 170, 169,
+ 168, 166, 164, 163, 162, 161, 160, 158, 150, 149,
+ 148, 147, 146, 145, 144, 143, 142, 141, 140, 138,
+ 137, 136, 135, 134, 133, 131, 130, 129, 128, 127,
+ 125, 124, 123, 113, 112, 108, 106, 105, 104, 103,
+ 102, 101, 100, 98, 97, 96, 95, 94, 93, 92,
+ 90, 89, 88, 87, 86, 84, 83, 81, 80, 79,
+
+ 77, 73, 66, 58, 47, 46, 45, 43, 42, 41,
+ 40, 39, 36, 34, 31, 25, 14, 10, 7, 3,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[90] =
+static yyconst flex_int32_t yy_rule_can_match_eol[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, 1, 1, 0, 0, };
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@@ -644,7 +647,7 @@ static yyconst flex_int32_t yy_rule_can_match_eol[90] =
*/
#define YY_NO_UNISTD_H 1
-#line 642 "lex.sksl.c"
+#line 645 "lex.sksl.c"
#define INITIAL 0
@@ -673,7 +676,7 @@ struct yyguts_t
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;
+ yy_size_t yy_n_chars;
yy_size_t yyleng_r;
char *yy_c_buf_p;
int yy_init;
@@ -715,11 +718,11 @@ 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 );
+void skslset_in (FILE * in_str ,yyscan_t yyscanner );
FILE *skslget_out (yyscan_t yyscanner );
-void skslset_out (FILE * _out_str ,yyscan_t yyscanner );
+void skslset_out (FILE * out_str ,yyscan_t yyscanner );
yy_size_t skslget_leng (yyscan_t yyscanner );
@@ -727,11 +730,11 @@ char *skslget_text (yyscan_t yyscanner );
int skslget_lineno (yyscan_t yyscanner );
-void skslset_lineno (int _line_number ,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 );
+void skslset_column (int column_no ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -745,12 +748,8 @@ 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
@@ -863,7 +862,7 @@ extern int sksllex (yyscan_t yyscanner);
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
-#define YY_BREAK /*LINTED*/break;
+#define YY_BREAK break;
#endif
#define YY_RULE_SETUP \
@@ -873,9 +872,9 @@ extern int sksllex (yyscan_t yyscanner);
*/
YY_DECL
{
- yy_state_type yy_current_state;
- char *yy_cp, *yy_bp;
- int yy_act;
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( !yyg->yy_init )
@@ -908,9 +907,9 @@ YY_DECL
#line 23 "sksl.flex"
-#line 906 "lex.sksl.c"
+#line 905 "lex.sksl.c"
- while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ while ( 1 ) /* loops until end-of-file is reached */
{
yy_cp = yyg->yy_c_buf_p;
@@ -926,7 +925,7 @@ YY_DECL
yy_match:
do
{
- YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ register 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;
@@ -935,13 +934,13 @@ yy_match:
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 >= 239 )
+ if ( yy_current_state >= 253 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 238 );
+ while ( yy_current_state != 252 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@@ -1036,391 +1035,406 @@ YY_RULE_SETUP
case 13:
YY_RULE_SETUP
#line 49 "sksl.flex"
-{ return SkSL::Token::BREAK; }
+{ return SkSL::Token::SWITCH; }
YY_BREAK
case 14:
YY_RULE_SETUP
#line 51 "sksl.flex"
-{ return SkSL::Token::CONTINUE; }
+{ return SkSL::Token::CASE; }
YY_BREAK
case 15:
YY_RULE_SETUP
#line 53 "sksl.flex"
-{ return SkSL::Token::DISCARD; }
+{ return SkSL::Token::DEFAULT; }
YY_BREAK
case 16:
YY_RULE_SETUP
#line 55 "sksl.flex"
-{ return SkSL::Token::RETURN; }
+{ return SkSL::Token::BREAK; }
YY_BREAK
case 17:
YY_RULE_SETUP
#line 57 "sksl.flex"
-{ return SkSL::Token::IN; }
+{ return SkSL::Token::CONTINUE; }
YY_BREAK
case 18:
YY_RULE_SETUP
#line 59 "sksl.flex"
-{ return SkSL::Token::OUT; }
+{ return SkSL::Token::DISCARD; }
YY_BREAK
case 19:
YY_RULE_SETUP
#line 61 "sksl.flex"
-{ return SkSL::Token::INOUT; }
+{ return SkSL::Token::RETURN; }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 63 "sksl.flex"
-{ return SkSL::Token::UNIFORM; }
+{ return SkSL::Token::IN; }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 65 "sksl.flex"
-{ return SkSL::Token::CONST; }
+{ return SkSL::Token::OUT; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 67 "sksl.flex"
-{ return SkSL::Token::LOWP; }
+{ return SkSL::Token::INOUT; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 69 "sksl.flex"
-{ return SkSL::Token::MEDIUMP; }
+{ return SkSL::Token::UNIFORM; }
YY_BREAK
case 24:
YY_RULE_SETUP
#line 71 "sksl.flex"
-{ return SkSL::Token::HIGHP; }
+{ return SkSL::Token::CONST; }
YY_BREAK
case 25:
YY_RULE_SETUP
#line 73 "sksl.flex"
-{ return SkSL::Token::FLAT; }
+{ return SkSL::Token::LOWP; }
YY_BREAK
case 26:
YY_RULE_SETUP
#line 75 "sksl.flex"
-{ return SkSL::Token::NOPERSPECTIVE; }
+{ return SkSL::Token::MEDIUMP; }
YY_BREAK
case 27:
YY_RULE_SETUP
#line 77 "sksl.flex"
-{ return SkSL::Token::READONLY; }
+{ return SkSL::Token::HIGHP; }
YY_BREAK
case 28:
YY_RULE_SETUP
#line 79 "sksl.flex"
-{ return SkSL::Token::WRITEONLY; }
+{ return SkSL::Token::FLAT; }
YY_BREAK
case 29:
YY_RULE_SETUP
#line 81 "sksl.flex"
-{ return SkSL::Token::COHERENT; }
+{ return SkSL::Token::NOPERSPECTIVE; }
YY_BREAK
case 30:
YY_RULE_SETUP
#line 83 "sksl.flex"
-{ return SkSL::Token::VOLATILE; }
+{ return SkSL::Token::READONLY; }
YY_BREAK
case 31:
YY_RULE_SETUP
#line 85 "sksl.flex"
-{ return SkSL::Token::RESTRICT; }
+{ return SkSL::Token::WRITEONLY; }
YY_BREAK
case 32:
YY_RULE_SETUP
#line 87 "sksl.flex"
-{ return SkSL::Token::STRUCT; }
+{ return SkSL::Token::COHERENT; }
YY_BREAK
case 33:
YY_RULE_SETUP
#line 89 "sksl.flex"
-{ return SkSL::Token::LAYOUT; }
+{ return SkSL::Token::VOLATILE; }
YY_BREAK
case 34:
YY_RULE_SETUP
#line 91 "sksl.flex"
-{ return SkSL::Token::PRECISION; }
+{ return SkSL::Token::RESTRICT; }
YY_BREAK
case 35:
YY_RULE_SETUP
#line 93 "sksl.flex"
-{ return SkSL::Token::IDENTIFIER; }
+{ return SkSL::Token::STRUCT; }
YY_BREAK
case 36:
YY_RULE_SETUP
#line 95 "sksl.flex"
-{ return SkSL::Token::DIRECTIVE; }
+{ return SkSL::Token::LAYOUT; }
YY_BREAK
case 37:
YY_RULE_SETUP
#line 97 "sksl.flex"
-{ return SkSL::Token::LPAREN; }
+{ return SkSL::Token::PRECISION; }
YY_BREAK
case 38:
YY_RULE_SETUP
#line 99 "sksl.flex"
-{ return SkSL::Token::RPAREN; }
+{ return SkSL::Token::IDENTIFIER; }
YY_BREAK
case 39:
YY_RULE_SETUP
#line 101 "sksl.flex"
-{ return SkSL::Token::LBRACE; }
+{ return SkSL::Token::DIRECTIVE; }
YY_BREAK
case 40:
YY_RULE_SETUP
#line 103 "sksl.flex"
-{ return SkSL::Token::RBRACE; }
+{ return SkSL::Token::LPAREN; }
YY_BREAK
case 41:
YY_RULE_SETUP
#line 105 "sksl.flex"
-{ return SkSL::Token::LBRACKET; }
+{ return SkSL::Token::RPAREN; }
YY_BREAK
case 42:
YY_RULE_SETUP
#line 107 "sksl.flex"
-{ return SkSL::Token::RBRACKET; }
+{ return SkSL::Token::LBRACE; }
YY_BREAK
case 43:
YY_RULE_SETUP
#line 109 "sksl.flex"
-{ return SkSL::Token::DOT; }
+{ return SkSL::Token::RBRACE; }
YY_BREAK
case 44:
YY_RULE_SETUP
#line 111 "sksl.flex"
-{ return SkSL::Token::COMMA; }
+{ return SkSL::Token::LBRACKET; }
YY_BREAK
case 45:
YY_RULE_SETUP
#line 113 "sksl.flex"
-{ return SkSL::Token::PLUSPLUS; }
+{ return SkSL::Token::RBRACKET; }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 115 "sksl.flex"
-{ return SkSL::Token::MINUSMINUS; }
+{ return SkSL::Token::DOT; }
YY_BREAK
case 47:
YY_RULE_SETUP
#line 117 "sksl.flex"
-{ return SkSL::Token::PLUS; }
+{ return SkSL::Token::COMMA; }
YY_BREAK
case 48:
YY_RULE_SETUP
#line 119 "sksl.flex"
-{ return SkSL::Token::MINUS; }
+{ return SkSL::Token::PLUSPLUS; }
YY_BREAK
case 49:
YY_RULE_SETUP
#line 121 "sksl.flex"
-{ return SkSL::Token::STAR; }
+{ return SkSL::Token::MINUSMINUS; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 123 "sksl.flex"
-{ return SkSL::Token::SLASH; }
+{ return SkSL::Token::PLUS; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 125 "sksl.flex"
-{ return SkSL::Token::PERCENT; }
+{ return SkSL::Token::MINUS; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 127 "sksl.flex"
-{ return SkSL::Token::SHL; }
+{ return SkSL::Token::STAR; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 129 "sksl.flex"
-{ return SkSL::Token::SHR; }
+{ return SkSL::Token::SLASH; }
YY_BREAK
case 54:
YY_RULE_SETUP
#line 131 "sksl.flex"
-{ return SkSL::Token::BITWISEOR; }
+{ return SkSL::Token::PERCENT; }
YY_BREAK
case 55:
YY_RULE_SETUP
#line 133 "sksl.flex"
-{ return SkSL::Token::BITWISEXOR; }
+{ return SkSL::Token::SHL; }
YY_BREAK
case 56:
YY_RULE_SETUP
#line 135 "sksl.flex"
-{ return SkSL::Token::BITWISEAND; }
+{ return SkSL::Token::SHR; }
YY_BREAK
case 57:
YY_RULE_SETUP
#line 137 "sksl.flex"
-{ return SkSL::Token::BITWISENOT; }
+{ return SkSL::Token::BITWISEOR; }
YY_BREAK
case 58:
YY_RULE_SETUP
#line 139 "sksl.flex"
-{ return SkSL::Token::LOGICALOR; }
+{ return SkSL::Token::BITWISEXOR; }
YY_BREAK
case 59:
YY_RULE_SETUP
#line 141 "sksl.flex"
-{ return SkSL::Token::LOGICALXOR; }
+{ return SkSL::Token::BITWISEAND; }
YY_BREAK
case 60:
YY_RULE_SETUP
#line 143 "sksl.flex"
-{ return SkSL::Token::LOGICALAND; }
+{ return SkSL::Token::BITWISENOT; }
YY_BREAK
case 61:
YY_RULE_SETUP
#line 145 "sksl.flex"
-{ return SkSL::Token::LOGICALNOT; }
+{ return SkSL::Token::LOGICALOR; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 147 "sksl.flex"
-{ return SkSL::Token::QUESTION; }
+{ return SkSL::Token::LOGICALXOR; }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 149 "sksl.flex"
-{ return SkSL::Token::COLON; }
+{ return SkSL::Token::LOGICALAND; }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 151 "sksl.flex"
-{ return SkSL::Token::EQ; }
+{ return SkSL::Token::LOGICALNOT; }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 153 "sksl.flex"
-{ return SkSL::Token::EQEQ; }
+{ return SkSL::Token::QUESTION; }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 155 "sksl.flex"
-{ return SkSL::Token::NEQ; }
+{ return SkSL::Token::COLON; }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 157 "sksl.flex"
-{ return SkSL::Token::GT; }
+{ return SkSL::Token::EQ; }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 159 "sksl.flex"
-{ return SkSL::Token::LT; }
+{ return SkSL::Token::EQEQ; }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 161 "sksl.flex"
-{ return SkSL::Token::GTEQ; }
+{ return SkSL::Token::NEQ; }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 163 "sksl.flex"
-{ return SkSL::Token::LTEQ; }
+{ return SkSL::Token::GT; }
YY_BREAK
case 71:
YY_RULE_SETUP
#line 165 "sksl.flex"
-{ return SkSL::Token::PLUSEQ; }
+{ return SkSL::Token::LT; }
YY_BREAK
case 72:
YY_RULE_SETUP
#line 167 "sksl.flex"
-{ return SkSL::Token::MINUSEQ; }
+{ return SkSL::Token::GTEQ; }
YY_BREAK
case 73:
YY_RULE_SETUP
#line 169 "sksl.flex"
-{ return SkSL::Token::STAREQ; }
+{ return SkSL::Token::LTEQ; }
YY_BREAK
case 74:
YY_RULE_SETUP
#line 171 "sksl.flex"
-{ return SkSL::Token::SLASHEQ; }
+{ return SkSL::Token::PLUSEQ; }
YY_BREAK
case 75:
YY_RULE_SETUP
#line 173 "sksl.flex"
-{ return SkSL::Token::PERCENTEQ; }
+{ return SkSL::Token::MINUSEQ; }
YY_BREAK
case 76:
YY_RULE_SETUP
#line 175 "sksl.flex"
-{ return SkSL::Token::SHLEQ; }
+{ return SkSL::Token::STAREQ; }
YY_BREAK
case 77:
YY_RULE_SETUP
#line 177 "sksl.flex"
-{ return SkSL::Token::SHREQ; }
+{ return SkSL::Token::SLASHEQ; }
YY_BREAK
case 78:
YY_RULE_SETUP
#line 179 "sksl.flex"
-{ return SkSL::Token::BITWISEOREQ; }
+{ return SkSL::Token::PERCENTEQ; }
YY_BREAK
case 79:
YY_RULE_SETUP
#line 181 "sksl.flex"
-{ return SkSL::Token::BITWISEXOREQ; }
+{ return SkSL::Token::SHLEQ; }
YY_BREAK
case 80:
YY_RULE_SETUP
#line 183 "sksl.flex"
-{ return SkSL::Token::BITWISEANDEQ; }
+{ return SkSL::Token::SHREQ; }
YY_BREAK
case 81:
YY_RULE_SETUP
#line 185 "sksl.flex"
-{ return SkSL::Token::LOGICALOREQ; }
+{ return SkSL::Token::BITWISEOREQ; }
YY_BREAK
case 82:
YY_RULE_SETUP
#line 187 "sksl.flex"
-{ return SkSL::Token::LOGICALXOREQ; }
+{ return SkSL::Token::BITWISEXOREQ; }
YY_BREAK
case 83:
YY_RULE_SETUP
#line 189 "sksl.flex"
-{ return SkSL::Token::LOGICALANDEQ; }
+{ return SkSL::Token::BITWISEANDEQ; }
YY_BREAK
case 84:
YY_RULE_SETUP
#line 191 "sksl.flex"
-{ return SkSL::Token::SEMICOLON; }
+{ return SkSL::Token::LOGICALOREQ; }
YY_BREAK
case 85:
YY_RULE_SETUP
#line 193 "sksl.flex"
-/* line comment */
+{ return SkSL::Token::LOGICALXOREQ; }
YY_BREAK
case 86:
-/* rule 86 can match eol */
YY_RULE_SETUP
#line 195 "sksl.flex"
-/* block comment */
+{ return SkSL::Token::LOGICALANDEQ; }
YY_BREAK
case 87:
-/* rule 87 can match eol */
YY_RULE_SETUP
#line 197 "sksl.flex"
-/* whitespace */
+{ return SkSL::Token::SEMICOLON; }
YY_BREAK
case 88:
YY_RULE_SETUP
#line 199 "sksl.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
+/* line comment */
YY_BREAK
case 89:
+/* rule 89 can match eol */
YY_RULE_SETUP
#line 201 "sksl.flex"
+/* block comment */
+ YY_BREAK
+case 90:
+/* rule 90 can match eol */
+YY_RULE_SETUP
+#line 203 "sksl.flex"
+/* whitespace */
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 205 "sksl.flex"
+{ return SkSL::Token::INVALID_TOKEN; }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 207 "sksl.flex"
ECHO;
YY_BREAK
-#line 1418 "lex.sksl.c"
+#line 1432 "lex.sksl.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1565,9 +1579,9 @@ case YY_STATE_EOF(INITIAL):
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;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int 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] )
@@ -1596,7 +1610,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* 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;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1678,9 +1692,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yy_size_t) (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_size_t 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()" );
@@ -1699,15 +1713,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- yy_state_type yy_current_state;
- char *yy_cp;
+ register yy_state_type yy_current_state;
+ register 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);
+ register 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;
@@ -1716,7 +1730,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
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 >= 239 )
+ if ( yy_current_state >= 253 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1732,11 +1746,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- int yy_is_jam;
+ register 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;
+ register char *yy_cp = yyg->yy_c_buf_p;
- YY_CHAR yy_c = 1;
+ register YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1745,21 +1759,19 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
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 >= 239 )
+ if ( yy_current_state >= 253 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 238);
+ yy_is_jam = (yy_current_state == 252);
(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)
+ static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
{
- char *yy_cp;
+ register char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_cp = yyg->yy_c_buf_p;
@@ -1770,10 +1782,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
- yy_size_t number_to_move = yyg->yy_n_chars + 2;
- char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ register yy_size_t number_to_move = yyg->yy_n_chars + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
- char *source =
+ register char *source =
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -1799,8 +1811,6 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yyg->yy_c_buf_p = yy_cp;
}
-#endif
-
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (yyscan_t yyscanner)
@@ -1961,7 +1971,7 @@ static void sksl_load_buffer_state (yyscan_t yyscanner)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in sksl_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = 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.
@@ -2122,7 +2132,7 @@ static void skslensure_buffer_stack (yyscan_t yyscanner)
* 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... */
+ num_to_alloc = 1;
yyg->yy_buffer_stack = (struct yy_buffer_state**)skslalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
@@ -2139,7 +2149,7 @@ static void skslensure_buffer_stack (yyscan_t yyscanner)
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 */;
+ int 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
@@ -2247,9 +2257,7 @@ YY_BUFFER_STATE sksl_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le
static void 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 );
+ (void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2355,10 +2363,10 @@ void skslset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
}
/** Set the current line number.
- * @param _line_number line number
+ * @param line_number
* @param yyscanner The scanner object.
*/
-void skslset_lineno (int _line_number , yyscan_t yyscanner)
+void skslset_lineno (int line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2366,14 +2374,14 @@ void skslset_lineno (int _line_number , yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "skslset_lineno called with no buffer" );
- yylineno = _line_number;
+ yylineno = line_number;
}
/** Set the current column.
- * @param _column_no column number
+ * @param line_number
* @param yyscanner The scanner object.
*/
-void skslset_column (int _column_no , yyscan_t yyscanner)
+void skslset_column (int column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2381,25 +2389,25 @@ void skslset_column (int _column_no , yyscan_t yyscanner)
if (! YY_CURRENT_BUFFER )
YY_FATAL_ERROR( "skslset_column called with no buffer" );
- yycolumn = _column_no;
+ yycolumn = column_no;
}
/** Set the input stream. This does not discard the current
* input buffer.
- * @param _in_str A readable stream.
+ * @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)
+void skslset_in (FILE * in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = _in_str ;
+ yyin = in_str ;
}
-void skslset_out (FILE * _out_str , yyscan_t yyscanner)
+void skslset_out (FILE * out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = _out_str ;
+ yyout = out_str ;
}
int skslget_debug (yyscan_t yyscanner)
@@ -2408,10 +2416,10 @@ int skslget_debug (yyscan_t yyscanner)
return yy_flex_debug;
}
-void skslset_debug (int _bdebug , yyscan_t yyscanner)
+void skslset_debug (int bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = _bdebug ;
+ yy_flex_debug = bdebug ;
}
/* Accessor methods for yylval and yylloc */
@@ -2550,10 +2558,7 @@ int sksllex_destroy (yyscan_t yyscanner)
#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;
+ register int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2562,7 +2567,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- int n;
+ register int n;
for ( n = 0; s[n]; ++n )
;
@@ -2572,16 +2577,11 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
void *skslalloc (yy_size_t size , yyscan_t yyscanner)
{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- (void)yyg;
return (void *) 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
@@ -2594,14 +2594,12 @@ void *skslrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
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 201 "sksl.flex"
+#line 206 "sksl.flex"
diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex
index 25216bd607..adecbcf62f 100644
--- a/src/sksl/sksl.flex
+++ b/src/sksl/sksl.flex
@@ -46,6 +46,12 @@ while { return SkSL::Token::WHILE; }
do { return SkSL::Token::DO; }
+switch { return SkSL::Token::SWITCH; }
+
+case { return SkSL::Token::CASE; }
+
+default { return SkSL::Token::DEFAULT; }
+
break { return SkSL::Token::BREAK; }
continue { return SkSL::Token::CONTINUE; }
diff --git a/tests/SkSLErrorTest.cpp b/tests/SkSLErrorTest.cpp
index 301281c28e..bde5e70795 100644
--- a/tests/SkSLErrorTest.cpp
+++ b/tests/SkSLErrorTest.cpp
@@ -337,6 +337,10 @@ DEF_TEST(SkSLUseWithoutInitialize, r) {
test_failure(r,
"void main() { bool x; if (true && (false || x)) return; }",
"error: 1: 'x' has not been assigned\n1 error\n");
+ test_failure(r,
+ "void main() { int x; switch (3) { case 0: x = 0; case 1: x = 1; }"
+ "sk_FragColor = vec4(x); }",
+ "error: 1: 'x' has not been assigned\n1 error\n");
}
DEF_TEST(SkSLUnreachable, r) {
@@ -366,13 +370,16 @@ DEF_TEST(SkSLNoReturn, r) {
DEF_TEST(SkSLBreakOutsideLoop, r) {
test_failure(r,
"void foo() { while(true) {} if (true) break; }",
- "error: 1: break statement must be inside a loop\n1 error\n");
+ "error: 1: break statement must be inside a loop or switch\n1 error\n");
}
DEF_TEST(SkSLContinueOutsideLoop, r) {
test_failure(r,
"void foo() { for(;;); continue; }",
"error: 1: continue statement must be inside a loop\n1 error\n");
+ test_failure(r,
+ "void foo() { switch (1) { default: continue; } }",
+ "error: 1: continue statement must be inside a loop\n1 error\n");
}
DEF_TEST(SkSLStaticIfError, r) {
@@ -430,4 +437,25 @@ DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
"error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
}
+DEF_TEST(SkSLWrongSwitchTypes, r) {
+ test_failure(r,
+ "void main() { switch (vec2(1)) { case 1: break; } }",
+ "error: 1: expected 'int', but found 'vec2'\n1 error\n");
+ test_failure(r,
+ "void main() { switch (1) { case vec2(1): break; } }",
+ "error: 1: expected 'int', but found 'vec2'\n1 error\n");
+}
+
+DEF_TEST(SkSLNonConstantCase, r) {
+ test_failure(r,
+ "void main() { int x = 1; switch (1) { case x: break; } }",
+ "error: 1: case value must be a constant\n1 error\n");
+}
+
+DEF_TEST(SkSLDuplicateCase, r) {
+ test_failure(r,
+ "void main() { switch (1) { case 0: case 1: case 0: break; } }",
+ "error: 1: duplicate case value\n1 error\n");
+}
+
#endif
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index a0fdb98dcf..53e5c6badf 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -777,4 +777,91 @@ DEF_TEST(SkSLGeometry, r) {
SkSL::Program::kGeometry_Kind);
}
+DEF_TEST(SkSLSwitch, r) {
+ test(r,
+ "void main() {"
+ " float x;"
+ " switch (1) {"
+ " case 0:"
+ " x = 0.0;"
+ " break;"
+ " case 1:"
+ " x = 1.0;"
+ " break;"
+ " default:"
+ " x = 2.0;"
+ " }"
+ " sk_FragColor = vec4(x);"
+ "}",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " float x;\n"
+ " switch (1) {\n"
+ " case 0:\n"
+ " x = 0.0;\n"
+ " break;\n"
+ " case 1:\n"
+ " x = 1.0;\n"
+ " break;\n"
+ " default:\n"
+ " x = 2.0;\n"
+ " }\n"
+ " sk_FragColor = vec4(x);\n"
+ "}\n");
+ test(r,
+ "void main() {"
+ " float x;"
+ " switch (2) {"
+ " case 0:"
+ " x = 0.0;"
+ " case 1:"
+ " x = 1.0;"
+ " default:"
+ " x = 2.0;"
+ " }"
+ " sk_FragColor = vec4(x);"
+ "}",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " float x;\n"
+ " switch (2) {\n"
+ " case 0:\n"
+ " x = 0.0;\n"
+ " case 1:\n"
+ " x = 1.0;\n"
+ " default:\n"
+ " x = 2.0;\n"
+ " }\n"
+ " sk_FragColor = vec4(2.0);\n"
+ "}\n");
+ test(r,
+ "void main() {"
+ " float x = 0.0;"
+ " switch (3) {"
+ " case 0:"
+ " x = 0.0;"
+ " case 1:"
+ " x = 1.0;"
+ " }"
+ " sk_FragColor = vec4(x);"
+ "}",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " float x = 0.0;\n"
+ " switch (3) {\n"
+ " case 0:\n"
+ " x = 0.0;\n"
+ " case 1:\n"
+ " x = 1.0;\n"
+ " }\n"
+ " sk_FragColor = vec4(x);\n"
+ "}\n");
+}
+
#endif