diff options
Diffstat (limited to 'src/sksl/SkSLParser.cpp')
-rw-r--r-- | src/sksl/SkSLParser.cpp | 158 |
1 files changed, 135 insertions, 23 deletions
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index 5e8ec6398b..18ca311ee7 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -52,6 +52,7 @@ static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 + #include "ast/SkSLASTPrecision.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" +#include "ast/SkSLASTSection.h" #include "ast/SkSLASTStatement.h" #include "ast/SkSLASTSuffixExpression.h" #include "ast/SkSLASTSwitchCase.h" @@ -113,7 +114,7 @@ Parser::~Parser() { layoutlex_destroy(fLayoutScanner); } -/* (precision | directive | declaration)* END_OF_FILE */ +/* (precision | directive | section | declaration)* END_OF_FILE */ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { std::vector<std::unique_ptr<ASTDeclaration>> result; for (;;) { @@ -134,6 +135,13 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } break; } + case Token::SECTION: { + std::unique_ptr<ASTDeclaration> section = this->section(); + if (section) { + result.push_back(std::move(section)); + } + break; + } default: { std::unique_ptr<ASTDeclaration> decl = this->declaration(); if (!decl) { @@ -145,7 +153,7 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } } -Token Parser::nextToken() { +Token Parser::nextRawToken() { if (fPushback.fKind != Token::INVALID_TOKEN) { Token result = fPushback; fPushback.fKind = Token::INVALID_TOKEN; @@ -153,25 +161,16 @@ Token Parser::nextToken() { return result; } int token = sksllex(fScanner); - String text; - switch ((Token::Kind) token) { - case Token::IDENTIFIER: // fall through - case Token::INT_LITERAL: // fall through - case Token::FLOAT_LITERAL: // fall through - case Token::DIRECTIVE: - text = String(skslget_text(fScanner)); - break; - default: -#ifdef SK_DEBUG - text = String(skslget_text(fScanner)); -#endif - break; - } - 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); + return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, + String(skslget_text(fScanner))); +} + +Token Parser::nextToken() { + Token token; + do { + token = this->nextRawToken(); + } while (token.fKind == Token::WHITESPACE); + return token; } void Parser::pushback(Token t) { @@ -296,6 +295,56 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { } } +/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces> + RBRACE */ +std::unique_ptr<ASTDeclaration> Parser::section() { + Token start; + if (!this->expect(Token::SECTION, "a section token", &start)) { + return nullptr; + } + String argument; + if (this->peek().fKind == Token::LPAREN) { + this->nextToken(); + Token argToken; + if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) { + return nullptr; + } + argument = argToken.fText; + if (!this->expect(Token::RPAREN, "')'")) { + return nullptr; + } + } + if (!this->expect(Token::LBRACE, "'{'")) { + return nullptr; + } + String text; + int level = 1; + for (;;) { + Token next = this->nextRawToken(); + switch (next.fKind) { + case Token::LBRACE: + ++level; + break; + case Token::RBRACE: + --level; + break; + case Token::END_OF_FILE: + this->error(start.fPosition, "reached end of file while parsing section"); + return nullptr; + default: + break; + } + if (!level) { + break; + } + text += next.fText; + } + return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition, + String(start.fText.c_str() + 1), + argument, + text)); +} + /* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */ std::unique_ptr<ASTDeclaration> Parser::declaration() { @@ -544,6 +593,61 @@ int Parser::layoutInt() { return -1; } +/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */ +String Parser::layoutCode() { + if (!this->expect(Token::EQ, "'='")) { + return ""; + } + Token start = this->peek(); + String code; + int level = 1; + bool done = false; + while (!done) { + Token next = this->peek(); + switch (next.fKind) { + case Token::LPAREN: + ++level; + break; + case Token::RPAREN: + --level; + break; + case Token::COMMA: + if (level == 1) { + done = true; + } + break; + case Token::END_OF_FILE: + this->error(start.fPosition, "reached end of file while parsing layout"); + return nullptr; + default: + break; + } + if (!level) { + done = true; + } + if (!done) { + code += this->nextRawToken().fText; + } + } + return code; +} + +/** (EQ IDENTIFIER('identity'))? */ +Layout::Key Parser::layoutKey() { + if (this->peek().fKind == Token::EQ) { + this->expect(Token::EQ, "'='"); + Token key; + if (this->expect(Token::IDENTIFIER, "an identifer", &key)) { + if (key.fText == "identity") { + return Layout::kIdentity_Key; + } else { + this->error(key.fPosition, "unsupported layout key"); + } + } + } + return Layout::kKey_Key; +} + /* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */ Layout Parser::layout() { int location = -1; @@ -561,11 +665,13 @@ Layout Parser::layout() { Layout::Primitive primitive = Layout::kUnspecified_Primitive; int maxVertices = -1; int invocations = -1; + String when; + Layout::Key key = Layout::kNo_Key; if (this->checkNext(Token::LAYOUT)) { if (!this->expect(Token::LPAREN, "'('")) { return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, overrideCoverage, blendSupportAllEquations, format, - pushConstant, primitive, maxVertices, invocations); + pushConstant, primitive, maxVertices, invocations, when, key); } for (;;) { Token t = this->nextToken(); @@ -635,6 +741,12 @@ Layout Parser::layout() { case Token::INVOCATIONS: invocations = this->layoutInt(); break; + case Token::WHEN: + when = this->layoutCode(); + break; + case Token::KEY: + key = this->layoutKey(); + break; } } else if (Layout::ReadFormat(t.fText, &format)) { // AST::ReadFormat stored the result in 'format'. @@ -652,7 +764,7 @@ Layout Parser::layout() { } return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, overrideCoverage, blendSupportAllEquations, format, - pushConstant, primitive, maxVertices, invocations); + pushConstant, primitive, maxVertices, invocations, when, key); } /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE | |