Unnamed repository; edit this file 'description' to name the repository.
Parse `try bikeshed T {}` syntax
Geoffry Song 3 months ago
parent 74eca73 · commit 97770dc
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs6
-rw-r--r--crates/parser/src/syntax_kind/generated.rs8
-rw-r--r--crates/parser/test_data/parser/err/0042_weird_blocks.rast3
-rw-r--r--crates/parser/test_data/parser/inline/ok/try_block_expr.rast37
-rw-r--r--crates/parser/test_data/parser/inline/ok/try_block_expr.rs1
-rw-r--r--crates/syntax/rust.ungram5
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs54
-rw-r--r--xtask/src/codegen/grammar/ast_src.rs2
8 files changed, 110 insertions, 6 deletions
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index d83e2eb2b4..b75474ee2b 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -976,11 +976,17 @@ fn break_expr(p: &mut Parser<'_>, r: Restrictions) -> CompletedMarker {
// test try_block_expr
// fn foo() {
// let _ = try {};
+// let _ = try bikeshed T<U> {};
// }
fn try_block_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(T![try]));
let m = m.unwrap_or_else(|| p.start());
+ let try_modifier = p.start();
p.bump(T![try]);
+ if p.eat_contextual_kw(T![bikeshed]) {
+ type_(p);
+ }
+ try_modifier.complete(p, TRY_BLOCK_MODIFIER);
if p.at(T!['{']) {
stmt_list(p);
} else {
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 5d22d966b2..a2295e4495 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -114,6 +114,7 @@ pub enum SyntaxKind {
ATT_SYNTAX_KW,
AUTO_KW,
AWAIT_KW,
+ BIKESHED_KW,
BUILTIN_KW,
CLOBBER_ABI_KW,
DEFAULT_KW,
@@ -285,6 +286,7 @@ pub enum SyntaxKind {
STRUCT,
TOKEN_TREE,
TRAIT,
+ TRY_BLOCK_MODIFIER,
TRY_EXPR,
TUPLE_EXPR,
TUPLE_FIELD,
@@ -458,6 +460,7 @@ impl SyntaxKind {
| STRUCT
| TOKEN_TREE
| TRAIT
+ | TRY_BLOCK_MODIFIER
| TRY_EXPR
| TUPLE_EXPR
| TUPLE_FIELD
@@ -596,6 +599,7 @@ impl SyntaxKind {
ASM_KW => "asm",
ATT_SYNTAX_KW => "att_syntax",
AUTO_KW => "auto",
+ BIKESHED_KW => "bikeshed",
BUILTIN_KW => "builtin",
CLOBBER_ABI_KW => "clobber_abi",
DEFAULT_KW => "default",
@@ -698,6 +702,7 @@ impl SyntaxKind {
ASM_KW => true,
ATT_SYNTAX_KW => true,
AUTO_KW => true,
+ BIKESHED_KW => true,
BUILTIN_KW => true,
CLOBBER_ABI_KW => true,
DEFAULT_KW => true,
@@ -788,6 +793,7 @@ impl SyntaxKind {
ASM_KW => true,
ATT_SYNTAX_KW => true,
AUTO_KW => true,
+ BIKESHED_KW => true,
BUILTIN_KW => true,
CLOBBER_ABI_KW => true,
DEFAULT_KW => true,
@@ -941,6 +947,7 @@ impl SyntaxKind {
"asm" => ASM_KW,
"att_syntax" => ATT_SYNTAX_KW,
"auto" => AUTO_KW,
+ "bikeshed" => BIKESHED_KW,
"builtin" => BUILTIN_KW,
"clobber_abi" => CLOBBER_ABI_KW,
"default" => DEFAULT_KW,
@@ -1112,6 +1119,7 @@ macro_rules ! T_ {
[asm] => { $ crate :: SyntaxKind :: ASM_KW };
[att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW };
[auto] => { $ crate :: SyntaxKind :: AUTO_KW };
+ [bikeshed] => { $ crate :: SyntaxKind :: BIKESHED_KW };
[builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW };
[clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW };
[default] => { $ crate :: SyntaxKind :: DEFAULT_KW };
diff --git a/crates/parser/test_data/parser/err/0042_weird_blocks.rast b/crates/parser/test_data/parser/err/0042_weird_blocks.rast
index d6d2e75cca..9e4e9dbf9d 100644
--- a/crates/parser/test_data/parser/err/0042_weird_blocks.rast
+++ b/crates/parser/test_data/parser/err/0042_weird_blocks.rast
@@ -45,7 +45,8 @@ SOURCE_FILE
WHITESPACE " "
EXPR_STMT
BLOCK_EXPR
- TRY_KW "try"
+ TRY_BLOCK_MODIFIER
+ TRY_KW "try"
WHITESPACE " "
LITERAL
INT_NUMBER "92"
diff --git a/crates/parser/test_data/parser/inline/ok/try_block_expr.rast b/crates/parser/test_data/parser/inline/ok/try_block_expr.rast
index aec8fbf477..472ce711c5 100644
--- a/crates/parser/test_data/parser/inline/ok/try_block_expr.rast
+++ b/crates/parser/test_data/parser/inline/ok/try_block_expr.rast
@@ -21,7 +21,42 @@ SOURCE_FILE
EQ "="
WHITESPACE " "
BLOCK_EXPR
- TRY_KW "try"
+ TRY_BLOCK_MODIFIER
+ TRY_KW "try"
+ WHITESPACE " "
+ STMT_LIST
+ L_CURLY "{"
+ R_CURLY "}"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ WILDCARD_PAT
+ UNDERSCORE "_"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ BLOCK_EXPR
+ TRY_BLOCK_MODIFIER
+ TRY_KW "try"
+ WHITESPACE " "
+ BIKESHED_KW "bikeshed"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "T"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "U"
+ R_ANGLE ">"
WHITESPACE " "
STMT_LIST
L_CURLY "{"
diff --git a/crates/parser/test_data/parser/inline/ok/try_block_expr.rs b/crates/parser/test_data/parser/inline/ok/try_block_expr.rs
index 0f1b41eb64..719980473c 100644
--- a/crates/parser/test_data/parser/inline/ok/try_block_expr.rs
+++ b/crates/parser/test_data/parser/inline/ok/try_block_expr.rs
@@ -1,3 +1,4 @@
fn foo() {
let _ = try {};
+ let _ = try bikeshed T<U> {};
}
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 991fe7d83a..544053408f 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -472,8 +472,11 @@ RefExpr =
TryExpr =
Attr* Expr '?'
+TryBlockModifier =
+ 'try' ('bikeshed' Type)?
+
BlockExpr =
- Attr* Label? ('try' | 'unsafe' | ('async' 'move'?) | ('gen' 'move'?) | 'const') StmtList
+ Attr* Label? (TryBlockModifier | 'unsafe' | ('async' 'move'?) | ('gen' 'move'?) | 'const') StmtList
PrefixExpr =
Attr* op:('-' | '!' | '*') Expr
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 7b9f5b9166..c4e72eafa7 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -323,6 +323,8 @@ impl BlockExpr {
#[inline]
pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
#[inline]
+ pub fn try_block_modifier(&self) -> Option<TryBlockModifier> { support::child(&self.syntax) }
+ #[inline]
pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
#[inline]
pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
@@ -331,8 +333,6 @@ impl BlockExpr {
#[inline]
pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
#[inline]
- pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
- #[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
pub struct BoxPat {
@@ -1630,6 +1630,19 @@ impl Trait {
#[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
+pub struct TryBlockModifier {
+ pub(crate) syntax: SyntaxNode,
+}
+impl TryBlockModifier {
+ #[inline]
+ pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+ #[inline]
+ pub fn bikeshed_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![bikeshed])
+ }
+ #[inline]
+ pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
+}
pub struct TryExpr {
pub(crate) syntax: SyntaxNode,
}
@@ -6320,6 +6333,38 @@ impl fmt::Debug for Trait {
f.debug_struct("Trait").field("syntax", &self.syntax).finish()
}
}
+impl AstNode for TryBlockModifier {
+ #[inline]
+ fn kind() -> SyntaxKind
+ where
+ Self: Sized,
+ {
+ TRY_BLOCK_MODIFIER
+ }
+ #[inline]
+ fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_MODIFIER }
+ #[inline]
+ fn cast(syntax: SyntaxNode) -> Option<Self> {
+ if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
+ }
+ #[inline]
+ fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl hash::Hash for TryBlockModifier {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
+}
+impl Eq for TryBlockModifier {}
+impl PartialEq for TryBlockModifier {
+ fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
+}
+impl Clone for TryBlockModifier {
+ fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
+}
+impl fmt::Debug for TryBlockModifier {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("TryBlockModifier").field("syntax", &self.syntax).finish()
+ }
+}
impl AstNode for TryExpr {
#[inline]
fn kind() -> SyntaxKind
@@ -9979,6 +10024,11 @@ impl std::fmt::Display for Trait {
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for TryBlockModifier {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for TryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
diff --git a/xtask/src/codegen/grammar/ast_src.rs b/xtask/src/codegen/grammar/ast_src.rs
index b9f570fe0e..205072a6ce 100644
--- a/xtask/src/codegen/grammar/ast_src.rs
+++ b/xtask/src/codegen/grammar/ast_src.rs
@@ -112,7 +112,7 @@ const RESERVED: &[&str] = &[
// keywords that are keywords only in specific parse contexts
#[doc(alias = "WEAK_KEYWORDS")]
const CONTEXTUAL_KEYWORDS: &[&str] =
- &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe"];
+ &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe", "bikeshed"];
// keywords we use for special macro expansions
const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[
"asm",