Simplify parsing of for init-statements.
The existing logic was written before `varDeclarationsOrExpression- Statement` existed. The new logic mirrors how this->statement() would behave, except that it doesn't even try to parse keywords that can't be used in an init-stmt (like do, if, switch, while, etc.) Separately, I've tried just calling `this->statement()` directly, and it does work, but it is too permissive--statements that can compile away to a no-op (like `switch(0) {}`) suddenly become valid inside a for init-statement. This is probably solvable but there's not much of a reason to investigate further when the parser can catch these already. DSL doesn't go through the parser, but we're willing to accept this weak spot for DSL since it is always safe; either we catch and report the error, or the code was meaningless and optimizes away to nothing. Change-Id: I44779ec39b30cf958255534d3d5c5eb3d71d4023 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/398227 Commit-Queue: John Stiles <johnstiles@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
6475638790
commit
89b484aee3
@ -512,7 +512,14 @@ ASTNode::ID Parser::declaration() {
|
||||
|
||||
/* (varDeclarations | expressionStatement) */
|
||||
ASTNode::ID Parser::varDeclarationsOrExpressionStatement() {
|
||||
if (this->isType(this->text(this->peek()))) {
|
||||
Token nextToken = this->peek();
|
||||
if (nextToken.fKind == Token::Kind::TK_CONST) {
|
||||
// Statements that begin with `const` might be variable declarations, but can't be legal
|
||||
// SkSL expression-statements. (SkSL constructors don't take a `const` modifier.)
|
||||
return this->varDeclarations();
|
||||
}
|
||||
|
||||
if (this->isType(this->text(nextToken))) {
|
||||
// Statements that begin with a typename are most often variable declarations, but
|
||||
// occasionally the type is part of a constructor, and these are actually expression-
|
||||
// statements in disguise. First, attempt the common case: parse it as a vardecl.
|
||||
@ -1074,7 +1081,6 @@ ASTNode::ID Parser::statement() {
|
||||
this->nextToken();
|
||||
return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
|
||||
case Token::Kind::TK_CONST:
|
||||
return this->varDeclarations();
|
||||
case Token::Kind::TK_IDENTIFIER:
|
||||
return this->varDeclarationsOrExpressionStatement();
|
||||
default:
|
||||
@ -1362,38 +1368,18 @@ ASTNode::ID Parser::forStatement() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID result = this->createNode(start.fOffset, ASTNode::Kind::kFor);
|
||||
ASTNode::ID initializer;
|
||||
Token nextToken = this->peek();
|
||||
switch (nextToken.fKind) {
|
||||
case Token::Kind::TK_SEMICOLON:
|
||||
this->nextToken();
|
||||
this->createEmptyChild(result);
|
||||
break;
|
||||
case Token::Kind::TK_CONST: {
|
||||
initializer = this->varDeclarations();
|
||||
if (!initializer) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
getNode(result).addChild(initializer);
|
||||
break;
|
||||
if (nextToken.fKind == Token::Kind::TK_SEMICOLON) {
|
||||
// An empty init-statement.
|
||||
this->nextToken();
|
||||
this->createEmptyChild(result);
|
||||
} else {
|
||||
// The init-statement must be an expression or variable declaration.
|
||||
ASTNode::ID initializer = this->varDeclarationsOrExpressionStatement();
|
||||
if (!initializer) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
case Token::Kind::TK_IDENTIFIER: {
|
||||
if (this->isType(this->text(nextToken))) {
|
||||
initializer = this->varDeclarations();
|
||||
if (!initializer) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
getNode(result).addChild(initializer);
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
default:
|
||||
initializer = this->expressionStatement();
|
||||
if (!initializer) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
getNode(result).addChild(initializer);
|
||||
getNode(result).addChild(initializer);
|
||||
}
|
||||
ASTNode::ID test;
|
||||
if (this->peek().fKind != Token::Kind::TK_SEMICOLON) {
|
||||
|
Loading…
Reference in New Issue
Block a user