| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_PARSER |
| #define SKSL_PARSER |
| |
| #include <vector> |
| #include <memory> |
| #include <unordered_map> |
| #include <unordered_set> |
| #include "src/sksl/SkSLASTFile.h" |
| #include "src/sksl/SkSLASTNode.h" |
| #include "src/sksl/SkSLErrorReporter.h" |
| #include "src/sksl/SkSLLexer.h" |
| #include "src/sksl/ir/SkSLLayout.h" |
| |
| struct yy_buffer_state; |
| #define YY_TYPEDEF_YY_BUFFER_STATE |
| typedef struct yy_buffer_state *YY_BUFFER_STATE; |
| |
| namespace SkSL { |
| |
| struct Modifiers; |
| class SymbolTable; |
| static constexpr int kMaxArrayDimensionality = 1; |
| static constexpr int kMaxStructDepth = 8; |
| |
| /** |
| * Consumes .sksl text and produces an abstract syntax tree describing the contents. |
| */ |
| class Parser { |
| public: |
| enum class LayoutToken { |
| LOCATION, |
| OFFSET, |
| BINDING, |
| INDEX, |
| SET, |
| BUILTIN, |
| INPUT_ATTACHMENT_INDEX, |
| ORIGIN_UPPER_LEFT, |
| OVERRIDE_COVERAGE, |
| BLEND_SUPPORT_ALL_EQUATIONS, |
| BLEND_SUPPORT_MULTIPLY, |
| BLEND_SUPPORT_SCREEN, |
| BLEND_SUPPORT_OVERLAY, |
| BLEND_SUPPORT_DARKEN, |
| BLEND_SUPPORT_LIGHTEN, |
| BLEND_SUPPORT_COLORDODGE, |
| BLEND_SUPPORT_COLORBURN, |
| BLEND_SUPPORT_HARDLIGHT, |
| BLEND_SUPPORT_SOFTLIGHT, |
| BLEND_SUPPORT_DIFFERENCE, |
| BLEND_SUPPORT_EXCLUSION, |
| BLEND_SUPPORT_HSL_HUE, |
| BLEND_SUPPORT_HSL_SATURATION, |
| BLEND_SUPPORT_HSL_COLOR, |
| BLEND_SUPPORT_HSL_LUMINOSITY, |
| PUSH_CONSTANT, |
| POINTS, |
| LINES, |
| LINE_STRIP, |
| LINES_ADJACENCY, |
| TRIANGLES, |
| TRIANGLE_STRIP, |
| TRIANGLES_ADJACENCY, |
| MAX_VERTICES, |
| INVOCATIONS, |
| MARKER, |
| WHEN, |
| KEY, |
| TRACKED, |
| SRGB_UNPREMUL, |
| CTYPE, |
| SKPMCOLOR4F, |
| SKV4, |
| SKRECT, |
| SKIRECT, |
| SKPMCOLOR, |
| SKM44, |
| BOOL, |
| INT, |
| FLOAT, |
| }; |
| |
| Parser(const char* text, size_t length, SymbolTable& symbols, ErrorReporter& errors); |
| |
| /** |
| * Consumes a complete .sksl file and returns the parse tree. Errors are reported via the |
| * ErrorReporter; the return value may contain some declarations even when errors have occurred. |
| */ |
| std::unique_ptr<ASTFile> compilationUnit(); |
| |
| StringFragment text(Token token); |
| |
| Position position(Token token); |
| |
| private: |
| static void InitLayoutMap(); |
| |
| /** |
| * Return the next token, including whitespace tokens, from the parse stream. |
| */ |
| Token nextRawToken(); |
| |
| /** |
| * Return the next non-whitespace token from the parse stream. |
| */ |
| Token nextToken(); |
| |
| /** |
| * Push a token back onto the parse stream, so that it is the next one read. Only a single level |
| * of pushback is supported (that is, it is an error to call pushback() twice in a row without |
| * an intervening nextToken()). |
| */ |
| void pushback(Token t); |
| |
| /** |
| * Returns the next non-whitespace token without consuming it from the stream. |
| */ |
| Token peek(); |
| |
| /** |
| * Checks to see if the next token is of the specified type. If so, stores it in result (if |
| * result is non-null) and returns true. Otherwise, pushes it back and returns false. |
| */ |
| bool checkNext(Token::Kind kind, Token* result = nullptr); |
| |
| /** |
| * Reads the next non-whitespace token and generates an error if it is not the expected type. |
| * The 'expected' string is part of the error message, which reads: |
| * |
| * "expected <expected>, but found '<actual text>'" |
| * |
| * If 'result' is non-null, it is set to point to the token that was read. |
| * Returns true if the read token was as expected, false otherwise. |
| */ |
| bool expect(Token::Kind kind, const char* expected, Token* result = nullptr); |
| bool expect(Token::Kind kind, String expected, Token* result = nullptr); |
| |
| void error(Token token, String msg); |
| void error(int offset, String msg); |
| /** |
| * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will |
| * always return true. |
| */ |
| bool isType(StringFragment name); |
| |
| // The pointer to the node may be invalidated by modifying the fNodes vector |
| ASTNode& getNode(ASTNode::ID id) { |
| SkASSERT(id.fValue >= 0 && id.fValue < (int) fFile->fNodes.size()); |
| return fFile->fNodes[id.fValue]; |
| } |
| |
| // these functions parse individual grammar rules from the current parse position; you probably |
| // don't need to call any of these outside of the parser. The function declarations in the .cpp |
| // file have comments describing the grammar rules. |
| |
| ASTNode::ID precision(); |
| |
| ASTNode::ID directive(); |
| |
| ASTNode::ID section(); |
| |
| ASTNode::ID enumDeclaration(); |
| |
| ASTNode::ID declaration(); |
| |
| ASTNode::ID varDeclarations(); |
| |
| ASTNode::ID structDeclaration(); |
| |
| ASTNode::ID structVarDeclaration(Modifiers modifiers); |
| |
| ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name); |
| |
| ASTNode::ID parameter(); |
| |
| int layoutInt(); |
| |
| StringFragment layoutIdentifier(); |
| |
| StringFragment layoutCode(); |
| |
| Layout::Key layoutKey(); |
| |
| Layout::CType layoutCType(); |
| |
| Layout layout(); |
| |
| Modifiers modifiers(); |
| |
| Modifiers modifiersWithDefaults(int defaultFlags); |
| |
| ASTNode::ID statement(); |
| |
| ASTNode::ID type(); |
| |
| ASTNode::ID interfaceBlock(Modifiers mods); |
| |
| ASTNode::ID ifStatement(); |
| |
| ASTNode::ID doStatement(); |
| |
| ASTNode::ID whileStatement(); |
| |
| ASTNode::ID forStatement(); |
| |
| ASTNode::ID switchCase(); |
| |
| ASTNode::ID switchStatement(); |
| |
| ASTNode::ID returnStatement(); |
| |
| ASTNode::ID breakStatement(); |
| |
| ASTNode::ID continueStatement(); |
| |
| ASTNode::ID discardStatement(); |
| |
| ASTNode::ID block(); |
| |
| ASTNode::ID expressionStatement(); |
| |
| ASTNode::ID expression(); |
| |
| ASTNode::ID assignmentExpression(); |
| |
| ASTNode::ID ternaryExpression(); |
| |
| ASTNode::ID logicalOrExpression(); |
| |
| ASTNode::ID logicalXorExpression(); |
| |
| ASTNode::ID logicalAndExpression(); |
| |
| ASTNode::ID bitwiseOrExpression(); |
| |
| ASTNode::ID bitwiseXorExpression(); |
| |
| ASTNode::ID bitwiseAndExpression(); |
| |
| ASTNode::ID equalityExpression(); |
| |
| ASTNode::ID relationalExpression(); |
| |
| ASTNode::ID shiftExpression(); |
| |
| ASTNode::ID additiveExpression(); |
| |
| ASTNode::ID multiplicativeExpression(); |
| |
| ASTNode::ID unaryExpression(); |
| |
| ASTNode::ID postfixExpression(); |
| |
| ASTNode::ID suffix(ASTNode::ID base); |
| |
| ASTNode::ID term(); |
| |
| bool intLiteral(SKSL_INT* dest); |
| |
| bool floatLiteral(SKSL_FLOAT* dest); |
| |
| bool boolLiteral(bool* dest); |
| |
| bool identifier(StringFragment* dest); |
| |
| template <typename... Args> ASTNode::ID createNode(Args&&... args); |
| |
| ASTNode::ID addChild(ASTNode::ID target, ASTNode::ID child); |
| |
| void createEmptyChild(ASTNode::ID target); |
| |
| static std::unordered_map<String, LayoutToken>* layoutTokens; |
| |
| const char* fText; |
| Lexer fLexer; |
| YY_BUFFER_STATE fBuffer; |
| // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the |
| // stack on pathological inputs |
| int fDepth = 0; |
| Token fPushback; |
| SymbolTable& fSymbols; |
| ErrorReporter& fErrors; |
| |
| std::unique_ptr<ASTFile> fFile; |
| |
| friend class AutoDepth; |
| friend class HCodeGenerator; |
| }; |
| |
| } // namespace SkSL |
| |
| #endif |