/*
 * Copyright 2021 Google LLC.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKSL_DSLPARSER
#define SKSL_DSLPARSER

#include "include/core/SkTypes.h"
#include "include/private/SkSLDefines.h"
#include "include/private/SkSLProgramKind.h"
#include "include/private/SkTArray.h"
#include "include/sksl/DSLCore.h"
#include "include/sksl/DSLExpression.h"
#include "include/sksl/DSLLayout.h"
#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLStatement.h"
#include "include/sksl/DSLType.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "include/sksl/SkSLOperator.h"
#include "include/sksl/SkSLPosition.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLProgramSettings.h"

#include <memory>
#include <optional>
#include <string>
#include <string_view>

namespace SkSL {

struct ParsedModule;
struct Program;

namespace dsl {
class DSLBlock;
class DSLCase;
class DSLGlobalVar;
class DSLParameter;
template <typename T> class DSLWrapper;

}

class AutoDSLDepth;

/**
 * Consumes .sksl text and invokes DSL functions to instantiate the program.
 */
class DSLParser {
public:
    DSLParser(Compiler* compiler, const ProgramSettings& settings, ProgramKind kind,
              std::string text);

    std::unique_ptr<Program> program();

    SkSL::LoadedModule moduleInheritingFrom(SkSL::ParsedModule baseModule);

    std::string_view 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);

    /**
     * Behaves like checkNext(TK_IDENTIFIER), but also verifies that identifier is not a builtin
     * type. If the token was actually a builtin type, false is returned (the next token is not
     * considered to be an identifier).
     */
    bool checkIdentifier(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, std::string expected, Token* result = nullptr);

    /**
     * Behaves like expect(TK_IDENTIFIER), but also verifies that identifier is not a type.
     * If the token was actually a type, generates an error message of the form:
     *
     * "expected an identifier, but found type 'float2'"
     */
    bool expectIdentifier(Token* result);

    void error(Token token, std::string msg);
    void error(Position position, std::string msg);

    // Returns the range from `start` to the current parse position.
    Position rangeFrom(Position start);
    Position rangeFrom(Token start);

    // 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.

    void declarations();

    /**
     * Parses an expression representing an array size. Reports errors if the array size is not
     * valid (out of bounds, not a literal integer). Returns true if an expression was
     * successfully parsed, even if that array size is not actually valid. In the event of a true
     * return, outResult always contains a valid array size (even if the parsed array size was not
     * actually valid; invalid array sizes result in a 1 to avoid additional errors downstream).
     */
    bool arraySize(SKSL_INT* outResult);

    void directive();

    bool declaration();

    bool functionDeclarationEnd(Position start,
                                const dsl::DSLModifiers& modifiers,
                                dsl::DSLType type,
                                const Token& name);

    struct VarDeclarationsPrefix {
        Position fPosition;
        dsl::DSLModifiers fModifiers;
        dsl::DSLType fType = dsl::DSLType(dsl::kVoid_Type);
        Token fName;
    };

    bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData);

    dsl::DSLStatement varDeclarationsOrExpressionStatement();

    dsl::DSLStatement varDeclarations();

    std::optional<dsl::DSLType> structDeclaration();

    SkTArray<dsl::DSLGlobalVar> structVarDeclaration(Position start,
                                                     const dsl::DSLModifiers& modifiers);

    bool parseArrayDimensions(Position pos, dsl::DSLType* type);

    bool parseInitializer(Position pos, dsl::DSLExpression* initializer);

    void globalVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods,
            dsl::DSLType baseType, Token name);

    dsl::DSLStatement localVarDeclarationEnd(Position position, const dsl::DSLModifiers& mods,
            dsl::DSLType baseType, Token name);

    std::optional<dsl::DSLWrapper<dsl::DSLParameter>> parameter(size_t paramIndex);

    int layoutInt();

    std::string_view layoutIdentifier();

    dsl::DSLLayout layout();

    dsl::DSLModifiers modifiers();

    dsl::DSLStatement statement();

    std::optional<dsl::DSLType> type(dsl::DSLModifiers* modifiers);

    bool interfaceBlock(const dsl::DSLModifiers& mods);

    dsl::DSLStatement ifStatement();

    dsl::DSLStatement doStatement();

    dsl::DSLStatement whileStatement();

    dsl::DSLStatement forStatement();

    std::optional<dsl::DSLCase> switchCase();

    dsl::DSLStatement switchStatement();

    dsl::DSLStatement returnStatement();

    dsl::DSLStatement breakStatement();

    dsl::DSLStatement continueStatement();

    dsl::DSLStatement discardStatement();

    std::optional<dsl::DSLBlock> block();

    dsl::DSLStatement expressionStatement();

    using BinaryParseFn = dsl::DSLExpression (DSLParser::*)();
    bool SK_WARN_UNUSED_RESULT operatorRight(AutoDSLDepth& depth, Operator::Kind op,
            BinaryParseFn rightFn, dsl::DSLExpression& result);

    dsl::DSLExpression expression();

    dsl::DSLExpression assignmentExpression();

    dsl::DSLExpression ternaryExpression();

    dsl::DSLExpression logicalOrExpression();

    dsl::DSLExpression logicalXorExpression();

    dsl::DSLExpression logicalAndExpression();

    dsl::DSLExpression bitwiseOrExpression();

    dsl::DSLExpression bitwiseXorExpression();

    dsl::DSLExpression bitwiseAndExpression();

    dsl::DSLExpression equalityExpression();

    dsl::DSLExpression relationalExpression();

    dsl::DSLExpression shiftExpression();

    dsl::DSLExpression additiveExpression();

    dsl::DSLExpression multiplicativeExpression();

    dsl::DSLExpression unaryExpression();

    dsl::DSLExpression postfixExpression();

    dsl::DSLExpression swizzle(Position pos, dsl::DSLExpression base,
            std::string_view swizzleMask, Position maskPos);

    dsl::DSLExpression call(Position pos, dsl::DSLExpression base, ExpressionArray args);

    dsl::DSLExpression suffix(dsl::DSLExpression base);

    dsl::DSLExpression term();

    bool intLiteral(SKSL_INT* dest);

    bool floatLiteral(SKSL_FLOAT* dest);

    bool boolLiteral(bool* dest);

    bool identifier(std::string_view* dest);

    class Checkpoint {
    public:
        Checkpoint(DSLParser* p) : fParser(p) {
            fPushbackCheckpoint = fParser->fPushback;
            fLexerCheckpoint = fParser->fLexer.getCheckpoint();
            fOldErrorReporter = &dsl::GetErrorReporter();
            fOldEncounteredFatalError = fParser->fEncounteredFatalError;
            SkASSERT(fOldErrorReporter);
            dsl::SetErrorReporter(&fErrorReporter);
        }

        ~Checkpoint() {
            SkASSERTF(!fOldErrorReporter,
                      "Checkpoint was not accepted or rewound before destruction");
        }

        void accept() {
            this->restoreErrorReporter();
            // Parser errors should have been fatal, but we can encounter other errors like type
            // mismatches despite accepting the parse. Forward those messages to the actual error
            // handler now.
            fErrorReporter.forwardErrors();
        }

        void rewind() {
            this->restoreErrorReporter();
            fParser->fPushback = fPushbackCheckpoint;
            fParser->fLexer.rewindToCheckpoint(fLexerCheckpoint);
            fParser->fEncounteredFatalError = fOldEncounteredFatalError;
        }

    private:
        class ForwardingErrorReporter : public ErrorReporter {
        public:
            void handleError(std::string_view msg, Position pos) override {
                fErrors.push_back({std::string(msg), pos});
            }

            void forwardErrors() {
                for (Error& error : fErrors) {
                    dsl::GetErrorReporter().error(error.fMsg.c_str(), error.fPos);
                }
            }

        private:
            struct Error {
                std::string fMsg;
                Position fPos;
            };

            SkTArray<Error> fErrors;
        };

        void restoreErrorReporter() {
            SkASSERT(fOldErrorReporter);
            fErrorReporter.reportPendingErrors(Position());
            dsl::SetErrorReporter(fOldErrorReporter);
            fOldErrorReporter = nullptr;
        }

        DSLParser* fParser;
        Token fPushbackCheckpoint;
        SkSL::Lexer::Checkpoint fLexerCheckpoint;
        ForwardingErrorReporter fErrorReporter;
        ErrorReporter* fOldErrorReporter;
        bool fOldEncounteredFatalError;
    };

    Compiler& fCompiler;
    ProgramSettings fSettings;
    ErrorReporter* fErrorReporter;
    bool fEncounteredFatalError;
    ProgramKind fKind;
    std::unique_ptr<std::string> fText;
    Lexer fLexer;
    // 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;

    friend class AutoDSLDepth;
    friend class HCodeGenerator;
};

}  // namespace SkSL

#endif
