aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLParser.cpp
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 /src/sksl/SkSLParser.cpp
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>
Diffstat (limited to 'src/sksl/SkSLParser.cpp')
-rw-r--r--src/sksl/SkSLParser.cpp84
1 files changed, 84 insertions, 0 deletions
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() {