Compare commits
No commits in common. "59f92e31fe31f1e018ab29596a738f46d0b909d9" and "6a233e978fcfdfb37c75597dc3c9ca3fd59550d5" have entirely different histories.
59f92e31fe
...
6a233e978f
9 changed files with 10 additions and 276 deletions
|
|
@ -264,32 +264,16 @@ fn parse_interpolation<'input>(
|
||||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||||
let expr_parser = resume_after_cut(
|
let expr_parser = resume_after_cut(
|
||||||
parse_value_expression,
|
parse_value_expression,
|
||||||
repeat_till(
|
repeat_till(0.., any, peek(TokenKind::RightDelim)).map(|((), _)| ()),
|
||||||
0..,
|
|
||||||
any,
|
|
||||||
peek(preceded(
|
|
||||||
opt(TokenKind::TrimWhitespace),
|
|
||||||
TokenKind::RightDelim,
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
.map(|((), _)| ()),
|
|
||||||
)
|
)
|
||||||
.with_taken()
|
.with_taken()
|
||||||
.map(|(expr, taken)| expr.unwrap_or(TemplateAstExpr::Invalid(taken)));
|
.map(|(expr, taken)| expr.unwrap_or(TemplateAstExpr::Invalid(taken)));
|
||||||
let (
|
let (prev_whitespace, _left, _wants_output, (expression, _right, post_whitespace)) = (
|
||||||
prev_whitespace,
|
|
||||||
_left,
|
|
||||||
left_trim,
|
|
||||||
_wants_output,
|
|
||||||
(expression, right_trim, _right, post_whitespace),
|
|
||||||
) = (
|
|
||||||
opt(TokenKind::Whitespace),
|
opt(TokenKind::Whitespace),
|
||||||
TokenKind::LeftDelim,
|
TokenKind::LeftDelim,
|
||||||
opt(TokenKind::TrimWhitespace),
|
|
||||||
TokenKind::WantsOutput,
|
TokenKind::WantsOutput,
|
||||||
cut_err((
|
cut_err((
|
||||||
surrounded(ws, expr_parser).map(Box::new),
|
surrounded(ws, expr_parser).map(Box::new),
|
||||||
opt(TokenKind::TrimWhitespace),
|
|
||||||
TokenKind::RightDelim,
|
TokenKind::RightDelim,
|
||||||
opt(TokenKind::Whitespace),
|
opt(TokenKind::Whitespace),
|
||||||
)),
|
)),
|
||||||
|
|
@ -297,17 +281,9 @@ fn parse_interpolation<'input>(
|
||||||
.parse_next(input)?;
|
.parse_next(input)?;
|
||||||
|
|
||||||
Ok(TemplateAstExpr::Interpolation {
|
Ok(TemplateAstExpr::Interpolation {
|
||||||
prev_whitespace_content: if left_trim.is_some() {
|
prev_whitespace_content: prev_whitespace,
|
||||||
None
|
|
||||||
} else {
|
|
||||||
prev_whitespace
|
|
||||||
},
|
|
||||||
expression,
|
expression,
|
||||||
post_whitespace_content: if right_trim.is_some() {
|
post_whitespace_content: post_whitespace,
|
||||||
None
|
|
||||||
} else {
|
|
||||||
post_whitespace
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,35 +439,19 @@ where
|
||||||
(
|
(
|
||||||
opt(TokenKind::Whitespace),
|
opt(TokenKind::Whitespace),
|
||||||
TokenKind::LeftDelim,
|
TokenKind::LeftDelim,
|
||||||
opt(TokenKind::TrimWhitespace),
|
|
||||||
not(TokenKind::WantsOutput),
|
not(TokenKind::WantsOutput),
|
||||||
(
|
(
|
||||||
surrounded(ws, expr_parser.map(Box::new)),
|
surrounded(ws, expr_parser.map(Box::new)),
|
||||||
opt(TokenKind::TrimWhitespace),
|
|
||||||
TokenKind::RightDelim,
|
TokenKind::RightDelim,
|
||||||
opt(TokenKind::Whitespace),
|
opt(TokenKind::Whitespace),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map(
|
.map(
|
||||||
|(
|
|(prev_whitespace, _left, _not_token, (expression, _right, post_whitespace))| {
|
||||||
prev_whitespace,
|
|
||||||
_left,
|
|
||||||
left_trim,
|
|
||||||
_not_token,
|
|
||||||
(expression, right_trim, _right, post_whitespace),
|
|
||||||
)| {
|
|
||||||
TemplateAstExpr::Block {
|
TemplateAstExpr::Block {
|
||||||
prev_whitespace_content: if left_trim.is_some() {
|
prev_whitespace_content: prev_whitespace,
|
||||||
None
|
|
||||||
} else {
|
|
||||||
prev_whitespace
|
|
||||||
},
|
|
||||||
expression,
|
expression,
|
||||||
post_whitespace_content: if right_trim.is_some() {
|
post_whitespace_content: post_whitespace,
|
||||||
None
|
|
||||||
} else {
|
|
||||||
post_whitespace
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -776,15 +736,4 @@ mod tests {
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(ast);
|
insta::assert_debug_snapshot!(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_trim_whitespace() {
|
|
||||||
let input = "{{ if foo -}} foo {{- else if bar -}} bar {{- end }}";
|
|
||||||
|
|
||||||
let parsed = crate::parser::parse(input.into()).unwrap();
|
|
||||||
|
|
||||||
let ast = panic_pretty(input, parse(parsed.tokens()));
|
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(ast);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
---
|
|
||||||
source: src/ast/mod.rs
|
|
||||||
expression: ast
|
|
||||||
---
|
|
||||||
TemplateAst {
|
|
||||||
root: [
|
|
||||||
ConditionalChain {
|
|
||||||
chain: [
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: IfConditional {
|
|
||||||
expression: VariableAccess(
|
|
||||||
[Ident]"foo" (6..9),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"foo" (14..17),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: ElseConditional {
|
|
||||||
expression: Some(
|
|
||||||
VariableAccess(
|
|
||||||
[Ident]"bar" (30..33),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"bar" (38..41),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: EndBlock,
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -53,12 +53,11 @@ pub fn execute(
|
||||||
Instruction::PushScope { inherit_parent: _ } => todo!(),
|
Instruction::PushScope { inherit_parent: _ } => todo!(),
|
||||||
Instruction::Abort => return Err(EvaluationError::ExplicitAbort),
|
Instruction::Abort => return Err(EvaluationError::ExplicitAbort),
|
||||||
Instruction::JumpIfNotTrue { emit_slot, jump } => {
|
Instruction::JumpIfNotTrue { emit_slot, jump } => {
|
||||||
let jump = if *jump == 0 { 1 } else { *jump };
|
|
||||||
let dont_jump = scopes.get(emit_slot).unwrap().as_bool().unwrap();
|
let dont_jump = scopes.get(emit_slot).unwrap().as_bool().unwrap();
|
||||||
if dont_jump {
|
if dont_jump {
|
||||||
// We are done
|
// We are done
|
||||||
} else {
|
} else {
|
||||||
let (new_ip, overflow) = ip.overflowing_add_signed(jump);
|
let (new_ip, overflow) = ip.overflowing_add_signed(*jump);
|
||||||
|
|
||||||
if overflow {
|
if overflow {
|
||||||
return Err(EvaluationError::InstructionPointerOverflow);
|
return Err(EvaluationError::InstructionPointerOverflow);
|
||||||
|
|
@ -69,8 +68,7 @@ pub fn execute(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instruction::Jump { jump } => {
|
Instruction::Jump { jump } => {
|
||||||
let jump = if *jump == 0 { 1 } else { *jump };
|
let (new_ip, overflow) = ip.overflowing_add_signed(*jump);
|
||||||
let (new_ip, overflow) = ip.overflowing_add_signed(jump);
|
|
||||||
|
|
||||||
if overflow {
|
if overflow {
|
||||||
return Err(EvaluationError::InstructionPointerOverflow);
|
return Err(EvaluationError::InstructionPointerOverflow);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ use winnow::combinator::eof;
|
||||||
use winnow::combinator::not;
|
use winnow::combinator::not;
|
||||||
use winnow::combinator::opt;
|
use winnow::combinator::opt;
|
||||||
use winnow::combinator::peek;
|
use winnow::combinator::peek;
|
||||||
use winnow::combinator::preceded;
|
|
||||||
use winnow::combinator::repeat_till;
|
use winnow::combinator::repeat_till;
|
||||||
use winnow::combinator::terminated;
|
use winnow::combinator::terminated;
|
||||||
use winnow::combinator::trace;
|
use winnow::combinator::trace;
|
||||||
|
|
@ -202,7 +201,6 @@ pub enum TokenKind {
|
||||||
Content,
|
Content,
|
||||||
LeftDelim,
|
LeftDelim,
|
||||||
RightDelim,
|
RightDelim,
|
||||||
TrimWhitespace,
|
|
||||||
WantsOutput,
|
WantsOutput,
|
||||||
Ident,
|
Ident,
|
||||||
Whitespace,
|
Whitespace,
|
||||||
|
|
@ -288,7 +286,6 @@ impl TemplateToken {
|
||||||
content => TokenKind::Content,
|
content => TokenKind::Content,
|
||||||
left_delim => TokenKind::LeftDelim,
|
left_delim => TokenKind::LeftDelim,
|
||||||
right_delim => TokenKind::RightDelim,
|
right_delim => TokenKind::RightDelim,
|
||||||
trim_whitespace => TokenKind::TrimWhitespace,
|
|
||||||
wants_output => TokenKind::WantsOutput,
|
wants_output => TokenKind::WantsOutput,
|
||||||
ident => TokenKind::Ident,
|
ident => TokenKind::Ident,
|
||||||
whitespace => TokenKind::Whitespace,
|
whitespace => TokenKind::Whitespace,
|
||||||
|
|
@ -347,10 +344,9 @@ fn parse_content<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<Templ
|
||||||
fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
|
fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
|
||||||
let prev_whitespace = opt(parse_whitespace).parse_next(input)?;
|
let prev_whitespace = opt(parse_whitespace).parse_next(input)?;
|
||||||
let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?;
|
let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?;
|
||||||
let left_trim = opt("-".map(TemplateToken::trim_whitespace)).parse_next(input)?;
|
|
||||||
let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?;
|
let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?;
|
||||||
|
|
||||||
let get_tokens = repeat_till(1.., parse_block_token, peek(preceded(opt("-"), "}}")));
|
let get_tokens = repeat_till(1.., parse_block_token, peek("}}"));
|
||||||
let recover = take_until(0.., "}}").void();
|
let recover = take_until(0.., "}}").void();
|
||||||
|
|
||||||
let (inside_tokens, _): (Vec<_>, _) = get_tokens
|
let (inside_tokens, _): (Vec<_>, _) = get_tokens
|
||||||
|
|
@ -361,17 +357,14 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
|
||||||
})
|
})
|
||||||
.parse_next(input)?;
|
.parse_next(input)?;
|
||||||
|
|
||||||
let right_trim = opt("-".map(TemplateToken::trim_whitespace)).parse_next(input)?;
|
|
||||||
let right_delim = "}}".map(TemplateToken::right_delim).parse_next(input)?;
|
let right_delim = "}}".map(TemplateToken::right_delim).parse_next(input)?;
|
||||||
let post_whitespace = opt(parse_whitespace).parse_next(input)?;
|
let post_whitespace = opt(parse_whitespace).parse_next(input)?;
|
||||||
|
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
tokens.extend(prev_whitespace);
|
tokens.extend(prev_whitespace);
|
||||||
tokens.push(left_delim);
|
tokens.push(left_delim);
|
||||||
tokens.extend(left_trim);
|
|
||||||
tokens.extend(wants_output);
|
tokens.extend(wants_output);
|
||||||
tokens.extend(inside_tokens);
|
tokens.extend(inside_tokens);
|
||||||
tokens.extend(right_trim);
|
|
||||||
tokens.push(right_delim);
|
tokens.push(right_delim);
|
||||||
tokens.extend(post_whitespace);
|
tokens.extend(post_whitespace);
|
||||||
|
|
||||||
|
|
@ -602,29 +595,4 @@ mod tests {
|
||||||
)
|
)
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_trim_whitespace() {
|
|
||||||
let input = "\n\n{{-= hello -}} \n\n";
|
|
||||||
let output = parse(input.into());
|
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(output, @r#"
|
|
||||||
Ok(
|
|
||||||
ParsedTemplate {
|
|
||||||
tokens: [
|
|
||||||
[Whitespace]"\n\n" (0..2),
|
|
||||||
[LeftDelim]"{{" (2..4),
|
|
||||||
[TrimWhitespace]"-" (4..5),
|
|
||||||
[WantsOutput]"=" (5..6),
|
|
||||||
[Whitespace]" " (6..7),
|
|
||||||
[Ident]"hello" (7..12),
|
|
||||||
[Whitespace]" " (12..13),
|
|
||||||
[TrimWhitespace]"-" (13..14),
|
|
||||||
[RightDelim]"}}" (14..16),
|
|
||||||
[Whitespace]" \n\n" (16..19),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
"#);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: parsed
|
|
||||||
input_file: tests/cases/trim_whitespace.nomo
|
|
||||||
---
|
|
||||||
ParsedTemplate {
|
|
||||||
tokens: [
|
|
||||||
[LeftDelim]"{{" (0..2),
|
|
||||||
[Whitespace]" " (2..3),
|
|
||||||
[ConditionalIf]"if" (3..5),
|
|
||||||
[Whitespace]" " (5..6),
|
|
||||||
[Ident]"test" (6..10),
|
|
||||||
[Whitespace]" " (10..11),
|
|
||||||
[TrimWhitespace]"-" (11..12),
|
|
||||||
[RightDelim]"}}" (12..14),
|
|
||||||
[Whitespace]"\n " (14..19),
|
|
||||||
[Content]"Hello" (19..24),
|
|
||||||
[Whitespace]" " (24..25),
|
|
||||||
[LeftDelim]"{{" (25..27),
|
|
||||||
[WantsOutput]"=" (27..28),
|
|
||||||
[Whitespace]" " (28..29),
|
|
||||||
[Ident]"stuff" (29..34),
|
|
||||||
[Whitespace]" " (34..35),
|
|
||||||
[TrimWhitespace]"-" (35..36),
|
|
||||||
[RightDelim]"}}" (36..38),
|
|
||||||
[Whitespace]"\n" (38..39),
|
|
||||||
[LeftDelim]"{{" (39..41),
|
|
||||||
[TrimWhitespace]"-" (41..42),
|
|
||||||
[Whitespace]" " (42..43),
|
|
||||||
[End]"end" (43..46),
|
|
||||||
[Whitespace]" " (46..47),
|
|
||||||
[RightDelim]"}}" (47..49),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: ast
|
|
||||||
input_file: tests/cases/trim_whitespace.nomo
|
|
||||||
---
|
|
||||||
TemplateAst {
|
|
||||||
root: [
|
|
||||||
ConditionalChain {
|
|
||||||
chain: [
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: IfConditional {
|
|
||||||
expression: VariableAccess(
|
|
||||||
[Ident]"test" (6..10),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
ConditionalContent {
|
|
||||||
content: [
|
|
||||||
StaticContent(
|
|
||||||
[Content]"Hello" (19..24),
|
|
||||||
),
|
|
||||||
Interpolation {
|
|
||||||
prev_whitespace_content: Some(
|
|
||||||
[Whitespace]" " (24..25),
|
|
||||||
),
|
|
||||||
expression: VariableAccess(
|
|
||||||
[Ident]"stuff" (29..34),
|
|
||||||
),
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Block {
|
|
||||||
prev_whitespace_content: None,
|
|
||||||
expression: EndBlock,
|
|
||||||
post_whitespace_content: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: emit
|
|
||||||
input_file: tests/cases/trim_whitespace.nomo
|
|
||||||
---
|
|
||||||
[
|
|
||||||
LoadFromContextToSlot {
|
|
||||||
name: "test" (6..10),
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
JumpIfNotTrue {
|
|
||||||
emit_slot: VariableSlot {
|
|
||||||
index: 0,
|
|
||||||
},
|
|
||||||
jump: 5,
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: "Hello" (19..24),
|
|
||||||
},
|
|
||||||
AppendContent {
|
|
||||||
content: " " (24..25),
|
|
||||||
},
|
|
||||||
LoadFromContextToSlot {
|
|
||||||
name: "stuff" (29..34),
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
EmitFromSlot {
|
|
||||||
slot: VariableSlot {
|
|
||||||
index: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Jump {
|
|
||||||
jump: 0,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
source: tests/file_tests.rs
|
|
||||||
expression: output
|
|
||||||
input_file: tests/cases/trim_whitespace.nomo
|
|
||||||
---
|
|
||||||
"Hello Hemera"
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"test": true,
|
|
||||||
"stuff": "Hemera"
|
|
||||||
}
|
|
||||||
---
|
|
||||||
{{ if test -}}
|
|
||||||
Hello {{= stuff -}}
|
|
||||||
{{- end }}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue