1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use nom::{
error::context,
sequence::{delimited, preceded, terminated, tuple},
};
use crate::parser::expression::{parse_expression, Expression};
use crate::parser::literals::sp;
use crate::parser::literals::{parse_variable, Variable};
use crate::parser::statement::{parse_block, Block};
use crate::parser::tokens::{end, ldo, lfor, lin};
use crate::parser::{Res, Span};
#[derive(Debug, PartialEq, Clone)]
pub struct For<'a> {
pub iter_item: Variable<'a>,
pub iterator: Expression<'a>,
pub block: Block<'a>,
}
pub fn parse_for(input: Span) -> Res<For> {
tuple((
parse_iter_item,
parse_iterator,
terminated(parse_block, preceded(sp, end)),
))(input)
.map(|(next_input, res)| {
(
next_input,
For {
iter_item: res.0,
iterator: res.1,
block: res.2,
},
)
})
}
fn parse_iter_item<'a>(input: Span<'a>) -> Res<Variable<'a>> {
context(
"ForIterItem",
preceded(preceded(sp, lfor), preceded(sp, parse_variable)),
)(input)
}
fn parse_iterator(input: Span) -> Res<Expression> {
context(
"ForIterator",
delimited(
preceded(sp, lin),
preceded(sp, parse_expression),
preceded(sp, ldo),
),
)(input)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::literals::Token;
use crate::parser::expression::{ExprOrVarname, Expression, PrefixExpr};
use crate::parser::literals::Literal;
use crate::parser::statement::{Block, LAssignment, Statement};
#[test]
fn test_parse_iter_item() {
let string = "for item in iterator do";
let (_, res) = parse_iter_item(Span::new(string)).unwrap();
assert_eq!(res, Token::new("item", Span::new("item")));
}
#[test]
fn test_parse_iterator() {
let string = " in iterator do";
let (_, res) = parse_iterator(Span::new(string)).unwrap();
assert_eq!(
res,
Expression::PrefixExpr(Box::new(PrefixExpr {
prefix: ExprOrVarname::Varname(Token::new("iterator", Span::new("iterator"))),
suffix_chain: vec![]
}))
);
}
#[test]
fn test_parse_for_loop() {
let string = "\nfor x in y do \n let y = 3 \nend";
let (_, res) = parse_for(Span::new(string)).unwrap();
assert_eq!(
res,
For {
iter_item: Token::new("x", Span::new("x")),
iterator: Expression::PrefixExpr(Box::new(PrefixExpr {
prefix: ExprOrVarname::Varname(Token::new("y", Span::new("y"))),
suffix_chain: vec![]
})),
block: Block {
statements: vec![Statement::LAssignment(LAssignment {
variable: Token::new("y", Span::new("y")),
expression: Expression::Literal(Literal::Int(Token::new(
3,
Span::new("3")
)))
})],
return_stmt: None
}
}
)
}
}