1use proc_macro2::TokenStream;2use quote::{format_ident, quote};34use super::{escape_token_macro, KindsSrc};56impl AstNodeSrc {7 pub fn remove_field(&mut self, to_remove: Vec<usize>) {8 to_remove.into_iter().rev().for_each(|idx| {9 self.fields.remove(idx);10 });11 }12}1314#[allow(dead_code)]15#[derive(Default, Debug)]16pub struct AstSrc {17 pub tokens: Vec<String>,18 pub nodes: Vec<AstNodeSrc>,19 pub enums: Vec<AstEnumSrc>,20}21#[derive(Debug)]22pub struct AstNodeSrc {23 pub doc: Vec<String>,24 pub name: String,25 pub traits: Vec<String>,26 pub fields: Vec<Field>,27}2829#[derive(Debug, Eq, PartialEq)]30pub enum Field {31 Token(String),32 Node {33 name: String,34 ty: String,35 cardinality: Cardinality,36 },37}3839#[derive(Debug, Eq, PartialEq)]40pub enum Cardinality {41 Optional,42 Many,43}4445#[derive(Debug, Clone)]46pub struct AstEnumSrc {47 pub doc: Vec<String>,48 pub name: String,49 pub traits: Vec<String>,50 pub variants: Vec<String>,51}5253impl Field {54 pub fn is_many(&self) -> bool {55 matches!(56 self,57 Field::Node {58 cardinality: Cardinality::Many,59 ..60 }61 )62 }63 pub fn token_kind(&self) -> Option<TokenStream> {64 match self {65 Field::Token(token) => {66 let token: TokenStream = escape_token_macro(token);67 Some(quote! { T![#token] })68 }69 _ => None,70 }71 }7273 pub fn method_name(&self, kinds: &KindsSrc) -> proc_macro2::Ident {74 match self {75 Field::Token(name) => {76 if let Some(punct_name) = kinds.get_punct_name(name) {77 format_ident!("{}_token", punct_name.to_lowercase())78 } else {79 format_ident!("{}_token", name.to_lowercase())80 }81 }82 Field::Node { name, .. } => {83 format_ident!("{}", name)84 }85 }86 }87 pub fn ty(&self) -> proc_macro2::Ident {88 match self {89 Field::Token(_) => format_ident!("SyntaxToken"),90 Field::Node { ty, .. } => format_ident!("{}", ty),91 }92 }93}