Add parsing of if/end
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
10a33dc935
commit
d691fb9198
1 changed files with 150 additions and 43 deletions
|
|
@ -13,6 +13,7 @@ use winnow::ascii::multispace1;
|
|||
use winnow::combinator::alt;
|
||||
use winnow::combinator::cut_err;
|
||||
use winnow::combinator::eof;
|
||||
use winnow::combinator::not;
|
||||
use winnow::combinator::opt;
|
||||
use winnow::combinator::peek;
|
||||
use winnow::combinator::repeat_till;
|
||||
|
|
@ -204,6 +205,14 @@ pub enum TokenKind {
|
|||
Ident,
|
||||
Whitespace,
|
||||
Invalid,
|
||||
ConditionalIf,
|
||||
End,
|
||||
Literal(TokenLiteral),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum TokenLiteral {
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl PartialEq<TokenKind> for TemplateToken {
|
||||
|
|
@ -242,52 +251,35 @@ pub struct TemplateToken {
|
|||
source: TempleInput,
|
||||
}
|
||||
|
||||
macro_rules! impl_token_kind_builders {
|
||||
($($name:ident => $kind:expr),+ $(,)?) => {
|
||||
$(
|
||||
fn $name(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: $kind,
|
||||
source,
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl TemplateToken {
|
||||
fn content(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::Content,
|
||||
source,
|
||||
}
|
||||
impl_token_kind_builders! {
|
||||
content => TokenKind::Content,
|
||||
left_delim => TokenKind::LeftDelim,
|
||||
right_delim => TokenKind::RightDelim,
|
||||
wants_output => TokenKind::WantsOutput,
|
||||
ident => TokenKind::Ident,
|
||||
whitespace => TokenKind::Whitespace,
|
||||
invalid => TokenKind::Invalid,
|
||||
conditional_if => TokenKind::ConditionalIf,
|
||||
end => TokenKind::End,
|
||||
}
|
||||
|
||||
fn left_delim(source: TempleInput) -> Self {
|
||||
pub fn literal(literal: TokenLiteral, source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::LeftDelim,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
fn right_delim(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::RightDelim,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
fn wants_output(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::WantsOutput,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
fn ident(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::Ident,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
fn whitespace(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::Whitespace,
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
fn invalid(source: TempleInput) -> Self {
|
||||
TemplateToken {
|
||||
kind: TokenKind::Invalid,
|
||||
kind: TokenKind::Literal(literal),
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
|
@ -364,11 +356,43 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
|
|||
fn parse_interpolate_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||
trace(
|
||||
"parse_interpolate_token",
|
||||
alt((parse_ident, parse_whitespace)),
|
||||
alt((
|
||||
parse_ident,
|
||||
parse_literal,
|
||||
parse_condition,
|
||||
parse_end,
|
||||
parse_whitespace,
|
||||
)),
|
||||
)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_literal<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||
trace(
|
||||
"parse_condition",
|
||||
alt((parse_boolean,))
|
||||
.with_taken()
|
||||
.map(|(lit, span)| TemplateToken::literal(lit, span)),
|
||||
)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> {
|
||||
alt((
|
||||
"true".value(TokenLiteral::Bool(true)),
|
||||
"false".value(TokenLiteral::Bool(false)),
|
||||
))
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_condition<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||
trace("parse_condition", "if".map(TemplateToken::conditional_if)).parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_end<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||
trace("parse_condition", "end".map(TemplateToken::end)).parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||
trace(
|
||||
"parse_whitespace",
|
||||
|
|
@ -396,6 +420,10 @@ fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateTok
|
|||
}
|
||||
|
||||
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, TempleInput> {
|
||||
peek(not(parse_literal))
|
||||
.context(ParseError::ctx().msg("Expected an ident, but found a literal instead"))
|
||||
.parse_next(input)?;
|
||||
|
||||
take_while(1.., |c: char| c.is_alphanumeric() || "_".contains(c)).parse_next(input)
|
||||
}
|
||||
|
||||
|
|
@ -517,4 +545,83 @@ mod tests {
|
|||
|
||||
insta::assert_snapshot!(error.to_report());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_simple_condition() {
|
||||
let input = "{{ if true }} Hello! {{ end }}";
|
||||
let output = parse(input.into());
|
||||
|
||||
insta::assert_debug_snapshot!(output, @r#"
|
||||
Ok(
|
||||
ParsedTemplate {
|
||||
tokens: [
|
||||
TemplateToken {
|
||||
kind: LeftDelim,
|
||||
source: "{{",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Ident,
|
||||
source: "if",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Literal(
|
||||
Bool(
|
||||
true,
|
||||
),
|
||||
),
|
||||
source: "true",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: RightDelim,
|
||||
source: "}}",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Content,
|
||||
source: "Hello!",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: LeftDelim,
|
||||
source: "{{",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Ident,
|
||||
source: "end",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: Whitespace,
|
||||
source: " ",
|
||||
},
|
||||
TemplateToken {
|
||||
kind: RightDelim,
|
||||
source: "}}",
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
"#);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue