/* * 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 "SkSLErrorReporter.h" #include "ir/SkSLLayout.h" #include "SkSLLexer.h" #include "SkSLLayoutLexer.h" struct yy_buffer_state; #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; namespace SkSL { struct ASTBlock; struct ASTBreakStatement; struct ASTContinueStatement; struct ASTDeclaration; struct ASTDiscardStatement; struct ASTDoStatement; struct ASTExpression; struct ASTExpressionStatement; struct ASTForStatement; struct ASTIfStatement; struct ASTInterfaceBlock; struct ASTParameter; struct ASTPrecision; struct ASTReturnStatement; struct ASTStatement; struct ASTSuffix; struct ASTSwitchCase; struct ASTSwitchStatement; struct ASTType; struct ASTWhileStatement; struct ASTVarDeclarations; struct Modifiers; class SymbolTable; /** * Consumes .sksl text and produces an abstract syntax tree describing the contents. */ class Parser { public: Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors); /** * Consumes a complete .sksl file and produces a list of declarations. Errors are reported via * the ErrorReporter; the return value may contain some declarations even when errors have * occurred. */ std::vector<std::unique_ptr<ASTDeclaration>> file(); StringFragment text(Token token); Position position(Token token); private: /** * 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); // 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. std::unique_ptr<ASTDeclaration> precision(); std::unique_ptr<ASTDeclaration> directive(); std::unique_ptr<ASTDeclaration> section(); std::unique_ptr<ASTDeclaration> enumDeclaration(); std::unique_ptr<ASTDeclaration> declaration(); std::unique_ptr<ASTVarDeclarations> varDeclarations(); std::unique_ptr<ASTType> structDeclaration(); std::unique_ptr<ASTVarDeclarations> structVarDeclaration(Modifiers modifiers); std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers, std::unique_ptr<ASTType> type, StringFragment name); std::unique_ptr<ASTParameter> parameter(); int layoutInt(); StringFragment layoutIdentifier(); String layoutCode(); Layout::Key layoutKey(); Layout layout(); Modifiers modifiers(); Modifiers modifiersWithDefaults(int defaultFlags); std::unique_ptr<ASTStatement> statement(); std::unique_ptr<ASTType> type(); std::unique_ptr<ASTDeclaration> interfaceBlock(Modifiers mods); std::unique_ptr<ASTIfStatement> ifStatement(); std::unique_ptr<ASTDoStatement> doStatement(); std::unique_ptr<ASTWhileStatement> whileStatement(); 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(); std::unique_ptr<ASTContinueStatement> continueStatement(); std::unique_ptr<ASTDiscardStatement> discardStatement(); std::unique_ptr<ASTBlock> block(); std::unique_ptr<ASTExpressionStatement> expressionStatement(); std::unique_ptr<ASTExpression> expression(); std::unique_ptr<ASTExpression> commaExpression(); std::unique_ptr<ASTExpression> assignmentExpression(); std::unique_ptr<ASTExpression> ternaryExpression(); std::unique_ptr<ASTExpression> logicalOrExpression(); std::unique_ptr<ASTExpression> logicalXorExpression(); std::unique_ptr<ASTExpression> logicalAndExpression(); std::unique_ptr<ASTExpression> bitwiseOrExpression(); std::unique_ptr<ASTExpression> bitwiseXorExpression(); std::unique_ptr<ASTExpression> bitwiseAndExpression(); std::unique_ptr<ASTExpression> equalityExpression(); std::unique_ptr<ASTExpression> relationalExpression(); std::unique_ptr<ASTExpression> shiftExpression(); std::unique_ptr<ASTExpression> additiveExpression(); std::unique_ptr<ASTExpression> multiplicativeExpression(); std::unique_ptr<ASTExpression> unaryExpression(); std::unique_ptr<ASTExpression> postfixExpression(); std::unique_ptr<ASTSuffix> suffix(); std::unique_ptr<ASTExpression> term(); bool intLiteral(int64_t* dest); bool floatLiteral(double* dest); bool boolLiteral(bool* dest); bool identifier(StringFragment* dest); const char* fText; Lexer fLexer; LayoutLexer fLayoutLexer; 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& fTypes; ErrorReporter& fErrors; friend class AutoDepth; friend class HCodeGenerator; }; } // namespace #endif