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
112
113
114
115
116
117
118
119
120
121
122
use crate::parser::expression::parse_expression;
use crate::parser::expression::Expression;
use crate::parser::literals::sp;
use crate::parser::tokens::{end, ldo, lwhile};
use crate::parser::Res;
use crate::Span;
use crate::parser::statement::{parse_block, Block};
use nom::{
error::context,
sequence::{delimited, preceded, terminated, tuple},
};
#[derive(Debug, PartialEq, Clone)]
pub struct While<'a> {
pub cond: Expression<'a>,
pub block: Block<'a>,
}
pub fn parse_while(input: Span) -> Res<While> {
tuple((while_condition, terminated(parse_block, preceded(sp, end))))(input).map(
|(next_input, res)| {
(
next_input,
While {
cond: res.0,
block: res.1,
},
)
},
)
}
fn while_condition(input: Span) -> Res<Expression> {
context(
"WhileCond",
delimited(
preceded(sp, lwhile),
preceded(sp, parse_expression),
preceded(sp, ldo),
),
)(input)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::literals::Token;
use crate::parser::expression::binary::BinaryOp;
use crate::parser::expression::{ExprOrVarname, Expression, PrefixExpr};
use crate::parser::literals::Literal;
use crate::parser::statement::declaration::assignment::LAssignment;
use crate::parser::statement::Statement;
use crate::parser::tokens::Operator;
#[test]
fn parse_while_condition() {
let string = " while x < 3 do";
let (_, res) = while_condition(Span::new(string)).unwrap();
assert_eq!(
res,
Expression::BinaryOp(Box::new(BinaryOp {
op: Operator::Lt,
left: Expression::PrefixExpr(Box::new(PrefixExpr {
prefix: ExprOrVarname::Varname(Token::new("x", Span::new("x"))),
suffix_chain: vec![],
})),
right: Expression::Literal(Literal::Int(Token::new(3, Span::new("3")))),
}))
)
}
#[test]
fn parse_while_statement() {
let string = "while x < 3 do \nlet z = x + 3\n let y = 3 \nend";
let (_, res) = parse_while(Span::new(string)).unwrap();
assert_eq!(
res,
While {
cond: Expression::BinaryOp(Box::new(BinaryOp {
op: Operator::Lt,
left: Expression::PrefixExpr(Box::new(PrefixExpr {
prefix: ExprOrVarname::Varname(Token::new("x", Span::new("x"))),
suffix_chain: vec![],
})),
right: Expression::Literal(Literal::Int(Token::new(3, Span::new("3")))),
})),
block: Block {
statements: vec![
Statement::LAssignment(LAssignment {
variable: Token::new("z", Span::new("z")),
expression: Expression::BinaryOp(Box::new(BinaryOp {
left: Expression::PrefixExpr(Box::new(PrefixExpr {
prefix: ExprOrVarname::Varname(Token::new("x", Span::new("x"))),
suffix_chain: vec![]
})),
op: Operator::Add,
right: Expression::Literal(Literal::Int(Token::new(
3,
Span::new("3")
)))
}))
}),
Statement::LAssignment(LAssignment {
variable: Token::new("y", Span::new("y")),
expression: Expression::Literal(Literal::Int(Token::new(
3,
Span::new("3")
)))
})
],
return_stmt: None
}
}
)
}
}