use std::vec;
use proc_macro2::{Delimiter, Span};
use crate::ast::{
capture::{Capture, ExampleItem, FieldDef},
keyword::Keyword,
meta::SemanticInfo,
};
#[derive(Clone)]
#[cfg_attr(any(feature = "extra-traits", test), derive(Debug))]
pub struct Pattern {
pub kind: PatternKind,
pub span: Span,
pub meta: Option<SemanticInfo>,
}
#[derive(Clone)]
#[cfg_attr(any(feature = "extra-traits", test), derive(Debug))]
pub enum PatternKind {
Literal(Keyword),
Group {
delimiter: proc_macro2::Delimiter,
children: Vec<Pattern>,
},
Capture(Box<Capture>),
}
impl Pattern {
pub fn collect_captures(&self) -> Vec<FieldDef> {
match &self.kind {
PatternKind::Literal(_) => vec![],
PatternKind::Group { children, .. } => {
children.iter().flat_map(|p| p.collect_captures()).collect()
}
PatternKind::Capture(cap) => cap.collect_captures(),
}
}
pub fn collect_example(&self) -> Vec<ExampleItem> {
match &self.kind {
PatternKind::Literal(lit) => vec![ExampleItem::Literal(lit.to_string())],
PatternKind::Capture(cap) => cap.collect_example(),
PatternKind::Group {
delimiter,
children,
} => {
let delimiter = match delimiter {
Delimiter::Brace => ("{", "}"),
Delimiter::Bracket => ("[", "]"),
Delimiter::Parenthesis => ("(", ")"),
_ => ("", ""),
};
vec![ExampleItem::Group {
delimiter: (delimiter.0.to_string(), delimiter.1.to_string()),
example: children.iter().flat_map(|p| p.collect_example()).collect(),
}]
}
}
}
}