Add parsing of operations
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
474324726a
commit
09ae91c393
1 changed files with 104 additions and 1 deletions
|
|
@ -12,7 +12,10 @@ use winnow::ascii::multispace0;
|
||||||
use winnow::ascii::multispace1;
|
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::dispatch;
|
||||||
|
use winnow::combinator::empty;
|
||||||
use winnow::combinator::eof;
|
use winnow::combinator::eof;
|
||||||
|
use winnow::combinator::fail;
|
||||||
use winnow::combinator::not;
|
use winnow::combinator::not;
|
||||||
use winnow::combinator::opt;
|
use winnow::combinator::opt;
|
||||||
use winnow::combinator::peek;
|
use winnow::combinator::peek;
|
||||||
|
|
@ -213,6 +216,17 @@ pub enum TokenKind {
|
||||||
In,
|
In,
|
||||||
End,
|
End,
|
||||||
Literal(TokenLiteral),
|
Literal(TokenLiteral),
|
||||||
|
Operator(TokenOperator),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum TokenOperator {
|
||||||
|
Plus,
|
||||||
|
Minus,
|
||||||
|
Times,
|
||||||
|
Divide,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
|
@ -309,6 +323,13 @@ impl TemplateToken {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn operator(operator: TokenOperator, source: NomoInput) -> Self {
|
||||||
|
TemplateToken {
|
||||||
|
kind: TokenKind::Operator(operator),
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> TokenKind {
|
pub fn kind(&self) -> TokenKind {
|
||||||
self.kind
|
self.kind
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +406,7 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
|
||||||
fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||||
trace(
|
trace(
|
||||||
"parse_block_token",
|
"parse_block_token",
|
||||||
alt((parse_ident, parse_keyword, parse_whitespace)),
|
alt((parse_ident, parse_keyword, parse_whitespace, parse_operator)),
|
||||||
)
|
)
|
||||||
.parse_next(input)
|
.parse_next(input)
|
||||||
}
|
}
|
||||||
|
|
@ -474,6 +495,31 @@ fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateTok
|
||||||
.parse_next(input)
|
.parse_next(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_operator<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
|
||||||
|
let (operator, source) = trace(
|
||||||
|
"operator",
|
||||||
|
dispatch! {any;
|
||||||
|
'+' => empty.value(TokenOperator::Plus),
|
||||||
|
'-' => empty.value(TokenOperator::Minus),
|
||||||
|
'*' => empty.value(TokenOperator::Times),
|
||||||
|
'/' => empty.value(TokenOperator::Divide),
|
||||||
|
'&' => alt((
|
||||||
|
"&".value(TokenOperator::And),
|
||||||
|
cut_err(fail),
|
||||||
|
)),
|
||||||
|
'|' => alt((
|
||||||
|
"|".value(TokenOperator::Or),
|
||||||
|
cut_err(fail),
|
||||||
|
)),
|
||||||
|
_ => fail,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.with_taken()
|
||||||
|
.parse_next(input)?;
|
||||||
|
|
||||||
|
Ok(TemplateToken::operator(operator, source))
|
||||||
|
}
|
||||||
|
|
||||||
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> {
|
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> {
|
||||||
peek(not(parse_keyword))
|
peek(not(parse_keyword))
|
||||||
.context(ParseError::ctx().msg("Expected an ident, but found a literal instead"))
|
.context(ParseError::ctx().msg("Expected an ident, but found a literal instead"))
|
||||||
|
|
@ -680,4 +726,61 @@ mod tests {
|
||||||
)
|
)
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_operations() {
|
||||||
|
let input = "{{= 5 * 4 + 3 / 2 - 1 }}{{ if foo && bar || baz }}{{ end }}";
|
||||||
|
let output = parse(input.into());
|
||||||
|
|
||||||
|
insta::assert_debug_snapshot!(output, @r#"
|
||||||
|
Ok(
|
||||||
|
ParsedTemplate {
|
||||||
|
tokens: [
|
||||||
|
[LeftDelim]"{{" (0..2),
|
||||||
|
[WantsOutput]"=" (2..3),
|
||||||
|
[Whitespace]" " (3..4),
|
||||||
|
[Ident]"5" (4..5),
|
||||||
|
[Whitespace]" " (5..6),
|
||||||
|
[Operator(Times)]"*" (6..7),
|
||||||
|
[Whitespace]" " (7..8),
|
||||||
|
[Ident]"4" (8..9),
|
||||||
|
[Whitespace]" " (9..10),
|
||||||
|
[Operator(Plus)]"+" (10..11),
|
||||||
|
[Whitespace]" " (11..12),
|
||||||
|
[Ident]"3" (12..13),
|
||||||
|
[Whitespace]" " (13..14),
|
||||||
|
[Operator(Divide)]"/" (14..15),
|
||||||
|
[Whitespace]" " (15..16),
|
||||||
|
[Ident]"2" (16..17),
|
||||||
|
[Whitespace]" " (17..18),
|
||||||
|
[Operator(Minus)]"-" (18..19),
|
||||||
|
[Whitespace]" " (19..20),
|
||||||
|
[Ident]"1" (20..21),
|
||||||
|
[Whitespace]" " (21..22),
|
||||||
|
[RightDelim]"}}" (22..24),
|
||||||
|
[LeftDelim]"{{" (24..26),
|
||||||
|
[Whitespace]" " (26..27),
|
||||||
|
[ConditionalIf]"if" (27..29),
|
||||||
|
[Whitespace]" " (29..30),
|
||||||
|
[Ident]"foo" (30..33),
|
||||||
|
[Whitespace]" " (33..34),
|
||||||
|
[Operator(And)]"&&" (34..36),
|
||||||
|
[Whitespace]" " (36..37),
|
||||||
|
[Ident]"bar" (37..40),
|
||||||
|
[Whitespace]" " (40..41),
|
||||||
|
[Operator(Or)]"||" (41..43),
|
||||||
|
[Whitespace]" " (43..44),
|
||||||
|
[Ident]"baz" (44..47),
|
||||||
|
[Whitespace]" " (47..48),
|
||||||
|
[RightDelim]"}}" (48..50),
|
||||||
|
[LeftDelim]"{{" (50..52),
|
||||||
|
[Whitespace]" " (52..53),
|
||||||
|
[End]"end" (53..56),
|
||||||
|
[Whitespace]" " (56..57),
|
||||||
|
[RightDelim]"}}" (57..59),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
"#);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue