use crate::ast::owned;
use crate::ast::traits;
use crate::ast::traits::{BlockCast, InlineCast, InlineContainer};
use crate::syntax::{MktLang, SyntaxKind, SyntaxNode};
use core::marker::PhantomData;
use rowan::SyntaxNodeChildren;
use std::borrow::Cow;
use std::convert::TryFrom;
use std::ops::Deref;
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
pub enum ConcreteSyntax {}
impl traits::Syntax for ConcreteSyntax {
type Root = Root;
type Block = Block;
type Admin = Admin;
type Mod = Mod;
type Inline = Inline;
type Emphasis = Emphasis;
type Icon = Icon;
type Link = Link;
type Newline = Newline;
type Strikethrough = Strikethrough;
type Strong = Strong;
type Text = Text;
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Root {
syntax: SyntaxNode,
}
impl TryFrom<SyntaxNode> for Root {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeContent => Ok(Self { syntax }),
_ => Err(()),
}
}
}
pub struct BlockIter<'a> {
inner: SyntaxNodeChildren<MktLang>,
phantom: PhantomData<&'a ()>,
}
impl<'a> BlockIter<'a> {
pub fn new(children: SyntaxNodeChildren<MktLang>) -> Self {
BlockIter {
inner: children,
phantom: PhantomData,
}
}
}
impl<'a> Iterator for BlockIter<'a> {
type Item = traits::MaybeOwned<'a, Block>;
fn next(&mut self) -> Option<Self::Item> {
for node in &mut self.inner {
if let Ok(e) = Block::try_from(node) {
return Some(traits::MaybeOwned::Owned(e));
}
}
None
}
}
pub struct InlineIter<'a> {
inner: SyntaxNodeChildren<MktLang>,
phantom: PhantomData<&'a ()>,
}
impl<'a> InlineIter<'a> {
pub fn new(children: SyntaxNodeChildren<MktLang>) -> Self {
InlineIter {
inner: children,
phantom: PhantomData,
}
}
}
impl<'a> Iterator for InlineIter<'a> {
type Item = traits::MaybeOwned<'a, Inline>;
fn next(&mut self) -> Option<Self::Item> {
for node in &mut self.inner {
if let Ok(e) = Inline::try_from(node) {
return Some(traits::MaybeOwned::Owned(e));
}
}
None
}
}
impl traits::BlockContainer for Root {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Block>> + 'a> {
Box::new(BlockIter::new(self.syntax.children()))
}
}
impl traits::Root for Root {
type Ast = ConcreteSyntax;
}
impl Root {
pub fn to_owned_ast(&self) -> owned::Root {
use traits::BlockContainer;
let children: Vec<owned::Block> = self.children().map(|c| Block::to_owned_ast(&c)).collect();
owned::Root { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Block {
syntax: SyntaxNode,
}
impl Deref for Block {
type Target = Block;
fn deref(&self) -> &Self::Target {
self
}
}
impl TryFrom<SyntaxNode> for Block {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
if syntax.kind().is_block() {
Ok(Self { syntax })
} else {
Err(())
}
}
}
impl traits::Block for Block {
type Ast = ConcreteSyntax;
fn cast(&self) -> BlockCast<ConcreteSyntax> {
match self.syntax.kind() {
SyntaxKind::NodeAdmin => BlockCast::Admin(traits::MaybeOwned::Owned(Admin {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeEmphasis => BlockCast::Emphasis(traits::MaybeOwned::Owned(Emphasis {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeIcon => BlockCast::Icon(traits::MaybeOwned::Owned(Icon {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeLink => BlockCast::Link(traits::MaybeOwned::Owned(Link {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeMod => BlockCast::Mod(traits::MaybeOwned::Owned(Mod {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeNewline => BlockCast::Newline(traits::MaybeOwned::Owned(Newline {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeStrikethrough => BlockCast::Strikethrough(traits::MaybeOwned::Owned(Strikethrough {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeStrong => BlockCast::Strong(traits::MaybeOwned::Owned(Strong {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeText => BlockCast::Text(traits::MaybeOwned::Owned(Text {
syntax: self.syntax.clone(),
})),
_ => panic!("UnexpectedNodeType {:?}", self.syntax.kind()),
}
}
}
impl Block {
pub fn to_owned_ast(&self) -> owned::Block {
use traits::Block;
match Block::cast(self) {
BlockCast::Admin(n) => owned::Block::Admin(n.to_owned_ast()),
BlockCast::Mod(n) => owned::Block::Mod(n.to_owned_ast()),
BlockCast::Emphasis(n) => owned::Block::Emphasis(n.to_owned_ast()),
BlockCast::Icon(n) => owned::Block::Icon(n.to_owned_ast()),
BlockCast::Link(n) => owned::Block::Link(n.to_owned_ast()),
BlockCast::Newline(n) => owned::Block::Newline(n.to_owned_ast()),
BlockCast::Strikethrough(n) => owned::Block::Strikethrough(n.to_owned_ast()),
BlockCast::Strong(n) => owned::Block::Strong(n.to_owned_ast()),
BlockCast::Text(n) => owned::Block::Text(n.to_owned_ast()),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Admin {
syntax: SyntaxNode,
}
impl traits::BlockContainer for Admin {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Block>> + 'a> {
Box::new(BlockIter::new(self.syntax.children()))
}
}
impl traits::Admin for Admin {
type Ast = ConcreteSyntax;
}
impl TryFrom<SyntaxNode> for Admin {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeAdmin => Ok(Admin { syntax }),
_ => Err(()),
}
}
}
impl Admin {
pub fn to_owned_ast(&self) -> owned::Admin {
use traits::BlockContainer;
let children: Vec<owned::Block> = self.children().map(|c| Block::to_owned_ast(&c)).collect();
owned::Admin { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Mod {
syntax: SyntaxNode,
}
impl traits::BlockContainer for Mod {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Block>> + 'a> {
Box::new(BlockIter::new(self.syntax.children()))
}
}
impl traits::Mod for Mod {
type Ast = ConcreteSyntax;
}
impl TryFrom<SyntaxNode> for Mod {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeMod => Ok(Mod { syntax }),
_ => Err(()),
}
}
}
impl Mod {
pub fn to_owned_ast(&self) -> owned::Mod {
use traits::BlockContainer;
let children: Vec<owned::Block> = self.children().map(|c| Block::to_owned_ast(&c)).collect();
owned::Mod { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Inline {
syntax: SyntaxNode,
}
impl Deref for Inline {
type Target = Inline;
fn deref(&self) -> &Self::Target {
self
}
}
impl TryFrom<SyntaxNode> for Inline {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
if syntax.kind().is_inline() {
Ok(Self { syntax })
} else {
Err(())
}
}
}
impl traits::Inline for Inline {
type Ast = ConcreteSyntax;
fn cast(&self) -> InlineCast<ConcreteSyntax> {
match self.syntax.kind() {
SyntaxKind::NodeEmphasis => InlineCast::Emphasis(traits::MaybeOwned::Owned(Emphasis {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeIcon => InlineCast::Icon(traits::MaybeOwned::Owned(Icon {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeLink => InlineCast::Link(traits::MaybeOwned::Owned(Link {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeNewline => InlineCast::Newline(traits::MaybeOwned::Owned(Newline {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeStrikethrough => InlineCast::Strikethrough(traits::MaybeOwned::Owned(Strikethrough {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeStrong => InlineCast::Strong(traits::MaybeOwned::Owned(Strong {
syntax: self.syntax.clone(),
})),
SyntaxKind::NodeText => InlineCast::Text(traits::MaybeOwned::Owned(Text {
syntax: self.syntax.clone(),
})),
_ => panic!("UnexpectedNodeType {:?}", self.syntax.kind()),
}
}
}
impl Inline {
pub fn to_owned_ast(&self) -> owned::Inline {
use traits::Inline;
match Inline::cast(self) {
InlineCast::Emphasis(n) => owned::Inline::Emphasis(n.to_owned_ast()),
InlineCast::Icon(n) => owned::Inline::Icon(n.to_owned_ast()),
InlineCast::Link(n) => owned::Inline::Link(n.to_owned_ast()),
InlineCast::Newline(n) => owned::Inline::Newline(n.to_owned_ast()),
InlineCast::Strikethrough(n) => owned::Inline::Strikethrough(n.to_owned_ast()),
InlineCast::Strong(n) => owned::Inline::Strong(n.to_owned_ast()),
InlineCast::Text(n) => owned::Inline::Text(n.to_owned_ast()),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Emphasis {
syntax: SyntaxNode,
}
impl traits::InlineContainer for Emphasis {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Inline>> + 'a> {
Box::new(InlineIter::new(self.syntax.first_child().unwrap().children()))
}
}
impl traits::Emphasis for Emphasis {
type Ast = ConcreteSyntax;
}
impl TryFrom<SyntaxNode> for Emphasis {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeEmphasis => Ok(Emphasis { syntax }),
_ => Err(()),
}
}
}
impl Emphasis {
pub fn to_owned_ast(&self) -> owned::Emphasis {
let children: Vec<owned::Inline> = self.children().map(|c| Inline::to_owned_ast(&c)).collect();
owned::Emphasis { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Icon {
syntax: SyntaxNode,
}
impl traits::Icon for Icon {
type Ast = ConcreteSyntax;
fn key(&self) -> Cow<str> {
let key_node = self.syntax.first_child().unwrap();
let token = key_node.first_token().unwrap();
let text = token.text();
Cow::Owned(text.to_string())
}
}
impl TryFrom<SyntaxNode> for Icon {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeIcon => Ok(Icon { syntax }),
_ => Err(()),
}
}
}
impl Icon {
pub fn to_owned_ast(&self) -> owned::Icon {
use traits::Icon;
let key = self.key();
owned::Icon {
loc: (),
key: key.to_string(),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Link {
syntax: SyntaxNode,
}
impl traits::InlineContainer for Link {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Inline>> + 'a> {
Box::new(InlineIter::new(self.syntax.first_child().unwrap().children()))
}
}
impl traits::Link for Link {
type Ast = ConcreteSyntax;
fn uri(&self) -> Cow<str> {
let uri_node = self.syntax.clone().children().nth(1).unwrap();
let uri_text_node = uri_node.first_child().unwrap();
let uri_text_token = uri_text_node.first_token().unwrap();
let text = uri_text_token.text();
Cow::Owned(text.to_string())
}
}
impl TryFrom<SyntaxNode> for Link {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeLink => Ok(Self { syntax }),
_ => Err(()),
}
}
}
impl Link {
pub fn to_owned_ast(&self) -> owned::Link {
use traits::Link;
let children: Vec<owned::Inline> = self.children().map(|c| Inline::to_owned_ast(&c)).collect();
let uri = self.uri();
owned::Link {
loc: (),
children,
uri: uri.to_string(),
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Strikethrough {
syntax: SyntaxNode,
}
impl traits::InlineContainer for Strikethrough {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Inline>> + 'a> {
Box::new(InlineIter::new(self.syntax.first_child().unwrap().children()))
}
}
impl traits::Strikethrough for Strikethrough {
type Ast = ConcreteSyntax;
}
impl TryFrom<SyntaxNode> for Strikethrough {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeStrikethrough => Ok(Strikethrough { syntax }),
_ => Err(()),
}
}
}
impl Strikethrough {
pub fn to_owned_ast(&self) -> owned::Strikethrough {
let children: Vec<owned::Inline> = self.children().map(|c| Inline::to_owned_ast(&c)).collect();
owned::Strikethrough { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Strong {
syntax: SyntaxNode,
}
impl traits::InlineContainer for Strong {
type Ast = ConcreteSyntax;
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = traits::MaybeOwned<'a, Inline>> + 'a> {
Box::new(InlineIter::new(self.syntax.first_child().unwrap().children()))
}
}
impl traits::Strong for Strong {
type Ast = ConcreteSyntax;
}
impl TryFrom<SyntaxNode> for Strong {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeStrong => Ok(Strong { syntax }),
_ => Err(()),
}
}
}
impl Strong {
pub fn to_owned_ast(&self) -> owned::Strong {
let children: Vec<owned::Inline> = self.children().map(|c| Inline::to_owned_ast(&c)).collect();
owned::Strong { loc: (), children }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Newline {
syntax: SyntaxNode,
}
impl traits::Newline for Newline {}
impl TryFrom<SyntaxNode> for Newline {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeNewline => Ok(Newline { syntax }),
_ => Err(()),
}
}
}
impl Newline {
pub fn to_owned_ast(&self) -> owned::Newline {
owned::Newline { loc: () }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Text {
syntax: SyntaxNode,
}
impl traits::Text for Text {
type Ast = ConcreteSyntax;
fn text(&self) -> Cow<str> {
let mut text: String = String::new();
for elem in self.syntax.children_with_tokens() {
if elem.kind() == SyntaxKind::TokenText {
text += &elem.to_string();
}
}
Cow::Owned(text)
}
}
impl TryFrom<SyntaxNode> for Text {
type Error = ();
fn try_from(syntax: SyntaxNode) -> Result<Self, Self::Error> {
match syntax.kind() {
SyntaxKind::NodeText => Ok(Text { syntax }),
_ => Err(()),
}
}
}
impl Text {
pub fn to_owned_ast(&self) -> owned::Text {
use traits::Text;
let text = self.text();
owned::Text {
loc: (),
text: text.to_string(),
}
}
}