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::alt;
|
||||||
use winnow::combinator::cut_err;
|
use winnow::combinator::cut_err;
|
||||||
use winnow::combinator::eof;
|
use winnow::combinator::eof;
|
||||||
|
use winnow::combinator::not;
|
||||||
use winnow::combinator::opt;
|
use winnow::combinator::opt;
|
||||||
use winnow::combinator::peek;
|
use winnow::combinator::peek;
|
||||||
use winnow::combinator::repeat_till;
|
use winnow::combinator::repeat_till;
|
||||||
|
|
@ -204,6 +205,14 @@ pub enum TokenKind {
|
||||||
Ident,
|
Ident,
|
||||||
Whitespace,
|
Whitespace,
|
||||||
Invalid,
|
Invalid,
|
||||||
|
ConditionalIf,
|
||||||
|
End,
|
||||||
|
Literal(TokenLiteral),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum TokenLiteral {
|
||||||
|
Bool(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<TokenKind> for TemplateToken {
|
impl PartialEq<TokenKind> for TemplateToken {
|
||||||
|
|
@ -242,52 +251,35 @@ pub struct TemplateToken {
|
||||||
source: TempleInput,
|
source: TempleInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_token_kind_builders {
|
||||||
|
($($name:ident => $kind:expr),+ $(,)?) => {
|
||||||
|
$(
|
||||||
|
fn $name(source: TempleInput) -> Self {
|
||||||
|
TemplateToken {
|
||||||
|
kind: $kind,
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl TemplateToken {
|
impl TemplateToken {
|
||||||
fn content(source: TempleInput) -> Self {
|
impl_token_kind_builders! {
|
||||||
TemplateToken {
|
content => TokenKind::Content,
|
||||||
kind: TokenKind::Content,
|
left_delim => TokenKind::LeftDelim,
|
||||||
source,
|
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 {
|
TemplateToken {
|
||||||
kind: TokenKind::LeftDelim,
|
kind: TokenKind::Literal(literal),
|
||||||
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,
|
|
||||||
source,
|
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> {
|
fn parse_interpolate_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||||
trace(
|
trace(
|
||||||
"parse_interpolate_token",
|
"parse_interpolate_token",
|
||||||
alt((parse_ident, parse_whitespace)),
|
alt((
|
||||||
|
parse_ident,
|
||||||
|
parse_literal,
|
||||||
|
parse_condition,
|
||||||
|
parse_end,
|
||||||
|
parse_whitespace,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
.parse_next(input)
|
.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> {
|
fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||||
trace(
|
trace(
|
||||||
"parse_whitespace",
|
"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> {
|
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)
|
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());
|
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