Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'xtask/src/codegen/grammar.rs')
-rw-r--r--xtask/src/codegen/grammar.rs137
1 files changed, 120 insertions, 17 deletions
diff --git a/xtask/src/codegen/grammar.rs b/xtask/src/codegen/grammar.rs
index e20dda7fec..82df78c1a8 100644
--- a/xtask/src/codegen/grammar.rs
+++ b/xtask/src/codegen/grammar.rs
@@ -67,7 +67,6 @@ fn generate_tokens(grammar: &AstSrc) -> String {
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,
}
@@ -83,6 +82,29 @@ fn generate_tokens(grammar: &AstSrc) -> String {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
+
+ impl fmt::Debug for #name {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct(#token).field("syntax", &self.syntax).finish()
+ }
+ }
+ impl Clone for #name {
+ fn clone(&self) -> Self {
+ Self { syntax: self.syntax.clone() }
+ }
+ }
+ impl hash::Hash for #name {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.syntax.hash(state);
+ }
+ }
+
+ impl Eq for #name {}
+ impl PartialEq for #name {
+ fn eq(&self, other: &Self) -> bool {
+ self.syntax == other.syntax
+ }
+ }
}
});
@@ -90,7 +112,10 @@ fn generate_tokens(grammar: &AstSrc) -> String {
crate::flags::CodegenType::Grammar,
reformat(
quote! {
+ use std::{fmt, hash};
+
use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
+
#(#tokens)*
}
.to_string(),
@@ -104,6 +129,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
.nodes
.iter()
.map(|node| {
+ let node_str_name = &node.name;
let name = format_ident!("{}", node.name);
let kind = format_ident!("{}", to_upper_snake_case(&node.name));
let traits = node
@@ -149,7 +175,6 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
(
quote! {
#[pretty_doc_comment_placeholder_workaround]
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct #name {
pub(crate) syntax: SyntaxNode,
}
@@ -180,6 +205,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
+
+ impl hash::Hash for #name {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.syntax.hash(state);
+ }
+ }
+
+ impl Eq for #name {}
+ impl PartialEq for #name {
+ fn eq(&self, other: &Self) -> bool {
+ self.syntax == other.syntax
+ }
+ }
+
+ impl Clone for #name {
+ fn clone(&self) -> Self {
+ Self { syntax: self.syntax.clone() }
+ }
+ }
+
+ impl fmt::Debug for #name {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
+ }
+ }
},
)
})
@@ -265,6 +315,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
.sorted_by_key(|(name, _)| *name)
.map(|(trait_name, nodes)| {
let name = format_ident!("Any{}", trait_name);
+ let node_str_name = name.to_string();
let trait_name = format_ident!("{}", trait_name);
let kinds: Vec<_> = nodes
.iter()
@@ -274,13 +325,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
(
quote! {
#[pretty_doc_comment_placeholder_workaround]
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct #name {
pub(crate) syntax: SyntaxNode,
}
- impl ast::#trait_name for #name {}
- },
- quote! {
impl #name {
#[inline]
pub fn new<T: ast::#trait_name>(node: T) -> #name {
@@ -289,6 +336,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
}
}
}
+ },
+ quote! {
+ impl ast::#trait_name for #name {}
impl AstNode for #name {
#[inline]
fn can_cast(kind: SyntaxKind) -> bool {
@@ -304,6 +354,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
}
}
+ impl hash::Hash for #name {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.syntax.hash(state);
+ }
+ }
+
+ impl Eq for #name {}
+ impl PartialEq for #name {
+ fn eq(&self, other: &Self) -> bool {
+ self.syntax == other.syntax
+ }
+ }
+
+ impl Clone for #name {
+ fn clone(&self) -> Self {
+ Self { syntax: self.syntax.clone() }
+ }
+ }
+
+ impl fmt::Debug for #name {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
+ }
+ }
+
#(
impl From<#nodes> for #name {
#[inline]
@@ -339,13 +414,14 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
.map(|kind| to_pascal_case(kind))
.filter(|name| !defined_nodes.iter().any(|&it| it == name))
{
- drop(node)
- // FIXME: restore this
- // eprintln!("Warning: node {} not defined in ast source", node);
+ eprintln!("Warning: node {} not defined in AST source", node);
+ drop(node);
}
let ast = quote! {
#![allow(non_snake_case)]
+ use std::{fmt, hash};
+
use crate::{
SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
ast::{self, AstNode, AstChildren, support},
@@ -476,7 +552,6 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
- // FIXME: This generates enum kinds?
let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
let ast = quote! {
@@ -484,7 +559,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
use crate::Edition;
/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
- #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+ #[derive(Debug)]
#[repr(u16)]
pub enum SyntaxKind {
// Technical SyntaxKinds: they appear temporally during parsing,
@@ -585,7 +660,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
}
#[macro_export]
- macro_rules! T {
+ macro_rules! T_ {
#([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
#([#strict_keywords_tokens] => { $crate::SyntaxKind::#strict_keywords_variants };)*
#([#contextual_keywords_tokens] => { $crate::SyntaxKind::#contextual_keywords_variants };)*
@@ -596,6 +671,38 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
[string] => { $crate::SyntaxKind::STRING };
[shebang] => { $crate::SyntaxKind::SHEBANG };
}
+
+ impl ::core::marker::Copy for SyntaxKind {}
+ impl ::core::clone::Clone for SyntaxKind {
+ #[inline]
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ impl ::core::cmp::PartialEq for SyntaxKind {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ (*self as u16) == (*other as u16)
+ }
+ }
+ impl ::core::cmp::Eq for SyntaxKind {}
+ impl ::core::cmp::PartialOrd for SyntaxKind {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> core::option::Option<core::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+ }
+ impl ::core::cmp::Ord for SyntaxKind {
+ #[inline]
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ (*self as u16).cmp(&(*other as u16))
+ }
+ }
+ impl ::core::hash::Hash for SyntaxKind {
+ fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
+ ::core::mem::discriminant(self).hash(state);
+ }
+ }
};
add_preamble(crate::flags::CodegenType::Grammar, reformat(ast.to_string()))
@@ -718,11 +825,7 @@ impl Field {
fn clean_token_name(name: &str) -> String {
let cleaned = name.trim_start_matches(['@', '#', '?']);
- if cleaned.is_empty() {
- name.to_owned()
- } else {
- cleaned.to_owned()
- }
+ if cleaned.is_empty() { name.to_owned() } else { cleaned.to_owned() }
}
fn lower(grammar: &Grammar) -> AstSrc {