From f89f2e38855f5b47f68758e98139aa962cb7a01d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:07:09 +0200 Subject: More readable ast_src for keywords --- xtask/src/codegen/gen_syntax.rs | 90 +++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 34 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index cc98802f6..c4fb29bbf 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -12,7 +12,7 @@ use proc_macro2::{Punct, Spacing}; use quote::{format_ident, quote}; use crate::{ - ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, + ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, codegen::{self, update, Mode}, project_root, Result, }; @@ -189,46 +189,30 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { quote!(impl ast::#trait_name for #name {}) }); - let methods = node.fields.iter().map(|(name, field)| { - let is_kw = name.ends_with("Kw"); - let method_name = match field { - FieldSrc::Shorthand => { - let name = if is_kw { &name[..name.len() - 2] } else { &name }; - format_ident!("{}", to_lower_snake_case(name)) - } - _ => format_ident!("{}", name), - }; - let ty = match field { - FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, - FieldSrc::Shorthand => name, - }; - - let ty = format_ident!("{}", ty); + let methods = node.fields.iter().map(|field| { + let method_name = field.method_name(); + let ty = field.ty(); - match field { - FieldSrc::Many(_) => { + if field.is_many() { + quote! { + pub fn #method_name(&self) -> AstChildren<#ty> { + support::children(&self.syntax) + } + } + } else { + if let Some(token_kind) = field.token_kind() { quote! { - pub fn #method_name(&self) -> AstChildren<#ty> { - support::children(&self.syntax) + pub fn #method_name(&self) -> Option<#ty> { + support::token2(&self.syntax, #token_kind) } } - } - FieldSrc::Optional(_) | FieldSrc::Shorthand => { + } else { let is_token = token_kinds.contains(&ty.to_string()); if is_token { let method_name = format_ident!("{}_token", method_name); - if is_kw { - let token_kind = format_ident!("{}", to_upper_snake_case(name)); - quote! { - pub fn #method_name(&self) -> Option { - support::token2(&self.syntax, #token_kind) - } - } - } else { - quote! { - pub fn #method_name(&self) -> Option<#ty> { - support::token(&self.syntax) - } + quote! { + pub fn #method_name(&self) -> Option<#ty> { + support::token(&self.syntax) } } } else { @@ -351,6 +335,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { use crate::{ SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, ast::{self, AstNode, AstChildren, support}, + T, }; use super::tokens::*; @@ -519,3 +504,40 @@ fn to_pascal_case(s: &str) -> String { } buf } + +impl Field<'_> { + fn is_many(&self) -> bool { + match self { + Field::Node { src: FieldSrc::Many(_), .. } => true, + _ => false, + } + } + fn token_kind(&self) -> Option { + let res = match self { + Field::Token(token) => { + let token = format_ident!("{}", token); + quote! { T![#token] } + } + _ => return None, + }; + Some(res) + } + fn method_name(&self) -> proc_macro2::Ident { + match self { + Field::Token(name) => format_ident!("{}_token", name), + Field::Node { name, src } => match src { + FieldSrc::Shorthand => format_ident!("{}", to_lower_snake_case(name)), + _ => format_ident!("{}", name), + }, + } + } + fn ty(&self) -> proc_macro2::Ident { + match self { + Field::Token(_) => format_ident!("SyntaxToken"), + Field::Node { name, src } => match src { + FieldSrc::Optional(ty) | FieldSrc::Many(ty) => format_ident!("{}", ty), + FieldSrc::Shorthand => format_ident!("{}", name), + }, + } + } +} -- cgit v1.2.3 From c8b4c36f8161d34c8145a49965efee4514275989 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:11:05 +0200 Subject: Semicolon token --- xtask/src/codegen/gen_syntax.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index c4fb29bbf..26f541da1 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -515,7 +515,7 @@ impl Field<'_> { fn token_kind(&self) -> Option { let res = match self { Field::Token(token) => { - let token = format_ident!("{}", token); + let token: proc_macro2::TokenStream = token.parse().unwrap(); quote! { T![#token] } } _ => return None, @@ -524,7 +524,13 @@ impl Field<'_> { } fn method_name(&self) -> proc_macro2::Ident { match self { - Field::Token(name) => format_ident!("{}_token", name), + Field::Token(name) => { + let name = match *name { + ";" => "semicolon", + _ => name, + }; + format_ident!("{}_token", name) + } Field::Node { name, src } => match src { FieldSrc::Shorthand => format_ident!("{}", to_lower_snake_case(name)), _ => format_ident!("{}", name), -- cgit v1.2.3 From 1c5d8591952cbb017fd6679a1ef29a86e1499025 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:18:43 +0200 Subject: Start replacing tokens --- xtask/src/codegen/gen_syntax.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 26f541da1..b7698ee6e 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -345,6 +345,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { #(#displays)* }; + let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])"); let pretty = crate::reformat(ast)?; Ok(pretty) } @@ -527,6 +528,9 @@ impl Field<'_> { Field::Token(name) => { let name = match *name { ";" => "semicolon", + "->" => "thin_arrow", + "'{'" => "l_curly", + "'}'" => "r_curly", _ => name, }; format_ident!("{}_token", name) -- cgit v1.2.3 From 548f562ddad3bca515b304f82e110aeb319591e3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:29:59 +0200 Subject: Other delimiters --- xtask/src/codegen/gen_syntax.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index b7698ee6e..a903d1da7 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -531,6 +531,10 @@ impl Field<'_> { "->" => "thin_arrow", "'{'" => "l_curly", "'}'" => "r_curly", + "'('" => "l_paren", + "')'" => "r_paren", + "'['" => "l_brack", + "']'" => "r_brack", _ => name, }; format_ident!("{}_token", name) -- cgit v1.2.3 From 779f06ed77e868b9409a1724f736a045415d4922 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:35:39 +0200 Subject: Convert more tokens --- xtask/src/codegen/gen_syntax.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index a903d1da7..4c9e447a3 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -535,6 +535,8 @@ impl Field<'_> { "')'" => "r_paren", "'['" => "l_brack", "']'" => "r_brack", + "=" => "eq", + "!" => "excl", _ => name, }; format_ident!("{}_token", name) -- cgit v1.2.3 From 8d71a6bf0ca51ae099a5b470afdb957bca321441 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 11:49:13 +0200 Subject: Scale token generation back --- xtask/src/codegen/gen_syntax.rs | 182 +++++----------------------------------- 1 file changed, 19 insertions(+), 163 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 4c9e447a3..ce18f2b8f 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -3,10 +3,7 @@ //! Specifically, it generates the `SyntaxKind` enum and a number of newtype //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. -use std::{ - borrow::Cow, - collections::{BTreeSet, HashSet}, -}; +use std::collections::{BTreeSet, HashSet}; use proc_macro2::{Punct, Spacing}; use quote::{format_ident, quote}; @@ -26,10 +23,6 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { let contents = generate_nodes(KINDS_SRC, AST_SRC)?; update(ast_nodes_file.as_path(), &contents, mode)?; - let ast_tokens_file = project_root().join(codegen::AST_TOKENS); - let contents = generate_tokens(KINDS_SRC, AST_SRC)?; - update(ast_tokens_file.as_path(), &contents, mode)?; - Ok(()) } @@ -40,147 +33,7 @@ struct ElementKinds { has_tokens: bool, } -fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { - let all_token_kinds: Vec<_> = kinds - .punct - .into_iter() - .map(|(_, kind)| kind) - .copied() - .map(|x| x.into()) - .chain( - kinds - .keywords - .into_iter() - .chain(kinds.contextual_keywords.into_iter()) - .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), - ) - .chain(kinds.literals.into_iter().copied().map(|x| x.into())) - .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) - .collect(); - - let tokens = all_token_kinds.iter().filter_map(|kind_str| { - if kind_str.ends_with("_KW") { - return None; - } - let kind_str = &**kind_str; - let kind = format_ident!("{}", kind_str); - let name = format_ident!("{}", to_pascal_case(kind_str)); - let res = quote! { - #[derive(Debug, Clone, PartialEq, Eq, Hash)] - pub struct #name { - pub(crate) syntax: SyntaxToken, - } - - impl std::fmt::Display for #name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.syntax, f) - } - } - - impl AstToken for #name { - fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } - fn cast(syntax: SyntaxToken) -> Option { - if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } - } - fn syntax(&self) -> &SyntaxToken { &self.syntax } - } - }; - Some(res) - }); - - let enums = grammar.token_enums.iter().map(|en| { - let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::>(); - let name = format_ident!("{}", en.name); - let kinds = variants - .iter() - .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) - .collect::>(); - assert!(en.traits.is_empty()); - - quote! { - #[derive(Debug, Clone, PartialEq, Eq, Hash)] - pub enum #name { - #(#variants(#variants),)* - } - - #( - impl From<#variants> for #name { - fn from(node: #variants) -> #name { - #name::#variants(node) - } - } - )* - - impl std::fmt::Display for #name { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } - } - - impl AstToken for #name { - fn can_cast(kind: SyntaxKind) -> bool { - match kind { - #(#kinds)|* => true, - _ => false, - } - } - fn cast(syntax: SyntaxToken) -> Option { - let res = match syntax.kind() { - #( - #kinds => #name::#variants(#variants { syntax }), - )* - _ => return None, - }; - Some(res) - } - fn syntax(&self) -> &SyntaxToken { - match self { - #( - #name::#variants(it) => &it.syntax, - )* - } - } - } - } - }); - - crate::reformat(quote! { - use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; - - #(#tokens)* - #(#enums)* - }) -} - fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { - let all_token_kinds: Vec<_> = kinds - .punct - .into_iter() - .map(|(_, kind)| kind) - .copied() - .map(|x| x.into()) - .chain( - kinds - .keywords - .into_iter() - .chain(kinds.contextual_keywords.into_iter()) - .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), - ) - .chain(kinds.literals.into_iter().copied().map(|x| x.into())) - .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) - .collect(); - - let mut token_kinds = HashSet::new(); - for kind in &all_token_kinds { - let kind = &**kind; - let name = to_pascal_case(kind); - token_kinds.insert(name); - } - - for en in grammar.token_enums { - token_kinds.insert(en.name.to_string()); - } - let nodes = grammar.nodes.iter().map(|node| { let name = format_ident!("{}", node.name); let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); @@ -207,19 +60,9 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { } } } else { - let is_token = token_kinds.contains(&ty.to_string()); - if is_token { - let method_name = format_ident!("{}_token", method_name); - quote! { - pub fn #method_name(&self) -> Option<#ty> { - support::token(&self.syntax) - } - } - } else { - quote! { - pub fn #method_name(&self) -> Option<#ty> { - support::child(&self.syntax) - } + quote! { + pub fn #method_name(&self) -> Option<#ty> { + support::child(&self.syntax) } } } @@ -338,8 +181,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { T, }; - use super::tokens::*; - #(#nodes)* #(#enums)* #(#displays)* @@ -456,6 +297,8 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result { macro_rules! T { #((#punctuation_values) => { $crate::SyntaxKind::#punctuation };)* #((#all_keywords_idents) => { $crate::SyntaxKind::#all_keywords };)* + (lifetime) => { $crate::SyntaxKind::LIFETIME }; + (ident) => { $crate::SyntaxKind::IDENT }; } }; @@ -535,8 +378,21 @@ impl Field<'_> { "')'" => "r_paren", "'['" => "l_brack", "']'" => "r_brack", + "<" => "l_angle", + ">" => "r_angle", "=" => "eq", "!" => "excl", + "*" => "star", + "&" => "amp", + "_" => "underscore", + "." => "dot", + ".." => "dotdot", + "..." => "dotdotdot", + "=>" => "fat_arrow", + "@" => "at", + ":" => "colon", + "::" => "coloncolon", + "#" => "pound", _ => name, }; format_ident!("{}_token", name) -- cgit v1.2.3 From 4560fe2abffde05e6ceb084e6d42207e0ce84b68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 15:53:09 +0200 Subject: Generate only minimal set of ineresting tokens --- xtask/src/codegen/gen_syntax.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index ce18f2b8f..fa48853d2 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -19,6 +19,10 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; + let ast_tokens_file = project_root().join(codegen::AST_TOKENS); + let contents = generate_tokens(KINDS_SRC, AST_SRC)?; + update(ast_tokens_file.as_path(), &contents, mode)?; + let ast_nodes_file = project_root().join(codegen::AST_NODES); let contents = generate_nodes(KINDS_SRC, AST_SRC)?; update(ast_nodes_file.as_path(), &contents, mode)?; @@ -33,6 +37,37 @@ struct ElementKinds { has_tokens: bool, } +fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { + let tokens = grammar.tokens.iter().map(|token| { + let name = format_ident!("{}", token); + let kind = format_ident!("{}", to_upper_snake_case(token)); + quote! { + #[derive(Debug, Clone, PartialEq, Eq, Hash)] + pub struct #name { + pub(crate) syntax: SyntaxToken, + } + impl std::fmt::Display for #name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.syntax, f) + } + } + impl AstToken for #name { + fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } + fn cast(syntax: SyntaxToken) -> Option { + if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } + } + fn syntax(&self) -> &SyntaxToken { &self.syntax } + } + } + }); + + let pretty = crate::reformat(quote! { + use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; + #(#tokens)* + })?; + Ok(pretty) +} + fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { let nodes = grammar.nodes.iter().map(|node| { let name = format_ident!("{}", node.name); -- cgit v1.2.3 From e0f02d233fa3e26e4f10bffacbaef11b6bcb0ada Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 15:54:05 +0200 Subject: Remove dead code --- xtask/src/codegen/gen_syntax.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index fa48853d2..7dc7f396c 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -3,7 +3,7 @@ //! Specifically, it generates the `SyntaxKind` enum and a number of newtype //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. -use std::collections::{BTreeSet, HashSet}; +use std::collections::HashSet; use proc_macro2::{Punct, Spacing}; use quote::{format_ident, quote}; @@ -20,7 +20,7 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; let ast_tokens_file = project_root().join(codegen::AST_TOKENS); - let contents = generate_tokens(KINDS_SRC, AST_SRC)?; + let contents = generate_tokens(AST_SRC)?; update(ast_tokens_file.as_path(), &contents, mode)?; let ast_nodes_file = project_root().join(codegen::AST_NODES); @@ -30,14 +30,7 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { Ok(()) } -#[derive(Debug, Default, Clone)] -struct ElementKinds { - kinds: BTreeSet, - has_nodes: bool, - has_tokens: bool, -} - -fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { +fn generate_tokens(grammar: AstSrc<'_>) -> Result { let tokens = grammar.tokens.iter().map(|token| { let name = format_ident!("{}", token); let kind = format_ident!("{}", to_upper_snake_case(token)); @@ -91,7 +84,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { if let Some(token_kind) = field.token_kind() { quote! { pub fn #method_name(&self) -> Option<#ty> { - support::token2(&self.syntax, #token_kind) + support::token(&self.syntax, #token_kind) } } } else { -- cgit v1.2.3 From d4332760d81c5575dd04b39275c4979b59bb9fc4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 16:00:24 +0200 Subject: Better readability --- xtask/src/codegen/gen_syntax.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 7dc7f396c..ff290bb33 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -57,7 +57,8 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result { let pretty = crate::reformat(quote! { use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; #(#tokens)* - })?; + })? + .replace("#[derive", "\n#[derive"); Ok(pretty) } @@ -215,7 +216,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result { }; let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])"); - let pretty = crate::reformat(ast)?; + let pretty = crate::reformat(ast)?.replace("#[derive", "\n#[derive"); Ok(pretty) } -- cgit v1.2.3 From 5c5bde47fb759440d007c90fd83021de538120b8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 17:06:57 +0200 Subject: Rename some tokens --- xtask/src/codegen/gen_syntax.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'xtask/src/codegen') diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index ff290bb33..ec1f6ad8a 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs @@ -324,10 +324,10 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result { #[macro_export] macro_rules! T { - #((#punctuation_values) => { $crate::SyntaxKind::#punctuation };)* - #((#all_keywords_idents) => { $crate::SyntaxKind::#all_keywords };)* - (lifetime) => { $crate::SyntaxKind::LIFETIME }; - (ident) => { $crate::SyntaxKind::IDENT }; + #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)* + #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)* + [lifetime] => { $crate::SyntaxKind::LIFETIME }; + [ident] => { $crate::SyntaxKind::IDENT }; } }; -- cgit v1.2.3