use std::fmt::Display;
use crate::{Span, __internal__parse_with_path};
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct SourceFile<'s> {
pub(crate) templates: Vec<(Template<'s>, Span<'s>)>,
pub(crate) type_defs: Vec<(TypeDefinition<'s>, Span<'s>)>,
}
impl<'s> SourceFile<'s> {
#[must_use]
pub fn into_templates_and_type_defs(
self,
) -> (
impl ExactSizeIterator<Item = Template<'s>>,
impl ExactSizeIterator<Item = (TypeDefinition<'s>, Span<'s>)>,
) {
(
self.templates.into_iter().map(|(tmpl, _)| tmpl),
self.type_defs.into_iter(),
)
}
}
impl<'s> SourceFile<'s> {
pub(crate) fn parse(
path: &'s str,
source: &'s str,
) -> Result<SourceFile<'s>, super::parse::Error<'s>> {
__internal__parse_with_path!(super::parse::source_file::source_file(), path, source)
.into_result()
.map_err(|errors| {
if errors.len() == 1 {
errors.into_iter().next().unwrap()
} else {
super::parse::Error::Multiple(errors)
}
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Template<'s> {
pub(crate) output_type: (Option<&'s str>, Span<'s>),
pub(crate) name: (&'s str, Span<'s>),
pub(crate) parameters: Vec<(TemplateParameterName<'s>, TemplateParameterType<'s>)>,
pub(crate) body: TemplateBody<'s>,
}
pub(crate) type TemplateParameterName<'s> = (&'s str, Span<'s>);
pub(crate) type TemplateParameterType<'s> = (Option<Type<'s>>, Span<'s>);
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct TemplateBody<'s> {
pub(crate) indentation_marker: IndentationMarker<'s>,
pub(crate) lines: Vec<(TemplateLine<'s>, Span<'s>)>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum IndentationMarker<'s> {
None,
Present {
indentation_and_span: (&'s str, Span<'s>),
},
Escaped {
indentation_and_span: (&'s str, Span<'s>),
marker_span: Span<'s>,
newline: (&'s str, Span<'s>),
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) enum Type<'s> {
Ident(&'s str),
Options(Vec<(Type<'s>, Span<'s>)>),
Array((Option<Box<Type<'s>>>, Span<'s>)),
Tuple(Vec<(Type<'s>, Span<'s>)>),
Struct(Vec<(StructEntryName<'s>, StructEntryType<'s>)>),
}
pub(crate) type StructEntryName<'s> = (&'s str, Span<'s>);
pub(crate) type StructEntryType<'s> = (Option<Type<'s>>, Span<'s>);
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct TemplateLine<'s> {
pub had_comments: bool,
pub indentation: (&'s str, Span<'s>),
pub content: Vec<(TemplateContent<'s>, Span<'s>)>,
pub newline: (TemplateLineNewline<'s>, Span<'s>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TemplateLineNewline<'s> {
Normal(&'s str),
Escaped,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum TemplateContent<'s> {
Static(&'s str),
EscapeSequence(TemplateContentEscapeSequence<'s>),
Command(Box<Command<'s>>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum EscapeSequence {
Tab,
Newline,
Backslash,
CarriageReturn,
}
impl EscapeSequence {
pub(crate) fn str(self) -> &'static str {
match self {
EscapeSequence::Tab => "\t",
EscapeSequence::Newline => "\n",
EscapeSequence::Backslash => "\\",
EscapeSequence::CarriageReturn => "\r",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CurlyKind {
Opening,
Closing,
}
impl Display for CurlyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Opening => write!(f, "opening"),
Self::Closing => write!(f, "closing"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum TemplateContentEscapeSequence<'s> {
Normal(EscapeSequence),
Curly(CurlyKind, usize, &'s str, Span<'s>),
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Command<'s> {
Expression(Expression<'s>, Span<'s>),
Assignment {
variable: (&'s str, Span<'s>),
expression: (Expression<'s>, Span<'s>),
},
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Expression<'s> {
Literal(Literal<'s>),
VariableOrCall(&'s str),
Call {
func: (Box<Expression<'s>>, Span<'s>),
arguments: Vec<(Expression<'s>, Span<'s>)>,
},
If {
condition: (Box<Expression<'s>>, Span<'s>),
then_expression: (Box<Expression<'s>>, Span<'s>),
else_expression: Option<(Box<Expression<'s>>, Span<'s>)>,
},
Each {
variable: (&'s str, Span<'s>),
array_expression: (Box<Expression<'s>>, Span<'s>),
body_expression: (Box<Expression<'s>>, Span<'s>),
},
Select {
expr: (Box<Expression<'s>>, Span<'s>),
#[allow(clippy::type_complexity)]
arms: Vec<(
(&'s str, Span<'s>),
(Type<'s>, Span<'s>),
(Expression<'s>, Span<'s>),
)>,
},
MemberAccess {
expression: (Box<Expression<'s>>, Span<'s>),
access: (MemberAccess<'s>, Span<'s>),
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MemberAccess<'s> {
Numeric(u32, Span<'s>),
Named(&'s str, Span<'s>),
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Literal<'s> {
Int(i64),
Float(f64),
Bool(bool),
String(Vec<(StringLiteralComponent<'s>, Span<'s>)>),
Template((Option<&'s str>, Span<'s>), Box<TemplateBody<'s>>),
Tuple(Vec<(Expression<'s>, Span<'s>)>),
Array(Vec<(Expression<'s>, Span<'s>)>),
Struct(Vec<(StructLiteralEntryName<'s>, StructLiteralEntryExpression<'s>)>),
}
pub(crate) type StructLiteralEntryName<'s> = (&'s str, Span<'s>);
pub(crate) type StructLiteralEntryExpression<'s> = (Expression<'s>, Span<'s>);
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum StringLiteralComponent<'s> {
Literal(&'s str),
EscapedQuote,
EscapeSequence(EscapeSequence),
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeDefinition<'s> {
pub(crate) name: (&'s str, Span<'s>),
pub(crate) ty: (Type<'s>, Span<'s>),
}