/*
* 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_PARSER
#define SKSL_PARSER
#include "include/core/SkTypes.h"
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperator.h"
#include "src/sksl/SkSLPosition.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLLayout.h"
#include "src/sksl/ir/SkSLModifiers.h"
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
namespace SkSL {
class Compiler;
class ErrorReporter;
class Expression;
class FunctionDeclaration;
struct Module;
struct Program;
class ProgramElement;
enum class ProgramKind : int8_t;
class Statement;
class SymbolTable;
class Type;
class VarDeclaration;
class Variable;
/**
* Consumes . sksl text and converts it into an IR tree , encapsulated in a Program .
*/
class Parser {
public:
Parser(Compiler* compiler,
const ProgramSettings& settings,
ProgramKind kind,
std::unique_ptr<std::string> text);
~Parser();
std::unique_ptr<Program> programInheritingFrom(const Module* module);
std::unique_ptr<Module> moduleInheritingFrom(const Module* parentModule);
std::string_view text(Token token);
Position position(Token token);
private :
class AutoDepth;
class AutoSymbolTable;
class Checkpoint;
/**
* 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);
/** If the next token is a newline, consumes it and returns true. If not, returns false. */
bool expectNewline();
void error(Token token, std::string_view msg);
void error(Position position, std::string_view 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 allowVersion);
void extensionDirective(Position start);
void versionDirective(Position start, bool allowVersion);
bool declaration();
bool functionDeclarationEnd(Position start,
Modifiers& modifiers,
const Type* returnType,
const Token& name);
bool prototypeFunction(SkSL::FunctionDeclaration* decl);
bool defineFunction(SkSL::FunctionDeclaration* decl);
struct VarDeclarationsPrefix {
Position fPosition;
Modifiers fModifiers;
const Type* fType;
Token fName;
};
bool varDeclarationsPrefix(VarDeclarationsPrefix* prefixData);
std::unique_ptr<Statement> varDeclarationsOrExpressionStatement();
std::unique_ptr<Statement> varDeclarations();
const Type* structDeclaration();
void structVarDeclaration(Position start, const Modifiers& modifiers);
bool allowUnsizedArrays() {
return ProgramConfig::IsCompute(fKind) || ProgramConfig::IsFragment(fKind) ||
ProgramConfig::IsVertex(fKind);
}
const Type* arrayType(const Type* base, int count, Position pos);
const Type* unsizedArrayType(const Type* base, Position pos);
bool parseArrayDimensions(Position pos, const Type** type);
bool parseInitializer(Position pos, std::unique_ptr<Expression>* initializer);
void addGlobalVarDeclaration(std::unique_ptr<SkSL::VarDeclaration> decl);
void globalVarDeclarationEnd(Position position, const Modifiers& mods,
const Type* baseType, Token name);
std::unique_ptr<Statement> localVarDeclarationEnd(Position position,
const Modifiers& mods,
const Type* baseType,
Token name);
bool modifiersDeclarationEnd(const Modifiers& mods);
bool parameter(std::unique_ptr<SkSL::Variable>* outParam);
int layoutInt();
std::string_view layoutIdentifier();
SkSL::Layout layout();
Modifiers modifiers();
std::unique_ptr<Statement> statementOrNop(Position pos, std::unique_ptr<Statement> stmt);
std::unique_ptr<Statement> statement(bool bracesIntroduceNewScope = true);
const Type* findType(Position pos, Modifiers* modifiers, std::string_view name);
const Type* type(Modifiers* modifiers);
bool interfaceBlock(const Modifiers& mods);
std::unique_ptr<Statement> ifStatement();
std::unique_ptr<Statement> doStatement();
std::unique_ptr<Statement> whileStatement();
std::unique_ptr<Statement> forStatement();
bool switchCaseBody(ExpressionArray* values,
StatementArray* caseBlocks,
std::unique_ptr<Expression> value);
bool switchCase(ExpressionArray* values, StatementArray* caseBlocks);
std::unique_ptr<Statement> switchStatement();
std::unique_ptr<Statement> returnStatement();
std::unique_ptr<Statement> breakStatement();
std::unique_ptr<Statement> continueStatement();
std::unique_ptr<Statement> discardStatement();
std::unique_ptr<Statement> block(bool introduceNewScope,
std::unique_ptr<SymbolTable>* adoptExistingSymbolTable);
std::unique_ptr<Statement> expressionStatement();
using BinaryParseFn = std::unique_ptr<Expression> (Parser::*)();
[[nodiscard]] bool operatorRight(AutoDepth& depth,
Operator ::Kind op,
BinaryParseFn rightFn,
std::unique_ptr<Expression>& expr);
std::unique_ptr<Expression> poison(Position pos);
std::unique_ptr<Expression> expressionOrPoison(Position pos, std::unique_ptr<Expression> expr);
std::unique_ptr<Expression> expression();
std::unique_ptr<Expression> assignmentExpression();
std::unique_ptr<Expression> ternaryExpression();
std::unique_ptr<Expression> logicalOrExpression();
std::unique_ptr<Expression> logicalXorExpression();
std::unique_ptr<Expression> logicalAndExpression();
std::unique_ptr<Expression> bitwiseOrExpression();
std::unique_ptr<Expression> bitwiseXorExpression();
std::unique_ptr<Expression> bitwiseAndExpression();
std::unique_ptr<Expression> equalityExpression();
std::unique_ptr<Expression> relationalExpression();
std::unique_ptr<Expression> shiftExpression();
std::unique_ptr<Expression> additiveExpression();
std::unique_ptr<Expression> multiplicativeExpression();
std::unique_ptr<Expression> unaryExpression();
std::unique_ptr<Expression> postfixExpression();
std::unique_ptr<Expression> swizzle(Position pos,
std::unique_ptr<Expression> base,
std::string_view swizzleMask,
Position maskPos);
std::unique_ptr<Expression> call(Position pos,
std::unique_ptr<Expression> base,
ExpressionArray args);
std::unique_ptr<Expression> suffix(std::unique_ptr<Expression> base);
std::unique_ptr<Expression> term();
bool intLiteral(SKSL_INT* dest);
bool floatLiteral(SKSL_FLOAT* dest);
bool boolLiteral(bool * dest);
bool identifier(std::string_view* dest);
SymbolTable* symbolTable();
Compiler& fCompiler;
ProgramSettings fSettings;
ErrorReporter* fErrorReporter;
bool fEncounteredFatalError;
ProgramKind fKind;
std::unique_ptr<std::string> fText;
std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
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;
};
} // namespace SkSL
#endif
Messung V0.5 in Prozent C=87 H=86 G=86
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland