66#include <initializer_list>
108 fParser->fDepth -= fDepth;
115 fParser->error(fParser->peek(),
"exceeded max parse depth");
116 fParser->fEncounteredFatalError =
true;
132 SymbolTable*& ctxSymbols = this->contextSymbolTable();
133 *newSymbolTable = std::make_unique<SymbolTable>(ctxSymbols, ctxSymbols->
isBuiltin());
134 ctxSymbols = newSymbolTable->get();
140 SymbolTable*& ctxSymbols = this->contextSymbolTable();
141 ctxSymbols = ctxSymbols->
fParent;
148 Parser* fParser =
nullptr;
155 fPushbackCheckpoint = fParser->fPushback;
157 fOldErrorReporter = context.
fErrors;
158 fOldEncounteredFatalError = fParser->fEncounteredFatalError;
164 SkASSERTF(!fOldErrorReporter,
"Checkpoint was not accepted or rewound before destruction");
168 this->restoreErrorReporter();
172 fErrorReporter.forwardErrors(fParser);
176 this->restoreErrorReporter();
177 fParser->fPushback = fPushbackCheckpoint;
179 fParser->fEncounteredFatalError = fOldEncounteredFatalError;
185 void handleError(std::string_view msg,
Position pos)
override {
186 fErrors.push_back({std::string(msg),
pos});
190 for (
const Error& error : fErrors) {
191 parser->error(error.fPos, error.fMsg);
204 void restoreErrorReporter() {
207 fOldErrorReporter =
nullptr;
211 Token fPushbackCheckpoint;
213 ForwardingErrorReporter fErrorReporter;
214 ErrorReporter* fOldErrorReporter;
215 bool fOldEncounteredFatalError;
221 std::unique_ptr<std::string>
text)
226 , fPushback(
Token::
Kind::TK_NONE, -1, -1) {
227 fLexer.
start(*fText);
236Token Parser::nextRawToken() {
244 token = fLexer.
next();
247 switch (token.fKind) {
256 this->error(token,
"name '" + std::string(this->
text(token)) +
"' is reserved");
261 this->error(token,
"'" + std::string(this->
text(token)) +
262 "' is not a valid octal number");
285bool Parser::expectNewline() {
286 Token token = this->nextRawToken();
290 std::string_view tokenText = this->
text(token);
291 if (tokenText.find_first_of(
'\r') != std::string_view::npos ||
292 tokenText.find_first_of(
'\n') != std::string_view::npos) {
297 this->pushback(token);
301Token Parser::nextToken() {
303 Token token = this->nextRawToken();
310void Parser::pushback(Token t) {
315Token Parser::peek() {
317 fPushback = this->nextToken();
326 Token
next = this->nextToken();
327 if (
next.fKind == kind) {
333 this->pushback(
next);
338 Token
next = this->nextToken();
339 if (
next.fKind == kind) {
345 this->error(
next,
"expected " + std::string(expected) +
", but found '" +
346 std::string(this->
text(next)) +
"'");
347 this->fEncounteredFatalError =
true;
352bool Parser::expectIdentifier(Token*
result) {
356 if (this->symbolTable()->isBuiltinType(this->
text(*result))) {
357 this->error(*
result,
"expected an identifier, but found type '" +
358 std::string(this->
text(*result)) +
"'");
359 this->fEncounteredFatalError =
true;
365bool Parser::checkIdentifier(Token*
result) {
369 if (this->symbolTable()->isBuiltinType(this->
text(*result))) {
377 return std::string_view(fText->data() + token.
fOffset, token.
fLength);
388void Parser::error(
Token token, std::string_view msg) {
389 this->error(this->
position(token), msg);
392void Parser::error(Position position, std::string_view msg) {
396Position Parser::rangeFrom(Position start) {
402Position Parser::rangeFrom(Token start) {
403 return this->rangeFrom(this->
position(start));
408 this->declarations();
409 std::unique_ptr<Program>
result;
411 result = fCompiler.releaseProgram(std::move(fText), std::move(fProgramElements));
413 fProgramElements.clear();
419 this->declarations();
421 auto result = std::make_unique<SkSL::Module>();
422 result->fParent = parentModule;
423 result->fSymbols = std::move(fCompiler.fGlobalSymbols);
424 result->fElements = std::move(fProgramElements);
428void Parser::declarations() {
429 fEncounteredFatalError =
false;
434 this->error(
Position(),
"program is too large");
440 this->directive(
true);
443 while (!fEncounteredFatalError) {
447 switch (this->peek().fKind) {
452 this->error(this->peek(),
"invalid token");
456 this->directive(
false);
467void Parser::extensionDirective(Position start) {
469 if (!this->expectIdentifier(&
name)) {
480 if (this->expectNewline()) {
482 this->rangeFrom(start),
484 this->text(behavior));
486 fProgramElements.push_back(std::move(
ext));
489 this->error(start,
"invalid #extension directive");
494void Parser::versionDirective(Position start,
bool allowVersion) {
496 this->error(start,
"#version directive must appear before anything else");
500 if (!this->intLiteral(&
version)) {
511 this->error(start,
"unsupported version number");
515 if (!this->expectNewline()) {
516 this->error(start,
"invalid #version directive");
522void Parser::directive(
bool allowVersion) {
527 std::string_view
text = this->
text(start);
528 if (
text ==
"#extension") {
529 return this->extensionDirective(this->
position(start));
531 if (
text ==
"#version") {
532 return this->versionDirective(this->
position(start), allowVersion);
534 this->error(start,
"unsupported directive '" + std::string(this->
text(start)) +
"'");
543 fProgramElements.push_back(std::move(decl));
549bool Parser::declaration() {
550 Token
start = this->peek();
553 this->error(start,
"expected a declaration, but found ';'");
556 Modifiers modifiers = this->modifiers();
557 Token lookahead = this->peek();
559 !this->symbolTable()->isType(this->text(lookahead))) {
561 return this->interfaceBlock(modifiers);
565 return this->modifiersDeclarationEnd(modifiers);
568 this->structVarDeclaration(this->
position(start), modifiers);
571 const Type* type = this->type(&modifiers);
576 if (!this->expectIdentifier(&
name)) {
580 return this->functionDeclarationEnd(this->
position(start), modifiers, type,
name);
582 this->globalVarDeclarationEnd(this->
position(start), modifiers, type,
name);
588bool Parser::functionDeclarationEnd(Position start,
589 Modifiers& modifiers,
590 const Type* returnType,
592 Token lookahead = this->peek();
593 bool validParams =
true;
602 std::unique_ptr<SkSL::Variable> param;
603 if (!this->parameter(¶m)) {
606 validParams = validParams && param;
620 this->rangeFrom(start),
623 std::move(parameters),
629 return this->prototypeFunction(decl);
631 return this->defineFunction(decl);
639 fProgramElements.push_back(std::make_unique<SkSL::FunctionPrototype>(
645 const Context& context = fCompiler.
context();
646 Token bodyStart = this->peek();
648 std::unique_ptr<SymbolTable> symbolTable;
649 std::unique_ptr<Statement> body;
652 AutoSymbolTable
symbols(
this, &symbolTable);
655 symbolTable->addWithoutOwnership(fCompiler.
context(), param);
660 body = this->block(
false, &symbolTable);
664 if (!decl || !body) {
668 std::unique_ptr<SkSL::Statement> block = std::move(body);
670 Position
pos = this->rangeFrom(bodyStart);
671 block->fPosition =
pos;
682 fProgramElements.push_back(std::move(
function));
686bool Parser::arraySize(
SKSL_INT* outResult) {
689 Token
next = this->peek();
691 this->error(this->
position(next),
"unsized arrays are not permitted here");
694 std::unique_ptr<Expression> sizeLiteral = this->expression();
698 if (!sizeLiteral->is<Poison>()) {
701 this->error(sizeLiteral->fPosition,
"array size must be an integer");
704 if (
size > INT32_MAX) {
705 this->error(sizeLiteral->fPosition,
"array size out of bounds");
709 this->error(sizeLiteral->fPosition,
"array size must be positive");
719 const Context& context = fCompiler.
context();
722 return context.fTypes.fPoison.get();
724 return this->symbolTable()->addArrayDimension(fCompiler.
context(),
base,
count);
728 const Context& context = fCompiler.
context();
729 if (!
base->checkIfUsableInArray(context,
pos)) {
732 return this->symbolTable()->addArrayDimension(fCompiler.
context(),
base,
736bool Parser::parseArrayDimensions(Position
pos,
const Type**
type) {
740 if (this->allowUnsizedArrays()) {
741 *
type = this->unsizedArrayType(*type, this->rangeFrom(
pos));
743 this->error(this->rangeFrom(
pos),
"unsized arrays are not permitted here");
747 if (!this->arraySize(&
size)) {
753 *
type = this->arrayType(*type,
size, this->rangeFrom(
pos));
759bool Parser::parseInitializer(Position
pos, std::unique_ptr<Expression>*
initializer) {
767void Parser::addGlobalVarDeclaration(std::unique_ptr<VarDeclaration> decl) {
769 fProgramElements.push_back(std::make_unique<SkSL::GlobalVarDeclaration>(std::move(decl)));
775void Parser::globalVarDeclarationEnd(Position
pos,
776 const Modifiers& mods,
777 const Type* baseType,
781 if (!this->parseArrayDimensions(
pos, &type)) {
788 this->rangeFrom(
pos),
791 this->position(
name),
797 Token identifierName;
798 if (!this->expectIdentifier(&identifierName)) {
801 if (!this->parseArrayDimensions(
pos, &type)) {
804 std::unique_ptr<Expression> anotherInitializer;
805 if (!this->parseInitializer(
pos, &anotherInitializer)) {
809 this->rangeFrom(identifierName),
812 this->position(identifierName),
813 this->text(identifierName),
815 std::move(anotherInitializer)));
822std::unique_ptr<Statement> Parser::localVarDeclarationEnd(Position
pos,
823 const Modifiers& mods,
824 const Type* baseType,
828 if (!this->parseArrayDimensions(
pos, &type)) {
835 this->rangeFrom(
pos),
838 this->position(
name),
848 Token identifierName;
849 if (!this->expectIdentifier(&identifierName)) {
852 if (!this->parseArrayDimensions(
pos, &type)) {
855 std::unique_ptr<Expression> anotherInitializer;
856 if (!this->parseInitializer(
pos, &anotherInitializer)) {
860 this->rangeFrom(identifierName),
863 this->position(identifierName),
864 this->text(identifierName),
866 std::move(anotherInitializer));
870 pos = this->rangeFrom(
pos);
871 return this->statementOrNop(
pos, std::move(
result));
875std::unique_ptr<Statement> Parser::varDeclarationsOrExpressionStatement() {
876 Token nextToken = this->peek();
880 return this->varDeclarations();
886 this->symbolTable()->isType(this->text(nextToken))) {
890 Checkpoint checkpoint(
this);
891 VarDeclarationsPrefix
prefix;
892 if (this->varDeclarationsPrefix(&
prefix)) {
894 return this->localVarDeclarationEnd(
prefix.fPosition,
prefix.fModifiers,
prefix.fType,
902 return this->expressionStatement();
907bool Parser::varDeclarationsPrefix(VarDeclarationsPrefix* prefixData) {
908 prefixData->fPosition = this->
position(this->peek());
909 prefixData->fModifiers = this->modifiers();
910 prefixData->fType = this->type(&prefixData->fModifiers);
911 if (!prefixData->fType) {
914 return this->expectIdentifier(&prefixData->fName);
918std::unique_ptr<Statement> Parser::varDeclarations() {
919 VarDeclarationsPrefix
prefix;
920 if (!this->varDeclarationsPrefix(&
prefix)) {
923 return this->localVarDeclarationEnd(
prefix.fPosition,
prefix.fModifiers,
prefix.fType,
928const Type* Parser::structDeclaration() {
929 AutoDepth depth(
this);
935 if (!this->expectIdentifier(&
name)) {
941 if (!depth.increase()) {
946 Token fieldStart = this->peek();
947 Modifiers modifiers = this->modifiers();
948 const Type*
type = this->type(&modifiers);
956 if (!this->expectIdentifier(&memberName)) {
962 if (!this->arraySize(&
size)) {
968 actualType = this->arrayType(actualType,
size,
969 this->rangeFrom(this->
position(fieldStart)));
975 this->text(memberName),
984 this->rangeFrom(start),
992 fProgramElements.push_back(std::move(def));
997void Parser::structVarDeclaration(Position start,
const Modifiers& modifiers) {
998 const Type*
type = this->structDeclaration();
1003 if (this->checkIdentifier(&
name)) {
1004 this->globalVarDeclarationEnd(this->rangeFrom(
name), modifiers, type,
name);
1011bool Parser::parameter(std::unique_ptr<SkSL::Variable>* outParam) {
1013 Modifiers modifiers = this->modifiers();
1014 const Type*
type = this->type(&modifiers);
1019 std::string_view nameText;
1021 if (this->checkIdentifier(&
name)) {
1022 nameText = this->
text(name);
1025 namePos = this->rangeFrom(
pos);
1027 if (!this->parseArrayDimensions(
pos, &type)) {
1031 this->rangeFrom(
pos),
1032 modifiers.fPosition,
1043int Parser::layoutInt() {
1051 std::string_view resultFrag = this->
text(resultToken);
1054 this->error(resultToken,
"value in layout is too large: " + std::string(resultFrag));
1061std::string_view Parser::layoutIdentifier() {
1066 if (!this->expectIdentifier(&resultToken)) {
1069 return this->
text(resultToken);
1106 Token t = this->nextToken();
1107 std::string_view
text = this->
text(t);
1111 this->error(t,
"'" + std::string(
text) +
"' is not a valid layout qualifier");
1113 if (
result.fFlags & *found) {
1114 this->error(t,
"layout qualifier '" + std::string(
text) +
1115 "' appears more than once");
1122 result.fLocation = this->layoutInt();
1125 result.fOffset = this->layoutInt();
1128 result.fBinding = this->layoutInt();
1131 result.fIndex = this->layoutInt();
1134 result.fSet = this->layoutInt();
1137 result.fTexture = this->layoutInt();
1140 result.fSampler = this->layoutInt();
1143 result.fBuiltin = this->layoutInt();
1146 result.fInputAttachmentIndex = this->layoutInt();
1149 result.fLocalSizeX = this->layoutInt();
1152 result.fLocalSizeY = this->layoutInt();
1155 result.fLocalSizeZ = this->layoutInt();
1174Modifiers Parser::modifiers() {
1177 Token raw = this->nextRawToken();
1178 int end = raw.fOffset;
1180 this->pushback(raw);
1188 Token modifier = this->nextToken();
1189 if (ModifierFlags duplicateFlags = (tokenFlag &
flags)) {
1190 this->error(modifier,
"'" + duplicateFlags.description() +
"' appears more than once");
1198std::unique_ptr<Statement> Parser::statementOrNop(Position
pos, std::unique_ptr<Statement> stmt) {
1202 if (
pos.valid() && !stmt->position().valid()) {
1203 stmt->setPosition(
pos);
1209std::unique_ptr<Statement> Parser::statement(
bool bracesIntroduceNewScope) {
1210 AutoDepth depth(
this);
1211 if (!depth.increase()) {
1214 switch (this->peek().fKind) {
1216 return this->ifStatement();
1218 return this->forStatement();
1220 return this->doStatement();
1222 return this->whileStatement();
1224 return this->switchStatement();
1226 return this->returnStatement();
1228 return this->breakStatement();
1230 return this->continueStatement();
1232 return this->discardStatement();
1234 return this->block(bracesIntroduceNewScope,
nullptr);
1239 return this->varDeclarations();
1244 return this->varDeclarationsOrExpressionStatement();
1246 return this->expressionStatement();
1250const Type* Parser::findType(Position
pos,
1251 Modifiers* modifiers,
1252 std::string_view
name) {
1253 const Context& context = fCompiler.
context();
1254 const Symbol* symbol = this->symbolTable()->find(
name);
1256 this->error(
pos,
"no symbol named '" + std::string(
name) +
"'");
1257 return context.fTypes.fPoison.get();
1259 if (!symbol->is<
Type>()) {
1260 this->error(
pos,
"symbol '" + std::string(
name) +
"' is not a type");
1261 return context.fTypes.fPoison.get();
1264 if (!context.fConfig->fIsBuiltinCode) {
1266 return context.fTypes.fPoison.get();
1269 Position qualifierRange = modifiers->fPosition;
1270 if (qualifierRange.startOffset() == qualifierRange.endOffset()) {
1271 qualifierRange = this->rangeFrom(qualifierRange);
1273 return modifiers ?
type->applyQualifiers(context, &modifiers->fFlags, qualifierRange)
1278const Type* Parser::type(Modifiers* modifiers) {
1283 if (!this->symbolTable()->isType(this->
text(type))) {
1284 this->error(type,
"no type named '" + std::string(this->
text(type)) +
"'");
1288 if (
result->isInterfaceBlock()) {
1291 this->error(type,
"expected a type, found '" + std::string(this->
text(type)) +
"'");
1297 if (this->allowUnsizedArrays()) {
1298 result = this->unsizedArrayType(
result, this->rangeFrom(type));
1300 this->error(this->rangeFrom(bracket),
"unsized arrays are not permitted here");
1304 if (!this->arraySize(&
size)) {
1317bool Parser::interfaceBlock(
const Modifiers& modifiers) {
1319 if (!this->expectIdentifier(&typeName)) {
1326 this->error(typeName,
"no type named '" + std::string(this->
text(typeName)) +
"'");
1332 Position fieldPos = this->
position(this->peek());
1333 Modifiers fieldModifiers = this->modifiers();
1334 const Type*
type = this->type(&fieldModifiers);
1340 if (!this->expectIdentifier(&fieldName)) {
1345 Token sizeToken = this->peek();
1348 if (!this->arraySize(&
size)) {
1351 actualType = this->arrayType(actualType,
size, this->
position(typeName));
1352 }
else if (this->allowUnsizedArrays()) {
1353 actualType = this->unsizedArrayType(actualType, this->
position(typeName));
1355 this->error(sizeToken,
"unsized arrays are not permitted here");
1364 fieldModifiers.fLayout,
1365 fieldModifiers.fFlags,
1366 this->text(fieldName),
1370 std::string_view instanceName;
1371 Token instanceNameToken;
1373 if (this->checkIdentifier(&instanceNameToken)) {
1374 instanceName = this->
text(instanceNameToken);
1376 if (!this->arraySize(&
size)) {
1385 this->position(typeName),
1387 this->text(typeName),
1391 fProgramElements.push_back(std::move(ib));
1398std::unique_ptr<Statement> Parser::ifStatement() {
1406 std::unique_ptr<Expression>
test = this->expression();
1413 std::unique_ptr<Statement> ifTrue = this->statement();
1417 std::unique_ptr<Statement> ifFalse;
1419 ifFalse = this->statement();
1424 Position
pos = this->rangeFrom(start);
1429 std::move(ifFalse)));
1433std::unique_ptr<Statement> Parser::doStatement() {
1438 std::unique_ptr<Statement> statement = this->statement();
1448 std::unique_ptr<Expression>
test = this->expression();
1458 Position
pos = this->rangeFrom(start);
1460 std::move(statement), std::move(
test)));
1464std::unique_ptr<Statement> Parser::whileStatement() {
1472 std::unique_ptr<Expression>
test = this->expression();
1479 std::unique_ptr<Statement> statement = this->statement();
1483 Position
pos = this->rangeFrom(start);
1486 std::move(statement)));
1490bool Parser::switchCaseBody(ExpressionArray*
values,
1492 std::unique_ptr<Expression> caseValue) {
1500 std::unique_ptr<Statement>
s = this->statement();
1504 statements.push_back(std::move(
s));
1506 values->push_back(std::move(caseValue));
1508 Block::Kind::kUnbracedBlock));
1518 std::unique_ptr<Expression> caseValue = this->expression();
1522 return this->switchCaseBody(
values, caseBlocks, std::move(caseValue));
1526std::unique_ptr<Statement> Parser::switchStatement() {
1534 std::unique_ptr<Expression>
value = this->expression();
1545 std::unique_ptr<SymbolTable> symbolTable;
1553 AutoSymbolTable
symbols(
this, &symbolTable);
1556 if (!this->switchCase(&
values, &caseBlocks)) {
1563 if (!this->switchCaseBody(&
values, &caseBlocks,
nullptr)) {
1572 Position
pos = this->rangeFrom(start);
1576 std::move(caseBlocks),
1577 std::move(symbolTable)));
1586std::unique_ptr<Statement> Parser::forStatement() {
1595 std::unique_ptr<SymbolTable> symbolTable;
1597 std::unique_ptr<Expression>
test;
1598 std::unique_ptr<Expression>
next;
1599 std::unique_ptr<Statement> statement;
1600 int firstSemicolonOffset;
1601 Token secondSemicolon;
1604 AutoSymbolTable
symbols(
this, &symbolTable);
1606 Token nextToken = this->peek();
1609 firstSemicolonOffset = this->nextToken().fOffset;
1612 initializer = this->varDeclarationsOrExpressionStatement();
1619 test = this->expression();
1628 next = this->expression();
1636 statement = this->statement(
false);
1641 Position
pos = this->rangeFrom(start);
1642 ForLoopPositions loopPositions{
1651 std::move(statement),
1652 std::move(symbolTable)));
1656std::unique_ptr<Statement> Parser::returnStatement() {
1661 std::unique_ptr<Expression> expression;
1663 expression = this->expression();
1677std::unique_ptr<Statement> Parser::breakStatement() {
1689std::unique_ptr<Statement> Parser::continueStatement() {
1701std::unique_ptr<Statement> Parser::discardStatement() {
1714std::unique_ptr<Statement> Parser::block(
bool introduceNewScope,
1715 std::unique_ptr<SymbolTable>* adoptExistingSymbolTable) {
1717 SkASSERT(!(introduceNewScope && adoptExistingSymbolTable));
1719 AutoDepth depth(
this);
1724 if (!depth.increase()) {
1728 std::unique_ptr<SymbolTable> newSymbolTable;
1729 std::unique_ptr<SymbolTable>* symbolTableToUse =
1730 adoptExistingSymbolTable ? adoptExistingSymbolTable : &newSymbolTable;
1734 AutoSymbolTable
symbols(
this, symbolTableToUse, introduceNewScope);
1744 this->error(this->peek(),
"expected '}', but found end of file");
1747 if (std::unique_ptr<Statement> statement = this->statement()) {
1748 statements.push_back(std::move(statement));
1750 if (fEncounteredFatalError) {
1756 std::move(statements),
1757 Block::Kind::kBracedScope,
1758 std::move(*symbolTableToUse));
1762std::unique_ptr<Statement> Parser::expressionStatement() {
1763 std::unique_ptr<Expression> expr = this->expression();
1770 Position
pos = expr->position();
1775std::unique_ptr<Expression> Parser::poison(Position
pos) {
1779std::unique_ptr<Expression> Parser::expressionOrPoison(Position
pos,
1780 std::unique_ptr<Expression> expr) {
1783 expr = this->poison(
pos);
1787 "expected expression position (%d-%d), but received (%d-%d)",
1790 expr->position().startOffset(),
1791 expr->position().endOffset());
1795bool Parser::operatorRight(Parser::AutoDepth& depth,
1797 BinaryParseFn rightFn,
1798 std::unique_ptr<Expression>& expr) {
1800 if (!depth.increase()) {
1803 std::unique_ptr<Expression>
right = (this->*rightFn)();
1807 Position
pos = expr->position().rangeThrough(
right->position());
1809 std::move(expr), op,
1815std::unique_ptr<Expression> Parser::expression() {
1816 AutoDepth depth(
this);
1817 [[maybe_unused]] Token
start = this->peek();
1818 std::unique_ptr<Expression>
result = this->assignmentExpression();
1828 SkASSERTF(
result->position().valid(),
"Expression %s has invalid position",
1829 result->description().c_str());
1830 SkASSERTF(
result->position().startOffset() == this->position(start).startOffset(),
1831 "Expected %s to start at %d (first token: '%.*s'), but it has range %d-%d\n",
1832 result->description().c_str(), this->position(start).startOffset(),
1833 (
int)this->text(start).length(), this->text(start).data(),
1834 result->position().startOffset(),
result->position().endOffset());
1842std::unique_ptr<Expression> Parser::assignmentExpression() {
1843 AutoDepth depth(
this);
1844 std::unique_ptr<Expression>
result = this->ternaryExpression();
1850 switch (this->peek().fKind) {
1864 if (!this->operatorRight(depth, op, &Parser::assignmentExpression,
result)) {
1871std::unique_ptr<Expression> Parser::ternaryExpression() {
1872 AutoDepth depth(
this);
1873 std::unique_ptr<Expression>
base = this->logicalOrExpression();
1880 if (!depth.increase()) {
1883 std::unique_ptr<Expression> trueExpr = this->expression();
1890 std::unique_ptr<Expression> falseExpr = this->assignmentExpression();
1894 Position
pos =
base->position().rangeThrough(falseExpr->position());
1897 std::move(trueExpr),
1898 std::move(falseExpr)));
1902std::unique_ptr<Expression> Parser::logicalOrExpression() {
1903 AutoDepth depth(
this);
1904 std::unique_ptr<Expression>
result = this->logicalXorExpression();
1909 if (!this->operatorRight(depth, Operator::Kind::LOGICALOR, &Parser::logicalXorExpression,
1918std::unique_ptr<Expression> Parser::logicalXorExpression() {
1919 AutoDepth depth(
this);
1920 std::unique_ptr<Expression>
result = this->logicalAndExpression();
1925 if (!this->operatorRight(depth, Operator::Kind::LOGICALXOR, &Parser::logicalAndExpression,
1934std::unique_ptr<Expression> Parser::logicalAndExpression() {
1935 AutoDepth depth(
this);
1936 std::unique_ptr<Expression>
result = this->bitwiseOrExpression();
1941 if (!this->operatorRight(depth, Operator::Kind::LOGICALAND, &Parser::bitwiseOrExpression,
1950std::unique_ptr<Expression> Parser::bitwiseOrExpression() {
1951 AutoDepth depth(
this);
1952 std::unique_ptr<Expression>
result = this->bitwiseXorExpression();
1957 if (!this->operatorRight(depth, Operator::Kind::BITWISEOR, &Parser::bitwiseXorExpression,
1966std::unique_ptr<Expression> Parser::bitwiseXorExpression() {
1967 AutoDepth depth(
this);
1968 std::unique_ptr<Expression>
result = this->bitwiseAndExpression();
1973 if (!this->operatorRight(depth, Operator::Kind::BITWISEXOR, &Parser::bitwiseAndExpression,
1982std::unique_ptr<Expression> Parser::bitwiseAndExpression() {
1983 AutoDepth depth(
this);
1984 std::unique_ptr<Expression>
result = this->equalityExpression();
1989 if (!this->operatorRight(depth, Operator::Kind::BITWISEAND, &Parser::equalityExpression,
1998std::unique_ptr<Expression> Parser::equalityExpression() {
1999 AutoDepth depth(
this);
2000 std::unique_ptr<Expression>
result = this->relationalExpression();
2006 switch (this->peek().fKind) {
2011 if (!this->operatorRight(depth, op, &Parser::relationalExpression,
result)) {
2018std::unique_ptr<Expression> Parser::relationalExpression() {
2019 AutoDepth depth(
this);
2020 std::unique_ptr<Expression>
result = this->shiftExpression();
2026 switch (this->peek().fKind) {
2033 if (!this->operatorRight(depth, op, &Parser::shiftExpression,
result)) {
2040std::unique_ptr<Expression> Parser::shiftExpression() {
2041 AutoDepth depth(
this);
2042 std::unique_ptr<Expression>
result = this->additiveExpression();
2048 switch (this->peek().fKind) {
2053 if (!this->operatorRight(depth, op, &Parser::additiveExpression,
result)) {
2060std::unique_ptr<Expression> Parser::additiveExpression() {
2061 AutoDepth depth(
this);
2062 std::unique_ptr<Expression>
result = this->multiplicativeExpression();
2068 switch (this->peek().fKind) {
2073 if (!this->operatorRight(depth, op, &Parser::multiplicativeExpression,
result)) {
2080std::unique_ptr<Expression> Parser::multiplicativeExpression() {
2081 AutoDepth depth(
this);
2082 std::unique_ptr<Expression>
result = this->unaryExpression();
2088 switch (this->peek().fKind) {
2094 if (!this->operatorRight(depth, op, &Parser::unaryExpression,
result)) {
2101std::unique_ptr<Expression> Parser::unaryExpression() {
2102 AutoDepth depth(
this);
2104 Token
start = this->peek();
2105 switch (
start.fKind) {
2112 default:
return this->postfixExpression();
2115 if (!depth.increase()) {
2118 std::unique_ptr<Expression> expr = this->unaryExpression();
2124 pos, op, std::move(expr)));
2128std::unique_ptr<Expression> Parser::postfixExpression() {
2129 AutoDepth depth(
this);
2130 std::unique_ptr<Expression>
result = this->term();
2135 Token t = this->peek();
2138 if (this->
text(t)[0] !=
'.') {
2147 if (!depth.increase()) {
2162std::unique_ptr<Expression> Parser::swizzle(Position
pos,
2163 std::unique_ptr<Expression>
base,
2164 std::string_view swizzleMask,
2167 if (!
base->type().isVector() && !
base->type().isScalar()) {
2169 std::move(
base), swizzleMask));
2173 std::move(
base), swizzleMask));
2176std::unique_ptr<Expression> Parser::call(Position
pos,
2177 std::unique_ptr<Expression>
base,
2178 ExpressionArray
args) {
2186std::unique_ptr<Expression> Parser::suffix(std::unique_ptr<Expression>
base) {
2187 AutoDepth depth(
this);
2188 Token
next = this->nextToken();
2189 if (!depth.increase()) {
2192 switch (
next.fKind) {
2195 this->error(this->rangeFrom(
next),
"missing index in '[]'");
2196 return this->poison(this->rangeFrom(
base->position()));
2198 std::unique_ptr<Expression> index = this->expression();
2204 Position
pos = this->rangeFrom(
base->position());
2210 std::string_view
text;
2211 if (this->identifier(&
text)) {
2212 Position
pos = this->rangeFrom(
base->position());
2214 this->rangeFrom(this->
position(next).after()));
2221 std::string_view field = this->
text(next);
2223 field.remove_prefix(1);
2226 Position
pos = this->rangeFrom(
base->position());
2230 Position maskPos = this->rangeFrom(start);
2231 Token
id = this->nextRawToken();
2233 pos = this->rangeFrom(
base->position());
2234 maskPos = this->rangeFrom(start);
2235 return this->swizzle(
pos,
2237 std::string(field) + std::string(this->
text(
id)),
2240 if (field.empty()) {
2241 this->error(
pos,
"expected field name or swizzle mask after '.'");
2242 return this->poison(
pos);
2245 return this->swizzle(
pos, std::move(
base), field, maskPos);
2248 ExpressionArray
args;
2251 std::unique_ptr<Expression> expr = this->assignmentExpression();
2255 args.push_back(std::move(expr));
2262 Position
pos = this->rangeFrom(
base->position());
2263 return this->call(
pos, std::move(
base), std::move(
args));
2268 ? Operator::Kind::PLUSPLUS
2269 : Operator::Kind::MINUSMINUS;
2270 Position
pos = this->rangeFrom(
base->position());
2276 this->error(
next,
"expected expression suffix, but found '" +
2277 std::string(this->
text(next)) +
"'");
2284std::unique_ptr<Expression> Parser::term() {
2285 AutoDepth depth(
this);
2286 Token t = this->peek();
2289 std::string_view
text;
2290 if (this->identifier(&
text)) {
2292 return this->expressionOrPoison(
2294 this->symbolTable()->instantiateSymbolRef(fCompiler.
context(),
text,
pos));
2300 if (!this->intLiteral(&
i)) {
2309 if (!this->floatLiteral(&
f)) {
2326 if (!depth.increase()) {
2329 std::unique_ptr<Expression>
result = this->expression();
2339 this->error(t,
"expected expression, but found '" + std::string(this->
text(t)) +
"'");
2340 fEncounteredFatalError =
true;
2352 std::string_view
s = this->
text(t);
2354 this->error(t,
"integer is too large: " + std::string(
s));
2366 std::string_view
s = this->
text(t);
2368 this->error(t,
"floating-point value is too large: " + std::string(
s));
2375bool Parser::boolLiteral(
bool*
dest) {
2376 Token t = this->nextToken();
2385 this->error(t,
"expected 'true' or 'false', but found '" +
2386 std::string(this->
text(t)) +
"'");
2392bool Parser::identifier(std::string_view*
dest) {
static struct Initializer initializer
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static float next(float f)
#define SkASSERTF(cond, fmt,...)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, std::unique_ptr< Expression > left, Operator op, std::unique_ptr< Expression > right)
static std::unique_ptr< Statement > MakeCompoundStatement(std::unique_ptr< Statement > existing, std::unique_ptr< Statement > additional)
static std::unique_ptr< Statement > Make(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
static std::unique_ptr< Block > MakeBlock(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
static std::unique_ptr< Statement > Make(Position pos)
const std::unique_ptr< Type > fInvalid
const std::unique_ptr< Type > fPoison
Context & context() const
SymbolTable * symbolTable()
ErrorReporter & errorReporter()
SymbolTable * globalSymbols()
static bool GetConstantInt(const Expression &value, SKSL_INT *out)
const BuiltinTypes & fTypes
void setErrorReporter(ErrorReporter *e)
SymbolTable * fSymbolTable
static std::unique_ptr< Statement > Make(Position pos)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, std::unique_ptr< Statement > stmt, std::unique_ptr< Expression > test)
void error(Position position, std::string_view msg)
static std::unique_ptr< Statement > Convert(const Context &context, std::unique_ptr< Expression > expr)
static std::unique_ptr< Extension > Convert(const Context &context, Position pos, std::string_view name, std::string_view behaviorText)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, std::unique_ptr< Expression > base, std::string_view field)
static std::unique_ptr< Statement > ConvertWhile(const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Statement > statement)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< SymbolTable > symbolTable)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, const FunctionDeclaration &function, ExpressionArray arguments)
SkSpan< Variable *const > parameters() const
void setDefinition(const FunctionDefinition *definition)
static FunctionDeclaration * Convert(const Context &context, Position pos, const Modifiers &modifiers, std::string_view name, skia_private::TArray< std::unique_ptr< Variable > > parameters, Position returnTypePos, const Type *returnType)
static std::unique_ptr< FunctionDefinition > Convert(const Context &context, Position pos, const FunctionDeclaration &function, std::unique_ptr< Statement > body, bool builtin)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Statement > ifTrue, std::unique_ptr< Statement > ifFalse)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
static std::unique_ptr< InterfaceBlock > Convert(const Context &context, Position pos, const Modifiers &modifiers, std::string_view typeName, skia_private::TArray< Field > fields, std::string_view varName, int arraySize)
Checkpoint getCheckpoint() const
void rewindToCheckpoint(Checkpoint checkpoint)
void start(std::string_view text)
static std::unique_ptr< Literal > MakeInt(const Context &context, Position pos, SKSL_INT value)
static std::unique_ptr< Literal > MakeBool(const Context &context, Position pos, bool value)
static std::unique_ptr< Literal > MakeFloat(const Context &context, Position pos, float value)
static std::unique_ptr< ModifiersDeclaration > Convert(const Context &context, const Modifiers &modifiers)
static std::unique_ptr< Statement > Make()
AutoSymbolTable(Parser *p, std::unique_ptr< SymbolTable > *newSymbolTable, bool enable=true)
Position position(Token token)
std::string_view text(Token token)
Parser(Compiler *compiler, const ProgramSettings &settings, ProgramKind kind, std::unique_ptr< std::string > text)
std::unique_ptr< Program > programInheritingFrom(const Module *module)
std::unique_ptr< Module > moduleInheritingFrom(const Module *parentModule)
static std::unique_ptr< Expression > Make(Position pos, const Context &context)
static constexpr int kMaxOffset
static Position Range(int startOffset, int endOffset)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, std::unique_ptr< Expression > base, Operator op)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, Operator op, std::unique_ptr< Expression > base)
static std::unique_ptr< Statement > Make(Position pos, std::unique_ptr< Expression > expression)
static std::unique_ptr< StructDefinition > Convert(const Context &context, Position pos, std::string_view name, skia_private::TArray< Field > fields)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, std::unique_ptr< Expression > value, ExpressionArray caseValues, StatementArray caseStatements, std::unique_ptr< SymbolTable > symbolTable)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, Position maskPos, std::unique_ptr< Expression > base, std::string_view componentString)
const std::string * takeOwnershipOfString(std::string n)
static std::unique_ptr< Expression > Convert(const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Expression > ifTrue, std::unique_ptr< Expression > ifFalse)
static bool VerifyType(const Context &context, const SkSL::Type *type, Position pos)
static constexpr int kUnsizedArray
static std::unique_ptr< VarDeclaration > Convert(const Context &context, Position overallPos, const Modifiers &modifiers, const Type &type, Position namePos, std::string_view name, VariableStorage storage, std::unique_ptr< Expression > value)
static std::unique_ptr< Variable > Convert(const Context &context, Position pos, Position modifiersPos, const Layout &layout, ModifierFlags flags, const Type *type, Position namePos, std::string_view name, Storage storage)
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
static float max(float r, float g, float b)
bool stod(std::string_view s, SKSL_FLOAT *value)
static Position range_of_at_least_one_char(int start, int end)
static ModifierFlags parse_modifier_token(Token::Kind token)
skia_private::STArray< 2, std::unique_ptr< Statement > > StatementArray
bool stoi(std::string_view s, SKSL_INT *value)
static bool is_whitespace(Token::Kind kind)
@ kBlendSupportAllEquations
static constexpr int kMaxParseDepth
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static bool AllowsPrivateIdentifiers(ProgramKind kind)
SkSL::Version fRequiredSkSLVersion