From 0c90e06932b0f9a9debefdbb5bfc9ccbfc3405bf Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Mon, 31 Oct 2022 15:39:35 +0000 Subject: [PATCH] Added pattern grammar rules This CL changes $SDK/tools/spec_parser/Dart.g to include grammar rules associated with the upcoming feature 'patterns'. Change-Id: I3c8a5404471b0957d8e2a2b833156e02bbd3607b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/266628 Commit-Queue: William Hesse Auto-Submit: Erik Ernst Reviewed-by: William Hesse --- tools/spec_parser/Dart.g | 168 +++++++++++++++++++++++++++++++++++-- tools/spec_parser/Makefile | 2 +- 2 files changed, 163 insertions(+), 7 deletions(-) diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g index 576619a290b..4162bb80e17 100644 --- a/tools/spec_parser/Dart.g +++ b/tools/spec_parser/Dart.g @@ -4,6 +4,8 @@ // CHANGES: // +// v0.21 Add support for patterns. +// // v0.20 Adjust record syntax such that () is allowed (denoting the empty // record type and the empty record value). // @@ -528,7 +530,8 @@ metadatum ; expression - : functionExpression + : patternAssignment + | functionExpression | throwExpression | assignableExpression assignmentOperator expression | conditionalExpression @@ -557,6 +560,7 @@ primary | literal | identifier | constructorTearoff + | switchExpression ; constructorInvocation @@ -657,6 +661,19 @@ constructorTearoff : typeName typeArguments? '.' NEW ; +switchExpression + : SWITCH '(' expression ')' + LBRACE switchExpressionCase* switchExpressionDefault? RBRACE + ; + +switchExpressionCase + : caseHead '=>' expression ';' + ; + +switchExpressionDefault + : DEFAULT '=>' expression ';' + ; + throwExpression : THROW expression ; @@ -991,6 +1008,132 @@ asOperator : AS ; +pattern + : logicalOrPattern + ; + +patterns + : pattern (',' pattern)* ','? + ; + +logicalOrPattern + : logicalAndPattern ('|' logicalAndPattern)* + ; + +logicalAndPattern + : relationalPattern ('&' relationalPattern)* + ; + +relationalPattern + : (equalityOperator | relationalOperator) relationalExpression + | unaryPattern + ; + +unaryPattern + : castPattern + | nullCheckPattern + | nullAssertPattern + | primaryPattern + ; + +primaryPattern + : constantPattern + | variablePattern + | parenthesizedPattern + | listPattern + | mapPattern + | recordPattern + | extractorPattern + ; + +castPattern + : primaryPattern AS type + ; + +nullCheckPattern + : primaryPattern '?' + ; + +nullAssertPattern + : primaryPattern '!' + ; + +constantPattern + : booleanLiteral + | nullLiteral + | numericLiteral + | stringLiteral + | identifier + | qualifiedName + | constObjectExpression + | CONST typeArguments? '[' elements? ']' + | CONST typeArguments? LBRACE elements? RBRACE + | CONST '(' expression ')' + ; + +variablePattern + : (VAR | FINAL | FINAL? type)? identifier + ; + +parenthesizedPattern + : '(' pattern ')' + ; + +listPattern + : typeArguments? '[' patterns? ']' + ; + +mapPattern + : typeArguments? LBRACE mapPatternEntries? RBRACE + ; + +mapPatternEntries + : mapPatternEntry (',' mapPatternEntry)* ','? + ; + +mapPatternEntry + : expression ':' pattern + ; + +recordPattern + : '(' patternFields? ')' + ; + +patternFields + : patternField ( ',' patternField )* ','? + ; + +patternField + : (identifier? ':')? pattern + ; + +extractorPattern + : extractorName typeArguments? '(' patternFields? ')' + ; + +// TODO: Could this be a single case containing `typeName`? +// I don't think we need `C.new` or `N1.N2.N3` or `N1.N2.new`. +extractorName + : typeIdentifier + | qualifiedName + ; + +patternVariableDeclaration + : (FINAL | VAR) outerPattern '=' expression + ; + +outerPattern + : parenthesizedPattern + | listPattern + | mapPattern + | recordPattern + | extractorPattern + ; + +patternAssignment + : outerPattern '=' expression + ; + statements : statement* ; @@ -1029,8 +1172,10 @@ expressionStatement : expression? ';' ; +// TODO: make it `metadata patternVariableDeclaration ';'`? localVariableDeclaration : metadata initializedVariableDeclaration ';' + | patternVariableDeclaration ';' ; initializedVariableDeclaration @@ -1042,17 +1187,19 @@ localFunctionDeclaration ; ifStatement - : IF '(' expression ')' statement (ELSE statement)? + : IF '(' expression caseHead? ')' statement (ELSE statement)? ; forStatement : AWAIT? FOR '(' forLoopParts ')' statement ; +// TODO: Include `metadata` in the pattern form? forLoopParts : metadata declaredIdentifier IN expression | metadata identifier IN expression | forInitializerStatement expression? ';' expressionList? + | ('final' | 'var') outerPattern 'in' expression ; // The localVariableDeclaration cannot be CONST, but that can @@ -1071,14 +1218,19 @@ doStatement ; switchStatement - : SWITCH '(' expression ')' LBRACE switchCase* defaultCase? RBRACE + : SWITCH '(' expression ')' + LBRACE switchStatementCase* switchStatementDefault? RBRACE ; -switchCase - : label* CASE expression ':' statements +switchStatementCase + : label* caseHead ':' statements ; -defaultCase +caseHead + : CASE pattern (WHEN expression)? + ; + +switchStatementDefault : label* DEFAULT ':' statements ; @@ -1725,6 +1877,10 @@ SYNC : 'sync' ; +WHEN + : 'when' + ; + // Lexical tokens that are not words. NUMBER diff --git a/tools/spec_parser/Makefile b/tools/spec_parser/Makefile index fe0f2393c96..35854714d23 100644 --- a/tools/spec_parser/Makefile +++ b/tools/spec_parser/Makefile @@ -2,7 +2,7 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -GRAMMAR=../../docs/language/Dart.g +GRAMMAR=Dart.g JAVA_PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin JAVA=$(JAVA_PATH)/java JAVAC=javac