use crate::component::*;
use crate::kw;
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
use crate::token::{Id, Index, LParen, NameAnnotation, Span};
#[derive(Debug)]
pub struct ComponentImport<'a> {
pub span: Span,
pub name: ComponentExternName<'a>,
pub item: ItemSig<'a>,
}
impl<'a> Parse<'a> for ComponentImport<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let span = parser.parse::<kw::import>()?.0;
let name = parser.parse()?;
let item = parser.parens(|p| p.parse())?;
Ok(ComponentImport { span, name, item })
}
}
#[derive(Debug, Copy, Clone)]
pub struct ComponentExternName<'a>(pub &'a str);
impl<'a> Parse<'a> for ComponentExternName<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let name = if parser.peek::<LParen>()? {
parser.parens(|p| {
p.parse::<kw::interface>()?;
p.parse()
})?
} else {
parser.parse()?
};
Ok(ComponentExternName(name))
}
}
#[derive(Debug)]
pub struct ItemSig<'a> {
pub span: Span,
pub id: Option<Id<'a>>,
pub name: Option<NameAnnotation<'a>>,
pub kind: ItemSigKind<'a>,
}
impl<'a> Parse<'a> for ItemSig<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parse_item_sig(parser, true)
}
}
#[derive(Debug)]
pub struct ItemSigNoName<'a>(pub ItemSig<'a>);
impl<'a> Parse<'a> for ItemSigNoName<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ItemSigNoName(parse_item_sig(parser, false)?))
}
}
fn parse_item_sig<'a>(parser: Parser<'a>, name: bool) -> Result<ItemSig<'a>> {
let mut l = parser.lookahead1();
let (span, parse_kind): (_, fn(Parser<'a>) -> Result<ItemSigKind>) = if l.peek::<kw::core>()? {
let span = parser.parse::<kw::core>()?.0;
parser.parse::<kw::module>()?;
(span, |parser| Ok(ItemSigKind::CoreModule(parser.parse()?)))
} else if l.peek::<kw::func>()? {
let span = parser.parse::<kw::func>()?.0;
(span, |parser| Ok(ItemSigKind::Func(parser.parse()?)))
} else if l.peek::<kw::component>()? {
let span = parser.parse::<kw::component>()?.0;
(span, |parser| Ok(ItemSigKind::Component(parser.parse()?)))
} else if l.peek::<kw::instance>()? {
let span = parser.parse::<kw::instance>()?.0;
(span, |parser| Ok(ItemSigKind::Instance(parser.parse()?)))
} else if l.peek::<kw::value>()? {
let span = parser.parse::<kw::value>()?.0;
(span, |parser| Ok(ItemSigKind::Value(parser.parse()?)))
} else if l.peek::<kw::r#type>()? {
let span = parser.parse::<kw::r#type>()?.0;
(span, |parser| {
Ok(ItemSigKind::Type(parser.parens(|parser| parser.parse())?))
})
} else {
return Err(l.error());
};
Ok(ItemSig {
span,
id: if name { parser.parse()? } else { None },
name: if name { parser.parse()? } else { None },
kind: parse_kind(parser)?,
})
}
#[derive(Debug)]
pub enum ItemSigKind<'a> {
CoreModule(CoreTypeUse<'a, ModuleType<'a>>),
Func(ComponentTypeUse<'a, ComponentFunctionType<'a>>),
Component(ComponentTypeUse<'a, ComponentType<'a>>),
Instance(ComponentTypeUse<'a, InstanceType<'a>>),
Value(ComponentValTypeUse<'a>),
Type(TypeBounds<'a>),
}
#[derive(Debug)]
pub enum TypeBounds<'a> {
Eq(Index<'a>),
SubResource,
}
impl<'a> Parse<'a> for TypeBounds<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut l = parser.lookahead1();
if l.peek::<kw::eq>()? {
parser.parse::<kw::eq>()?;
Ok(Self::Eq(parser.parse()?))
} else if l.peek::<kw::sub>()? {
parser.parse::<kw::sub>()?;
parser.parse::<kw::resource>()?;
Ok(Self::SubResource)
} else {
Err(l.error())
}
}
}
#[derive(Debug, Clone)]
pub struct InlineImport<'a> {
pub name: ComponentExternName<'a>,
}
impl<'a> Parse<'a> for InlineImport<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parens(|p| {
p.parse::<kw::import>()?;
Ok(InlineImport { name: p.parse()? })
})
}
}
impl Peek for InlineImport<'_> {
fn peek(cursor: Cursor<'_>) -> Result<bool> {
let cursor = match cursor.lparen()? {
Some(cursor) => cursor,
None => return Ok(false),
};
let cursor = match cursor.keyword()? {
Some(("import", cursor)) => cursor,
_ => return Ok(false),
};
if let Some((_, cursor)) = cursor.string()? {
return Ok(cursor.rparen()?.is_some());
}
let cursor = match cursor.lparen()? {
Some(cursor) => cursor,
None => return Ok(false),
};
let cursor = match cursor.keyword()? {
Some(("interface", cursor)) => cursor,
_ => return Ok(false),
};
let cursor = match cursor.string()? {
Some((_, cursor)) => cursor,
_ => return Ok(false),
};
let cursor = match cursor.rparen()? {
Some(cursor) => cursor,
_ => return Ok(false),
};
Ok(cursor.rparen()?.is_some())
}
fn display() -> &'static str {
"inline import"
}
}