sksl support for static ifs & switches

Bug: skia:
Change-Id: Ic9e01a3a18efddb19bab26e92bfb473cad294fc1
Reviewed-on: https://skia-review.googlesource.com/16144
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
diff --git a/src/sksl/README b/src/sksl/README
index 5e8e21b..a16dd80 100644
--- a/src/sksl/README
+++ b/src/sksl/README
@@ -18,6 +18,9 @@
 translating them to "varying" and "attribute" as appropriate). Be aware of the
 following differences between SkSL and GLSL:
 
+* "@if" and "@switch" are static versions of if and switch. They behave exactly
+  the same as if and switch in all respects other than it being a compile-time
+  error to use a non-constant expression as a test.
 * GLSL caps can be referenced via the syntax 'sk_Caps.<name>', e.g.
   sk_Caps.sampleVariablesSupport. The value will be a constant boolean or int,
   as appropriate. As SkSL supports constant folding and branch elimination, this
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index 6438d59..b756f2d 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -560,6 +560,8 @@
         case Statement::kSwitch_Kind: {
             SwitchStatement& ss = (SwitchStatement&) **s;
             this->addExpression(cfg, &ss.fValue, true);
+            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
+                                                         nullptr, s });
             BlockId start = cfg.fCurrent;
             BlockId switchExit = cfg.newIsolatedBlock();
             fLoopExits.push(switchExit);
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index c6140d3..a283e30 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -764,12 +764,70 @@
     }
 }
 
+
+// returns true if this statement could potentially execute a break at the current level (we ignore
+// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
+static bool contains_break(Statement& s) {
+    switch (s.fKind) {
+        case Statement::kBlock_Kind:
+            for (const auto& sub : ((Block&) s).fStatements) {
+                if (contains_break(*sub)) {
+                    return true;
+                }
+            }
+            return false;
+        case Statement::kBreak_Kind:
+            return true;
+        case Statement::kIf_Kind: {
+            const IfStatement& i = (IfStatement&) s;
+            return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse));
+        }
+        default:
+            return false;
+    }
+}
+
+// Returns a block containing all of the statements that will be run if the given case matches
+// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
+// broken by this call and must then be discarded).
+// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
+// when break statements appear inside conditionals.
+static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
+    bool capturing = false;
+    std::vector<std::unique_ptr<Statement>*> statementPtrs;
+    for (const auto& current : s->fCases) {
+        if (current.get() == c) {
+            capturing = true;
+        }
+        if (capturing) {
+            for (auto& stmt : current->fStatements) {
+                if (stmt->fKind == Statement::kBreak_Kind) {
+                    capturing = false;
+                    break;
+                }
+                if (contains_break(*stmt)) {
+                    return nullptr;
+                }
+                statementPtrs.push_back(&stmt);
+            }
+            if (!capturing) {
+                break;
+            }
+        }
+    }
+    std::vector<std::unique_ptr<Statement>> statements;
+    for (const auto& s : statementPtrs) {
+        statements.push_back(std::move(*s));
+    }
+    return std::unique_ptr<Statement>(new Block(Position(), std::move(statements)));
+}
+
 void Compiler::simplifyStatement(DefinitionMap& definitions,
-                                  BasicBlock& b,
-                                  std::vector<BasicBlock::Node>::iterator* iter,
-                                  std::unordered_set<const Variable*>* undefinedVariables,
-                                  bool* outUpdated,
-                                  bool* outNeedsRescan) {
+                                 BasicBlock& b,
+                                 std::vector<BasicBlock::Node>::iterator* iter,
+                                 std::unordered_set<const Variable*>* undefinedVariables,
+                                 bool* outUpdated,
+                                 bool* outNeedsRescan) {
     Statement* stmt = (*iter)->statement()->get();
     switch (stmt->fKind) {
         case Statement::kVarDeclarations_Kind: {
@@ -798,6 +856,22 @@
         }
         case Statement::kIf_Kind: {
             IfStatement& i = (IfStatement&) *stmt;
+            if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
+                // constant if, collapse down to a single branch
+                if (((BoolLiteral&) *i.fTest).fValue) {
+                    ASSERT(i.fIfTrue);
+                    (*iter)->setStatement(std::move(i.fIfTrue));
+                } else {
+                    if (i.fIfFalse) {
+                        (*iter)->setStatement(std::move(i.fIfFalse));
+                    } else {
+                        (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
+                    }
+                }
+                *outUpdated = true;
+                *outNeedsRescan = true;
+                break;
+            }
             if (i.fIfFalse && i.fIfFalse->isEmpty()) {
                 // else block doesn't do anything, remove it
                 i.fIfFalse.reset();
@@ -820,6 +894,57 @@
             }
             break;
         }
+        case Statement::kSwitch_Kind: {
+            SwitchStatement& s = (SwitchStatement&) *stmt;
+            if (s.fValue->isConstant()) {
+                // switch is constant, replace it with the case that matches
+                bool found = false;
+                SwitchCase* defaultCase = nullptr;
+                for (const auto& c : s.fCases) {
+                    if (!c->fValue) {
+                        defaultCase = c.get();
+                        continue;
+                    }
+                    ASSERT(c->fValue->fKind == s.fValue->fKind);
+                    found = c->fValue->compareConstant(fContext, *s.fValue);
+                    if (found) {
+                        std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
+                        if (newBlock) {
+                            (*iter)->setStatement(std::move(newBlock));
+                            break;
+                        } else {
+                            if (s.fIsStatic) {
+                                this->error(s.fPosition,
+                                            "static switch contains non-static conditional break");
+                                s.fIsStatic = false;
+                            }
+                            return; // can't simplify
+                        }
+                    }
+                }
+                if (!found) {
+                    // no matching case. use default if it exists, or kill the whole thing
+                    if (defaultCase) {
+                        std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
+                        if (newBlock) {
+                            (*iter)->setStatement(std::move(newBlock));
+                        } else {
+                            if (s.fIsStatic) {
+                                this->error(s.fPosition,
+                                            "static switch contains non-static conditional break");
+                                s.fIsStatic = false;
+                            }
+                            return; // can't simplify
+                        }
+                    } else {
+                        (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
+                    }
+                }
+                *outUpdated = true;
+                *outNeedsRescan = true;
+            }
+            break;
+        }
         case Statement::kExpression_Kind: {
             ExpressionStatement& e = (ExpressionStatement&) *stmt;
             ASSERT((*iter)->statement()->get() == &e);
@@ -892,6 +1017,31 @@
     } while (updated);
     ASSERT(!needsRescan);
 
+    // verify static ifs & switches
+    for (BasicBlock& b : cfg.fBlocks) {
+        DefinitionMap definitions = b.fBefore;
+
+        for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
+            if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
+                const Statement& s = **iter->statement();
+                switch (s.fKind) {
+                    case Statement::kIf_Kind:
+                        if (((const IfStatement&) s).fIsStatic) {
+                            this->error(s.fPosition, "static if has non-static test");
+                        }
+                        break;
+                    case Statement::kSwitch_Kind:
+                        if (((const SwitchStatement&) s).fIsStatic) {
+                            this->error(s.fPosition, "static switch has non-static test");
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
     // check for missing return
     if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
         if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index b167d1e..e160a71 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -311,7 +311,7 @@
                                                         fSymbolTable));
         }
     }
-    return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
+    return std::unique_ptr<Statement>(new IfStatement(s.fPosition, s.fIsStatic, std::move(test),
                                                       std::move(ifTrue), std::move(ifFalse)));
 }
 
@@ -429,8 +429,8 @@
         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)));
+    return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, s.fIsStatic,
+                                                          std::move(value), std::move(cases)));
 }
 
 std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index f466f6f..04e2517 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -167,7 +167,11 @@
 #endif
             break;
     }
-    return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, text);
+    Position p = Position(skslget_lineno(fScanner), -1);
+    if (token == Token::INVALID_TOKEN) {
+        this->error(p, "invalid token: '" + text + "'");
+    }
+    return Token(p, (Token::Kind) token, text);
 }
 
 void Parser::pushback(Token t) {
@@ -746,7 +750,8 @@
 std::unique_ptr<ASTStatement> Parser::statement() {
     Token start = this->peek();
     switch (start.fKind) {
-        case Token::IF:
+        case Token::IF: // fall through
+        case Token::STATIC_IF:
             return this->ifStatement();
         case Token::FOR:
             return this->forStatement();
@@ -754,7 +759,8 @@
             return this->doStatement();
         case Token::WHILE:
             return this->whileStatement();
-        case Token::SWITCH:
+        case Token::SWITCH: // fall through
+        case Token::STATIC_SWITCH:
             return this->switchStatement();
         case Token::RETURN:
             return this->returnStatement();
@@ -872,7 +878,8 @@
 /* IF LPAREN expression RPAREN statement (ELSE statement)? */
 std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
     Token start;
-    if (!this->expect(Token::IF, "'if'", &start)) {
+    bool isStatic = this->checkNext(Token::STATIC_IF, &start);
+    if (!isStatic && !this->expect(Token::IF, "'if'", &start)) {
         return nullptr;
     }
     if (!this->expect(Token::LPAREN, "'('")) {
@@ -896,7 +903,9 @@
             return nullptr;
         }
     }
-    return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
+    return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition,
+                                                              isStatic,
+                                                              std::move(test),
                                                               std::move(ifTrue),
                                                               std::move(ifFalse)));
 }
@@ -986,7 +995,8 @@
 /* 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)) {
+    bool isStatic = this->checkNext(Token::STATIC_SWITCH, &start);
+    if (!isStatic && !this->expect(Token::SWITCH, "'switch'", &start)) {
         return nullptr;
     }
     if (!this->expect(Token::LPAREN, "'('")) {
@@ -1033,6 +1043,7 @@
         return nullptr;
     }
     return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
+                                                                isStatic,
                                                                 std::move(value),
                                                                 std::move(cases)));
 }
diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h
index a5b1754..07eb856 100644
--- a/src/sksl/SkSLToken.h
+++ b/src/sksl/SkSLToken.h
@@ -78,11 +78,13 @@
         LOGICALANDEQ,
         SEMICOLON,
         IF,
+        STATIC_IF,
         ELSE,
         FOR,
         WHILE,
         DO,
         SWITCH,
+        STATIC_SWITCH,
         CASE,
         DEFAULT,
         RETURN,
diff --git a/src/sksl/ast/SkSLASTIfStatement.h b/src/sksl/ast/SkSLASTIfStatement.h
index 684bea0..2752b2b 100644
--- a/src/sksl/ast/SkSLASTIfStatement.h
+++ b/src/sksl/ast/SkSLASTIfStatement.h
@@ -16,15 +16,20 @@
  * An 'if' statement.
  */
 struct ASTIfStatement : public ASTStatement {
-    ASTIfStatement(Position position, std::unique_ptr<ASTExpression> test,
+    ASTIfStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> test,
                    std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse)
     : INHERITED(position, kIf_Kind)
+    , fIsStatic(isStatic)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
     , fIfFalse(std::move(ifFalse)) {}
 
     String description() const override {
-        String result("if (");
+        String result;
+        if (fIsStatic) {
+            result += "@";
+        }
+        result += "if (";
         result += fTest->description();
         result += ") ";
         result += fIfTrue->description();
@@ -35,6 +40,7 @@
         return result;
     }
 
+    const bool fIsStatic;
     const std::unique_ptr<ASTExpression> fTest;
     const std::unique_ptr<ASTStatement> fIfTrue;
     const std::unique_ptr<ASTStatement> fIfFalse;
diff --git a/src/sksl/ast/SkSLASTSwitchStatement.h b/src/sksl/ast/SkSLASTSwitchStatement.h
index 4a963eb..ecd0a67 100644
--- a/src/sksl/ast/SkSLASTSwitchStatement.h
+++ b/src/sksl/ast/SkSLASTSwitchStatement.h
@@ -17,14 +17,19 @@
  * A 'switch' statement.
  */
 struct ASTSwitchStatement : public ASTStatement {
-    ASTSwitchStatement(Position position, std::unique_ptr<ASTExpression> value,
+    ASTSwitchStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> value,
                        std::vector<std::unique_ptr<ASTSwitchCase>> cases)
     : INHERITED(position, kSwitch_Kind)
+    , fIsStatic(isStatic)
     , fValue(std::move(value))
     , fCases(std::move(cases)) {}
 
     String description() const override {
-        String result = String::printf("switch (%s) {\n", + fValue->description().c_str());
+        String result;
+        if (fIsStatic) {
+            result += "@";
+        }
+        result += String::printf("switch (%s) {\n", fValue->description().c_str());
         for (const auto& c : fCases) {
             result += c->description();
         }
@@ -32,6 +37,7 @@
         return result;
     }
 
+    bool fIsStatic;
     const std::unique_ptr<ASTExpression> fValue;
     const std::vector<std::unique_ptr<ASTSwitchCase>> fCases;
 
diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h
index 1197666..bcd4bb1 100644
--- a/src/sksl/ir/SkSLBlock.h
+++ b/src/sksl/ir/SkSLBlock.h
@@ -18,7 +18,7 @@
  */
 struct Block : public Statement {
     Block(Position position, std::vector<std::unique_ptr<Statement>> statements,
-          const std::shared_ptr<SymbolTable> symbols)
+          const std::shared_ptr<SymbolTable> symbols = nullptr)
     : INHERITED(position, kBlock_Kind)
     , fSymbols(std::move(symbols))
     , fStatements(std::move(statements)) {}
diff --git a/src/sksl/ir/SkSLIfStatement.h b/src/sksl/ir/SkSLIfStatement.h
index 0377b12..b09c10e 100644
--- a/src/sksl/ir/SkSLIfStatement.h
+++ b/src/sksl/ir/SkSLIfStatement.h
@@ -17,21 +17,27 @@
  * An 'if' statement.
  */
 struct IfStatement : public Statement {
-    IfStatement(Position position, std::unique_ptr<Expression> test,
+    IfStatement(Position position, bool isStatic, std::unique_ptr<Expression> test,
                 std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)
     : INHERITED(position, kIf_Kind)
+    , fIsStatic(isStatic)
     , fTest(std::move(test))
     , fIfTrue(std::move(ifTrue))
     , fIfFalse(std::move(ifFalse)) {}
 
     String description() const override {
-        String result = "if (" + fTest->description() + ") " + fIfTrue->description();
+        String result;
+        if (fIsStatic) {
+            result += "@";
+        }
+        result += "if (" + fTest->description() + ") " + fIfTrue->description();
         if (fIfFalse) {
             result += " else " + fIfFalse->description();
         }
         return result;
     }
 
+    bool fIsStatic;
     std::unique_ptr<Expression> fTest;
     std::unique_ptr<Statement> fIfTrue;
     // may be null
diff --git a/src/sksl/ir/SkSLSwitchStatement.h b/src/sksl/ir/SkSLSwitchStatement.h
index 88e1e70..3837554 100644
--- a/src/sksl/ir/SkSLSwitchStatement.h
+++ b/src/sksl/ir/SkSLSwitchStatement.h
@@ -17,14 +17,19 @@
  * A 'switch' statement.
  */
 struct SwitchStatement : public Statement {
-    SwitchStatement(Position position, std::unique_ptr<Expression> value,
+    SwitchStatement(Position position, bool isStatic, std::unique_ptr<Expression> value,
                     std::vector<std::unique_ptr<SwitchCase>> cases)
     : INHERITED(position, kSwitch_Kind)
+    , fIsStatic(isStatic)
     , fValue(std::move(value))
     , fCases(std::move(cases)) {}
 
     String description() const override {
-        String result = String::printf("switch (%s) {\n", + fValue->description().c_str());
+        String result;
+        if (fIsStatic) {
+            result += "@";
+        }
+        result += String::printf("switch (%s) {\n", fValue->description().c_str());
         for (const auto& c : fCases) {
             result += c->description();
         }
@@ -32,6 +37,7 @@
         return result;
     }
 
+    bool fIsStatic;
     std::unique_ptr<Expression> fValue;
     std::vector<std::unique_ptr<SwitchCase>> fCases;
 
diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c
index bfb6c5e..ebf94ed 100644
--- a/src/sksl/lex.sksl.c
+++ b/src/sksl/lex.sksl.c
@@ -362,8 +362,8 @@
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 94
-#define YY_END_OF_BUFFER 95
+#define YY_NUM_RULES 96
+#define YY_END_OF_BUFFER 97
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -371,38 +371,39 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[276] =
+static yyconst flex_int16_t yy_accept[285] =
     {   0,
-        0,    0,   95,   93,   92,   92,   66,   93,   40,   56,
-       61,   42,   43,   54,   52,   49,   53,   48,   55,    4,
-        4,   68,   89,   73,   69,   72,   67,   46,   47,   60,
-       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,   40,   40,   44,   59,
-       45,   62,   92,   71,   41,   40,   80,   65,   85,   78,
-       50,   76,   51,   77,    1,    0,   90,   79,    2,    4,
-        0,    0,   57,   75,   70,   74,   58,   84,   64,   40,
-       40,   40,   40,   40,   40,   12,   40,   40,   40,   40,
-       40,    8,   20,   40,   40,   40,   40,   40,   40,   40,
+        0,    0,   97,   95,   94,   94,   68,   95,   42,   58,
+       63,   44,   45,   56,   54,   51,   55,   50,   57,    4,
+        4,   70,   91,   75,   71,   74,   69,   95,   48,   49,
+       62,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   46,
+       61,   47,   64,   94,   73,   43,   42,   82,   67,   87,
+       80,   52,   78,   53,   79,    1,    0,   92,   81,    2,
+        4,    0,    0,   59,   77,   72,   76,   60,    0,    0,
+       86,   66,   42,   42,   42,   42,   42,   42,   13,   42,
+       42,   42,   42,   42,    8,   22,   42,   42,   42,   42,
 
-       40,   40,   40,   40,   40,   40,   40,   40,   83,   63,
-       41,   88,    0,    0,    0,   90,    1,    0,    0,    3,
-        5,   81,   82,   87,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   10,   40,   40,   40,   40,   40,
-       40,   21,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   86,    0,    1,   91,    0,    0,
-        2,   40,   40,   14,   40,   40,   40,   40,   40,    9,
-       40,   28,   40,   40,   40,   25,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,    6,   40,   40,   40,   40,
-        0,    1,   16,   40,   40,   24,   40,   40,   40,    7,
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   85,   65,   43,   90,    0,    0,    0,   92,    1,
+        0,    0,    3,    5,   83,   84,    9,    0,   89,   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,   88,
+        0,    1,   93,    0,    0,    2,    0,   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,    0,   18,
 
-       27,   22,   40,   40,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   11,   40,   35,   40,   40,   40,
-       40,   38,   40,   40,   40,   40,   40,   19,   40,   37,
-       13,   40,   40,   40,   40,   40,   15,   18,   26,   40,
-       40,   40,   40,   40,   23,   40,   40,   32,   17,   40,
-       40,   30,   34,   40,   33,   40,   40,   39,   40,   31,
-       40,   40,   40,   40,   40,   40,   29,   40,   40,   40,
-       40,   40,   40,   36,    0
+       42,   42,   26,   42,   42,   42,    7,   29,   24,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   12,   42,    0,   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] =
@@ -413,14 +414,14 @@
         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,    1,   25,   25,   25,   25,   26,   25,
+       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,
-       27,    1,   28,   29,   30,    1,   31,   32,   33,   34,
+       28,    1,   29,   30,   31,    1,   32,   33,   34,   35,
 
-       35,   36,   37,   38,   39,    6,   40,   41,   42,   43,
-       44,   45,    6,   46,   47,   48,   49,   50,   51,   52,
-       53,    6,   54,   55,   56,   57,    1,    1,    1,    1,
+       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,
@@ -437,192 +438,194 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst YY_CHAR yy_meta[58] =
+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,    5,    5,    1,    1,    1,    3,
-        5,    5,    5,    5,    5,    5,    3,    3,    3,    3,
+        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,    1,    1,    1,    1
+        3,    3,    3,    3,    1,    1,    1,    1
     } ;
 
-static yyconst flex_uint16_t yy_base[282] =
+static yyconst flex_uint16_t yy_base[291] =
     {   0,
-        0,    0,  344,  345,   56,   58,  321,    0,    0,  320,
-       54,  345,  345,  319,   51,  345,   50,   48,   58,   53,
-       60,  345,  345,   60,  318,   61,  345,  345,  345,   63,
-       41,   58,   59,  298,   60,  299,   57,   65,  302,  292,
-      286,  288,  298,   59,  286,  288,  286,   68,  345,   75,
-      345,  345,  109,  345,    0,    0,  345,  307,  345,  345,
-      345,  345,  345,  345,   98,  317,    0,  345,  100,  105,
-      120,    0,  305,  345,  345,  345,  304,  345,  303,  289,
-      287,  275,   70,  285,  273,    0,  272,  277,  286,  270,
-      278,    0,  270,  260,  261,  277,  265,  261,  273,   94,
+        0,    0,  353,  354,   57,   59,  330,    0,    0,  329,
+       55,  354,  354,  328,   52,  354,   51,   49,   59,   61,
+       65,  354,  354,   47,  327,   49,  354,   45,  354,  354,
+       64,   37,   57,   55,  306,   64,  307,   61,   58,  310,
+      300,  294,  296,  306,   58,  294,  296,  294,   65,  354,
+       86,  354,  354,  113,  354,    0,    0,  354,  316,  354,
+      354,  354,  354,  354,  354,  100,  326,    0,  354,  102,
+      107,  114,    0,  314,  354,  354,  354,  313,  297,  281,
+      354,  310,  295,  293,  281,   91,  291,  279,    0,  278,
+      283,  292,  276,  284,    0,  276,  266,  267,  283,  271,
 
-      277,  260,  266,  255,  264,  261,  262,  261,  345,  277,
-        0,  345,  131,  287,  281,    0,  129,  139,  110,  141,
-        0,  345,  345,  345,  265,  259,  259,  258,  113,  261,
-      258,  255,  242,  240,    0,  249,  237,  241,  239,  244,
-      247,    0,  248,  246,  231,  229,  239,  227,  227,  239,
-      237,  241,  230,  222,  345,  145,  148,  345,  155,  153,
-      157,  229,  233,    0,  221,  218,  226,  215,  232,    0,
-      227,    0,  216,  212,  210,    0,  209,  211,  217,  211,
-      208,  207,  221,  218,  217,    0,  205,  200,  212,  211,
-      159,  161,    0,  199,  209,    0,  200,  201,  195,    0,
+      267,  279,   91,  283,  266,  272,  261,  270,  267,  268,
+      267,  354,  284,    0,  354,  132,  294,  288,    0,  130,
+      141,  134,  143,    0,  354,  354,  354,  263,  354,  270,
+      264,  264,  263,  114,  266,  263,  260,  247,  245,    0,
+      254,  242,  246,  244,  249,  252,    0,  253,  251,  236,
+      234,  244,  232,  232,  244,  242,  246,  235,  227,  354,
+      147,  150,  354,  157,  155,  159,  226,  233,  237,    0,
+      225,  222,  230,  219,  236,    0,  231,    0,  220,  216,
+      214,    0,  213,  215,  221,  215,  212,  211,  225,  222,
+      221,    0,  209,  204,  216,  215,  161,  163,  216,    0,
 
-        0,    0,  192,  197,  191,  190,  193,  196,  191,  186,
-      184,  193,  184,  190,    0,  184,    0,  184,  177,  177,
-      190,    0,  178,  177,  182,  179,  186,    0,  188,    0,
-        0,  175,  175,  172,  166,  178,    0,    0,    0,  177,
-      167,  157,  161,  161,    0,  172,  165,    0,    0,  172,
-      161,    0,    0,  164,    0,  149,  153,    0,  161,    0,
-      142,  133,  104,  122,  115,  109,    0,  103,  100,   94,
-       88,   71,   20,    0,  345,  177,  180,  183,  188,  193,
-      195
+      202,  212,    0,  203,  204,  198,    0,    0,    0,  195,
+      200,  194,  193,  196,  199,  194,  189,  187,  196,  187,
+      193,    0,  187,  192,    0,  186,  179,  179,  192,    0,
+      180,  179,  184,  181,  188,    0,  190,    0,    0,  177,
+      177,  174,  354,  168,  180,    0,    0,    0,  179,  169,
+      159,  163,  163,    0,  174,  167,    0,    0,  174,  163,
+        0,    0,  166,    0,  151,  155,    0,  168,    0,  157,
+      147,  119,  125,  118,  109,    0,  104,  100,   97,   87,
+       64,   63,    0,  354,  179,  182,  185,  190,  195,  197
     } ;
 
-static yyconst flex_int16_t yy_def[282] =
+static yyconst flex_int16_t yy_def[291] =
     {   0,
-      275,    1,  275,  275,  275,  275,  275,  276,  277,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  275,  275,
-      275,  275,  275,  275,  278,  277,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  279,  280,  275,  275,  275,
-      275,  281,  275,  275,  275,  275,  275,  275,  275,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      284,    1,  284,  284,  284,  284,  284,  285,  286,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  284,
+      284,  284,  284,  284,  284,  287,  286,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  288,  289,  284,  284,
+      284,  284,  290,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
 
-      277,  277,  277,  277,  277,  277,  277,  277,  275,  275,
-      278,  275,  275,  279,  279,  280,  275,  275,  275,  275,
-      281,  275,  275,  275,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  275,  275,  275,  275,  275,  275,
-      275,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      275,  275,  277,  277,  277,  277,  277,  277,  277,  277,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  284,  284,  287,  284,  284,  288,  288,  289,  284,
+      284,  284,  284,  290,  284,  284,  284,  284,  284,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  284,
+      284,  284,  284,  284,  284,  284,  284,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  284,  284,  284,  286,
 
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
-      277,  277,  277,  277,    0,  275,  275,  275,  275,  275,
-      275
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  284,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  284,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,    0,  284,  284,  284,  284,  284,  284
     } ;
 
-static yyconst flex_uint16_t yy_nxt[403] =
+static yyconst flex_uint16_t yy_nxt[413] =
     {   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,    9,    9,   28,   29,   30,    9,
-        9,   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,  274,   69,   66,   70,
-       70,   64,   62,   67,   69,   59,   70,   70,   71,   68,
-       73,   74,   76,   77,   78,   71,   80,   71,   82,   81,
-       88,   79,   92,   84,   71,   94,  109,   85,  101,   93,
+       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,   64,   66,   66,   74,   75,   67,
+       77,   78,   65,   63,   68,   70,   60,   71,   71,   70,
+       69,   71,   71,   83,   79,   81,   84,   72,   85,   97,
+       87,   72,   80,   82,   88,   91,   72,   95,  104,   89,
 
-       89,   83,   86,   90,   72,  107,  102,  128,   95,  103,
-       53,   53,  129,  108,   65,   65,  117,  117,  273,   69,
-      272,   70,   70,  113,  144,  118,  120,  120,  271,  110,
-       71,  119,  113,  119,  118,  270,  120,  120,  269,   71,
-      145,  146,  156,  268,  156,  117,  117,  157,  157,  267,
-      160,  266,  160,  265,  159,  161,  161,  120,  120,  166,
-      167,  157,  157,  159,  157,  157,  191,  264,  191,  161,
-      161,  192,  192,  161,  161,  192,  192,  192,  192,   55,
-      263,   55,   56,   56,   56,  111,  111,  111,  114,  114,
-      114,  114,  114,  116,  262,  116,  116,  116,  121,  121,
+       72,   86,   98,  110,   96,   92,  105,  112,   93,  106,
+      283,  111,  282,   73,   54,   54,   66,   66,  120,  120,
+      281,   70,  149,   71,   71,  122,  116,  122,  121,  133,
+      123,  123,  280,   72,  134,  116,  279,  121,  150,  151,
+      278,  113,   72,  161,  277,  161,  120,  120,  162,  162,
+      123,  123,  165,  276,  165,  275,  164,  166,  166,  123,
+      123,  172,  173,  162,  162,  164,  162,  162,  197,  274,
+      197,  166,  166,  198,  198,  166,  166,  198,  198,  198,
+      198,   56,  273,   56,   57,   57,   57,  114,  114,  114,
+      117,  117,  117,  117,  117,  119,  272,  119,  119,  119,
 
-      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,  202,
-      201,  200,  199,  198,  197,  196,  195,  194,  193,  190,
-      189,  188,  187,  186,  185,  184,  183,  182,  181,  180,
-      179,  178,  177,  176,  175,  174,  173,  172,  171,  170,
-      169,  168,  165,  164,  163,  162,  158,  115,  155,  154,
+      124,  124,  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,  202,  201,  200,  199,  196,  195,  194,  193,  192,
+      191,  190,  189,  188,  187,  186,  185,  184,  183,  182,
+      181,  180,  179,  178,  177,  176,  175,  174,  171,  170,
 
-      153,  152,  151,  150,  149,  148,  147,  143,  142,  141,
-      140,  139,  138,  137,  136,  135,  134,  133,  132,  131,
-      130,  127,  126,  125,  124,  123,  122,  115,  112,  106,
-      105,  104,  100,   99,   98,   97,   96,   91,   87,   75,
-       60,   57,   54,  275,    3,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
+      169,  168,  167,  163,  118,  160,  159,  158,  157,  156,
+      155,  154,  153,  152,  148,  147,  146,  145,  144,  143,
+      142,  141,  140,  139,  138,  137,  136,  135,  132,  131,
+      130,  129,  128,  127,  126,  125,  118,  115,  109,  108,
+      107,  103,  102,  101,  100,   99,   94,   90,   76,   61,
+       58,   55,  284,    3,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
 
-      275,  275
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284
     } ;
 
-static yyconst flex_int16_t yy_chk[403] =
+static yyconst flex_int16_t yy_chk[413] =
     {   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,    5,    5,    6,
-        6,   11,   15,   17,   18,   18,  273,   20,   19,   20,
-       20,   17,   15,   19,   21,   11,   21,   21,   20,   19,
-       24,   24,   26,   26,   30,   21,   31,   20,   32,   31,
-       35,   30,   37,   33,   21,   38,   50,   33,   44,   37,
+        1,    1,    1,    1,    1,    1,    1,    1,    5,    5,
+        6,    6,   11,   15,   17,   18,   18,   24,   24,   19,
+       26,   26,   17,   15,   19,   20,   11,   20,   20,   21,
+       19,   21,   21,   32,   28,   31,   32,   20,   33,   39,
+       34,   21,   28,   31,   34,   36,   20,   38,   45,   34,
 
-       35,   32,   33,   35,   20,   48,   44,   83,   38,   44,
-       53,   53,   83,   48,   65,   65,   69,   69,  272,   70,
-      271,   70,   70,   65,  100,   69,  119,  119,  270,   50,
-       70,   71,   65,   71,   69,  269,   71,   71,  268,   70,
-      100,  100,  113,  266,  113,  117,  117,  113,  113,  265,
-      118,  264,  118,  263,  117,  118,  118,  120,  120,  129,
-      129,  156,  156,  117,  157,  157,  159,  262,  159,  160,
-      160,  159,  159,  161,  161,  191,  191,  192,  192,  276,
-      261,  276,  277,  277,  277,  278,  278,  278,  279,  279,
-      279,  279,  279,  280,  259,  280,  280,  280,  281,  281,
+       21,   33,   39,   49,   38,   36,   45,   51,   36,   45,
+      282,   49,  281,   20,   54,   54,   66,   66,   70,   70,
+      280,   71,  103,   71,   71,   72,   66,   72,   70,   86,
+       72,   72,  279,   71,   86,   66,  278,   70,  103,  103,
+      277,   51,   71,  116,  275,  116,  120,  120,  116,  116,
+      122,  122,  121,  274,  121,  273,  120,  121,  121,  123,
+      123,  134,  134,  161,  161,  120,  162,  162,  164,  272,
+      164,  165,  165,  164,  164,  166,  166,  197,  197,  198,
+      198,  285,  271,  285,  286,  286,  286,  287,  287,  287,
+      288,  288,  288,  288,  288,  289,  270,  289,  289,  289,
 
-      257,  256,  254,  251,  250,  247,  246,  244,  243,  242,
-      241,  240,  236,  235,  234,  233,  232,  229,  227,  226,
-      225,  224,  223,  221,  220,  219,  218,  216,  214,  213,
-      212,  211,  210,  209,  208,  207,  206,  205,  204,  203,
-      199,  198,  197,  195,  194,  190,  189,  188,  187,  185,
-      184,  183,  182,  181,  180,  179,  178,  177,  175,  174,
-      173,  171,  169,  168,  167,  166,  165,  163,  162,  154,
-      153,  152,  151,  150,  149,  148,  147,  146,  145,  144,
-      143,  141,  140,  139,  138,  137,  136,  134,  133,  132,
-      131,  130,  128,  127,  126,  125,  115,  114,  110,  108,
+      290,  290,  268,  266,  265,  263,  260,  259,  256,  255,
+      253,  252,  251,  250,  249,  245,  244,  242,  241,  240,
+      237,  235,  234,  233,  232,  231,  229,  228,  227,  226,
+      224,  223,  221,  220,  219,  218,  217,  216,  215,  214,
+      213,  212,  211,  210,  206,  205,  204,  202,  201,  199,
+      196,  195,  194,  193,  191,  190,  189,  188,  187,  186,
+      185,  184,  183,  181,  180,  179,  177,  175,  174,  173,
+      172,  171,  169,  168,  167,  159,  158,  157,  156,  155,
+      154,  153,  152,  151,  150,  149,  148,  146,  145,  144,
+      143,  142,  141,  139,  138,  137,  136,  135,  133,  132,
 
-      107,  106,  105,  104,  103,  102,  101,   99,   98,   97,
-       96,   95,   94,   93,   91,   90,   89,   88,   87,   85,
-       84,   82,   81,   80,   79,   77,   73,   66,   58,   47,
-       46,   45,   43,   42,   41,   40,   39,   36,   34,   25,
-       14,   10,    7,    3,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
-      275,  275,  275,  275,  275,  275,  275,  275,  275,  275,
+      131,  130,  128,  118,  117,  113,  111,  110,  109,  108,
+      107,  106,  105,  104,  102,  101,  100,   99,   98,   97,
+       96,   94,   93,   92,   91,   90,   88,   87,   85,   84,
+       83,   82,   80,   79,   78,   74,   67,   59,   48,   47,
+       46,   44,   43,   42,   41,   40,   37,   35,   25,   14,
+       10,    7,    3,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
 
-      275,  275
+      284,  284,  284,  284,  284,  284,  284,  284,  284,  284,
+      284,  284
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[95] =
+static yyconst flex_int32_t yy_rule_can_match_eol[97] =
     {   0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 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, 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.
@@ -651,7 +654,7 @@
 
 */
 #define YY_NO_UNISTD_H 1
-#line 655 "lex.sksl.c"
+#line 658 "lex.sksl.c"
 
 #define INITIAL 0
 
@@ -915,7 +918,7 @@
 #line 30 "sksl.flex"
 
 
-#line 919 "lex.sksl.c"
+#line 922 "lex.sksl.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -942,13 +945,13 @@
 			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 >= 276 )
+				if ( yy_current_state >= 285 )
 					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 != 275 );
+		while ( yy_current_state != 284 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -1023,436 +1026,446 @@
 case 9:
 YY_RULE_SETUP
 #line 48 "sksl.flex"
-{ return SkSL::Token::ELSE; }
+{ return SkSL::Token::STATIC_IF; }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
 #line 50 "sksl.flex"
-{ return SkSL::Token::FOR; }
+{ return SkSL::Token::ELSE; }
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
 #line 52 "sksl.flex"
-{ return SkSL::Token::WHILE; }
+{ return SkSL::Token::FOR; }
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
 #line 54 "sksl.flex"
-{ return SkSL::Token::DO; }
+{ return SkSL::Token::WHILE; }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
 #line 56 "sksl.flex"
-{ return SkSL::Token::SWITCH; }
+{ return SkSL::Token::DO; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
 #line 58 "sksl.flex"
-{ return SkSL::Token::CASE; }
+{ return SkSL::Token::SWITCH; }
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
 #line 60 "sksl.flex"
-{ return SkSL::Token::DEFAULT; }
+{ return SkSL::Token::STATIC_SWITCH; }
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
 #line 62 "sksl.flex"
-{ return SkSL::Token::BREAK; }
+{ return SkSL::Token::CASE; }
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
 #line 64 "sksl.flex"
-{ return SkSL::Token::CONTINUE; }
+{ return SkSL::Token::DEFAULT; }
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
 #line 66 "sksl.flex"
-{ return SkSL::Token::DISCARD; }
+{ return SkSL::Token::BREAK; }
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 68 "sksl.flex"
-{ return SkSL::Token::RETURN; }
+{ return SkSL::Token::CONTINUE; }
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
 #line 70 "sksl.flex"
-{ return SkSL::Token::IN; }
+{ return SkSL::Token::DISCARD; }
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
 #line 72 "sksl.flex"
-{ return SkSL::Token::OUT; }
+{ return SkSL::Token::RETURN; }
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
 #line 74 "sksl.flex"
-{ return SkSL::Token::INOUT; }
+{ return SkSL::Token::IN; }
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
 #line 76 "sksl.flex"
-{ return SkSL::Token::UNIFORM; }
+{ return SkSL::Token::OUT; }
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
 #line 78 "sksl.flex"
-{ return SkSL::Token::CONST; }
+{ return SkSL::Token::INOUT; }
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
 #line 80 "sksl.flex"
-{ return SkSL::Token::LOWP; }
+{ return SkSL::Token::UNIFORM; }
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
 #line 82 "sksl.flex"
-{ return SkSL::Token::MEDIUMP; }
+{ return SkSL::Token::CONST; }
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
 #line 84 "sksl.flex"
-{ return SkSL::Token::HIGHP; }
+{ return SkSL::Token::LOWP; }
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
 #line 86 "sksl.flex"
-{ return SkSL::Token::FLAT; }
+{ return SkSL::Token::MEDIUMP; }
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
 #line 88 "sksl.flex"
-{ return SkSL::Token::NOPERSPECTIVE; }
+{ return SkSL::Token::HIGHP; }
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
 #line 90 "sksl.flex"
-{ return SkSL::Token::READONLY; }
+{ return SkSL::Token::FLAT; }
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
 #line 92 "sksl.flex"
-{ return SkSL::Token::WRITEONLY; }
+{ return SkSL::Token::NOPERSPECTIVE; }
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
 #line 94 "sksl.flex"
-{ return SkSL::Token::COHERENT; }
+{ return SkSL::Token::READONLY; }
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
 #line 96 "sksl.flex"
-{ return SkSL::Token::VOLATILE; }
+{ return SkSL::Token::WRITEONLY; }
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
 #line 98 "sksl.flex"
-{ return SkSL::Token::RESTRICT; }
+{ return SkSL::Token::COHERENT; }
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
 #line 100 "sksl.flex"
-{ return SkSL::Token::BUFFER; }
+{ return SkSL::Token::VOLATILE; }
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
 #line 102 "sksl.flex"
-{ return SkSL::Token::HASSIDEEFFECTS; }
+{ return SkSL::Token::RESTRICT; }
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
 #line 104 "sksl.flex"
-{ return SkSL::Token::STRUCT; }
+{ return SkSL::Token::BUFFER; }
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
 #line 106 "sksl.flex"
-{ return SkSL::Token::LAYOUT; }
+{ return SkSL::Token::HASSIDEEFFECTS; }
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
 #line 108 "sksl.flex"
-{ return SkSL::Token::PRECISION; }
+{ return SkSL::Token::STRUCT; }
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
 #line 110 "sksl.flex"
-{ return SkSL::Token::IDENTIFIER; }
+{ return SkSL::Token::LAYOUT; }
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
 #line 112 "sksl.flex"
-{ return SkSL::Token::DIRECTIVE; }
+{ return SkSL::Token::PRECISION; }
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
 #line 114 "sksl.flex"
-{ return SkSL::Token::LPAREN; }
+{ return SkSL::Token::IDENTIFIER; }
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
 #line 116 "sksl.flex"
-{ return SkSL::Token::RPAREN; }
+{ return SkSL::Token::DIRECTIVE; }
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
 #line 118 "sksl.flex"
-{ return SkSL::Token::LBRACE; }
+{ return SkSL::Token::LPAREN; }
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
 #line 120 "sksl.flex"
-{ return SkSL::Token::RBRACE; }
+{ return SkSL::Token::RPAREN; }
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
 #line 122 "sksl.flex"
-{ return SkSL::Token::LBRACKET; }
+{ return SkSL::Token::LBRACE; }
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
 #line 124 "sksl.flex"
-{ return SkSL::Token::RBRACKET; }
+{ return SkSL::Token::RBRACE; }
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
 #line 126 "sksl.flex"
-{ return SkSL::Token::DOT; }
+{ return SkSL::Token::LBRACKET; }
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
 #line 128 "sksl.flex"
-{ return SkSL::Token::COMMA; }
+{ return SkSL::Token::RBRACKET; }
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
 #line 130 "sksl.flex"
-{ return SkSL::Token::PLUSPLUS; }
+{ return SkSL::Token::DOT; }
 	YY_BREAK
 case 51:
 YY_RULE_SETUP
 #line 132 "sksl.flex"
-{ return SkSL::Token::MINUSMINUS; }
+{ return SkSL::Token::COMMA; }
 	YY_BREAK
 case 52:
 YY_RULE_SETUP
 #line 134 "sksl.flex"
-{ return SkSL::Token::PLUS; }
+{ return SkSL::Token::PLUSPLUS; }
 	YY_BREAK
 case 53:
 YY_RULE_SETUP
 #line 136 "sksl.flex"
-{ return SkSL::Token::MINUS; }
+{ return SkSL::Token::MINUSMINUS; }
 	YY_BREAK
 case 54:
 YY_RULE_SETUP
 #line 138 "sksl.flex"
-{ return SkSL::Token::STAR; }
+{ return SkSL::Token::PLUS; }
 	YY_BREAK
 case 55:
 YY_RULE_SETUP
 #line 140 "sksl.flex"
-{ return SkSL::Token::SLASH; }
+{ return SkSL::Token::MINUS; }
 	YY_BREAK
 case 56:
 YY_RULE_SETUP
 #line 142 "sksl.flex"
-{ return SkSL::Token::PERCENT; }
+{ return SkSL::Token::STAR; }
 	YY_BREAK
 case 57:
 YY_RULE_SETUP
 #line 144 "sksl.flex"
-{ return SkSL::Token::SHL; }
+{ return SkSL::Token::SLASH; }
 	YY_BREAK
 case 58:
 YY_RULE_SETUP
 #line 146 "sksl.flex"
-{ return SkSL::Token::SHR; }
+{ return SkSL::Token::PERCENT; }
 	YY_BREAK
 case 59:
 YY_RULE_SETUP
 #line 148 "sksl.flex"
-{ return SkSL::Token::BITWISEOR; }
+{ return SkSL::Token::SHL; }
 	YY_BREAK
 case 60:
 YY_RULE_SETUP
 #line 150 "sksl.flex"
-{ return SkSL::Token::BITWISEXOR; }
+{ return SkSL::Token::SHR; }
 	YY_BREAK
 case 61:
 YY_RULE_SETUP
 #line 152 "sksl.flex"
-{ return SkSL::Token::BITWISEAND; }
+{ return SkSL::Token::BITWISEOR; }
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
 #line 154 "sksl.flex"
-{ return SkSL::Token::BITWISENOT; }
+{ return SkSL::Token::BITWISEXOR; }
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
 #line 156 "sksl.flex"
-{ return SkSL::Token::LOGICALOR; }
+{ return SkSL::Token::BITWISEAND; }
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
 #line 158 "sksl.flex"
-{ return SkSL::Token::LOGICALXOR; }
+{ return SkSL::Token::BITWISENOT; }
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
 #line 160 "sksl.flex"
-{ return SkSL::Token::LOGICALAND; }
+{ return SkSL::Token::LOGICALOR; }
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
 #line 162 "sksl.flex"
-{ return SkSL::Token::LOGICALNOT; }
+{ return SkSL::Token::LOGICALXOR; }
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
 #line 164 "sksl.flex"
-{ return SkSL::Token::QUESTION; }
+{ return SkSL::Token::LOGICALAND; }
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
 #line 166 "sksl.flex"
-{ return SkSL::Token::COLON; }
+{ return SkSL::Token::LOGICALNOT; }
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
 #line 168 "sksl.flex"
-{ return SkSL::Token::EQ; }
+{ return SkSL::Token::QUESTION; }
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
 #line 170 "sksl.flex"
-{ return SkSL::Token::EQEQ; }
+{ return SkSL::Token::COLON; }
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
 #line 172 "sksl.flex"
-{ return SkSL::Token::NEQ; }
+{ return SkSL::Token::EQ; }
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
 #line 174 "sksl.flex"
-{ return SkSL::Token::GT; }
+{ return SkSL::Token::EQEQ; }
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
 #line 176 "sksl.flex"
-{ return SkSL::Token::LT; }
+{ return SkSL::Token::NEQ; }
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
 #line 178 "sksl.flex"
-{ return SkSL::Token::GTEQ; }
+{ return SkSL::Token::GT; }
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
 #line 180 "sksl.flex"
-{ return SkSL::Token::LTEQ; }
+{ return SkSL::Token::LT; }
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
 #line 182 "sksl.flex"
-{ return SkSL::Token::PLUSEQ; }
+{ return SkSL::Token::GTEQ; }
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
 #line 184 "sksl.flex"
-{ return SkSL::Token::MINUSEQ; }
+{ return SkSL::Token::LTEQ; }
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
 #line 186 "sksl.flex"
-{ return SkSL::Token::STAREQ; }
+{ return SkSL::Token::PLUSEQ; }
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
 #line 188 "sksl.flex"
-{ return SkSL::Token::SLASHEQ; }
+{ return SkSL::Token::MINUSEQ; }
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
 #line 190 "sksl.flex"
-{ return SkSL::Token::PERCENTEQ; }
+{ return SkSL::Token::STAREQ; }
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
 #line 192 "sksl.flex"
-{ return SkSL::Token::SHLEQ; }
+{ return SkSL::Token::SLASHEQ; }
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
 #line 194 "sksl.flex"
-{ return SkSL::Token::SHREQ; }
+{ return SkSL::Token::PERCENTEQ; }
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
 #line 196 "sksl.flex"
-{ return SkSL::Token::BITWISEOREQ; }
+{ return SkSL::Token::SHLEQ; }
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
 #line 198 "sksl.flex"
-{ return SkSL::Token::BITWISEXOREQ; }
+{ return SkSL::Token::SHREQ; }
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
 #line 200 "sksl.flex"
-{ return SkSL::Token::BITWISEANDEQ; }
+{ return SkSL::Token::BITWISEOREQ; }
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
 #line 202 "sksl.flex"
-{ return SkSL::Token::LOGICALOREQ; }
+{ return SkSL::Token::BITWISEXOREQ; }
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
 #line 204 "sksl.flex"
-{ return SkSL::Token::LOGICALXOREQ; }
+{ return SkSL::Token::BITWISEANDEQ; }
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
 #line 206 "sksl.flex"
-{ return SkSL::Token::LOGICALANDEQ; }
+{ return SkSL::Token::LOGICALOREQ; }
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
 #line 208 "sksl.flex"
-{ return SkSL::Token::SEMICOLON; }
+{ return SkSL::Token::LOGICALXOREQ; }
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
 #line 210 "sksl.flex"
-/* line comment */
+{ return SkSL::Token::LOGICALANDEQ; }
 	YY_BREAK
 case 91:
-/* rule 91 can match eol */
 YY_RULE_SETUP
 #line 212 "sksl.flex"
-/* block comment */
+{ return SkSL::Token::SEMICOLON; }
 	YY_BREAK
 case 92:
-/* rule 92 can match eol */
 YY_RULE_SETUP
 #line 214 "sksl.flex"
-/* whitespace */
+/* line comment */
 	YY_BREAK
 case 93:
+/* rule 93 can match eol */
 YY_RULE_SETUP
 #line 216 "sksl.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
+/* block comment */
 	YY_BREAK
 case 94:
+/* rule 94 can match eol */
 YY_RULE_SETUP
 #line 218 "sksl.flex"
+/* whitespace */
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 220 "sksl.flex"
+{ return SkSL::Token::INVALID_TOKEN; }
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 222 "sksl.flex"
 ECHO;
 	YY_BREAK
-#line 1456 "lex.sksl.c"
+#line 1469 "lex.sksl.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1748,7 +1761,7 @@
 		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 >= 276 )
+			if ( yy_current_state >= 285 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
@@ -1777,11 +1790,11 @@
 	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 >= 276 )
+		if ( yy_current_state >= 285 )
 			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 == 275);
+	yy_is_jam = (yy_current_state == 284);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
@@ -2633,7 +2646,7 @@
 
 #define YYTABLES_NAME "yytables"
 
-#line 218 "sksl.flex"
+#line 222 "sksl.flex"
 
 
 
diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex
index c35ce5d..c5d5ec3 100644
--- a/src/sksl/sksl.flex
+++ b/src/sksl/sksl.flex
@@ -45,6 +45,8 @@
 
 if { return SkSL::Token::IF; }
 
+@if { return SkSL::Token::STATIC_IF; }
+
 else { return SkSL::Token::ELSE; }
 
 for { return SkSL::Token::FOR; }
@@ -55,6 +57,8 @@
 
 switch { return SkSL::Token::SWITCH; }
 
+@switch { return SkSL::Token::STATIC_SWITCH; }
+
 case { return SkSL::Token::CASE; }
 
 default { return SkSL::Token::DEFAULT; }