Skip to content

Commit 6a75f4a

Browse files
committed
(fix) functions
1 parent 6493347 commit 6a75f4a

File tree

5 files changed

+145
-105
lines changed

5 files changed

+145
-105
lines changed

src/parser/parse_content.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ pub fn parse_block(
4343
current: &mut Node,
4444
) -> Result<(), CompileError> {
4545
tokens.next().map_or(Ok(()), |token| {
46-
println!("token = {token}\t\tCurrent = {current}");
4746
let (value, location) = token.into_value_location();
4847
match value {
4948
TokenValue::Char(ch) => {

src/parser/symbols/blocks.rs

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub enum TodoBlock {
2424
SemiColon,
2525
}
2626

27+
/// Manages recursions calls and creates blocks
2728
pub fn blocks_handler(
2829
current: &mut Node,
2930
tokens: &mut IntoIter<Token>,
@@ -34,18 +35,7 @@ pub fn blocks_handler(
3435
match block_state {
3536
// semi-colon
3637
TodoBlock::SemiColon => {
37-
if let Node::Block(Block { elts, full }) = current
38-
&& !*full
39-
{
40-
elts.push(Node::Empty);
41-
} else if *current != Node::Empty {
42-
*current = Node::Block(Block {
43-
elts: vec![mem::take(current), Node::Empty],
44-
full: false,
45-
});
46-
} else {
47-
/* last is empty: nothing to be done */
48-
}
38+
handle_colon(current);
4939
parse_block(tokens, p_state, current)
5040
}
5141
// parenthesis
@@ -89,7 +79,7 @@ pub fn blocks_handler(
8979
// brace
9080
TodoBlock::CloseBraceBlock
9181
if current
92-
.edit_list_initialiser(&|_, full| *full = true)
82+
.apply_to_last_list_initialiser(&|_, full| *full = true)
9383
.is_err() =>
9484
{
9585
p_state.opened_blocks.push(BlockState::Brace);
@@ -105,27 +95,7 @@ pub fn blocks_handler(
10595
.map_err(|err| location.into_error(err))?;
10696
parse_block(tokens, p_state, current)
10797
}
108-
Ok(false) => {
109-
let mut brace_block = Node::Empty;
110-
parse_block(tokens, p_state, &mut brace_block)?;
111-
if p_state.opened_blocks.pop() == Some(BlockState::Brace) {
112-
if let Node::Block(Block { elts, full }) = current
113-
&& !*full
114-
{
115-
elts.push(brace_block);
116-
} else if *current == Node::Empty {
117-
*current = brace_block;
118-
} else {
119-
*current = Node::Block(Block {
120-
elts: vec![mem::take(current), brace_block],
121-
full: false,
122-
});
123-
}
124-
parse_block(tokens, p_state, current)
125-
} else {
126-
Err(location.into_error(mismatched_err('{', '}')))
127-
}
128-
}
98+
Ok(false) => handle_brace_block_open(current, tokens, p_state, location),
12999
},
130100
// others
131101
TodoBlock::None
@@ -135,6 +105,53 @@ pub fn blocks_handler(
135105
}
136106
}
137107

108+
fn handle_brace_block_open(
109+
current: &mut Node,
110+
tokens: &mut IntoIter<Token>,
111+
p_state: &mut ParsingState,
112+
location: Location,
113+
) -> Result<(), CompileError> {
114+
let mut brace_block = Node::Block(Block::default());
115+
parse_block(tokens, p_state, &mut brace_block)?;
116+
if p_state.opened_blocks.pop() != Some(BlockState::Brace) {
117+
return Err(location.into_error(mismatched_err('{', '}')));
118+
}
119+
if let Node::Block(Block { full, .. }) = &mut brace_block {
120+
*full = true;
121+
} else {
122+
panic!("a block can't be changed to another node")
123+
}
124+
//
125+
if let Node::Block(Block { elts, full }) = current
126+
&& !*full
127+
{
128+
elts.push(brace_block);
129+
} else if *current == Node::Empty {
130+
*current = brace_block;
131+
} else {
132+
*current = Node::Block(Block {
133+
elts: vec![mem::take(current), brace_block],
134+
full: false,
135+
});
136+
}
137+
parse_block(tokens, p_state, current)
138+
}
139+
140+
fn handle_colon(current: &mut Node) {
141+
if let Node::Block(Block { elts, full }) = current
142+
&& !*full
143+
{
144+
elts.push(Node::Empty);
145+
} else if *current != Node::Empty {
146+
*current = Node::Block(Block {
147+
elts: vec![mem::take(current), Node::Empty],
148+
full: false,
149+
});
150+
} else {
151+
/* last is empty: nothing to be done */
152+
}
153+
}
154+
138155
fn mismatched_err(open: char, close: char) -> String {
139156
format!(
140157
"Mismatched {open}: You either forgot a closing {close} or there is an extra semi-colon."

src/parser/symbols/handlers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::super::tree::unary::UnaryOperator;
44

55
pub fn handle_comma(current: &mut Node) -> Result<(), String> {
66
if current
7-
.edit_list_initialiser(&|vec, _| vec.push(Node::Empty))
7+
.apply_to_last_list_initialiser(&|vec, _| vec.push(Node::Empty))
88
.is_err()
99
{
1010
current.push_op(BinaryOperator::Comma)?;

src/parser/tree/node.rs

Lines changed: 90 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,68 @@ pub enum Node {
3131
}
3232

3333
impl Node {
34+
/// Applies a closure to the current [`ListInitialiser`].
35+
///
36+
/// It applies the closure somewhere in the [`Node`]. If this closure
37+
/// returns a value, it is returns in `Ok(_)`. If no list initialiser is
38+
/// found, `Err(())` is returned.
39+
///
40+
/// In the case of nested [`ListInitialiser`]s, the closure is applied to
41+
/// the one closest from the leaves.
42+
#[allow(clippy::min_ident_chars)]
43+
pub fn apply_to_last_list_initialiser<T, F: Fn(&mut Vec<Self>, &mut bool) -> T>(
44+
&mut self,
45+
f: &F,
46+
) -> Result<T, ()> {
47+
match self {
48+
//
49+
//
50+
// success
51+
Self::ListInitialiser(ListInitialiser {
52+
elts,
53+
full: full @ false,
54+
}) => {
55+
if let Some(last) = elts.last_mut() {
56+
if let res @ Ok(_) = last.apply_to_last_list_initialiser(f) {
57+
return res;
58+
}
59+
}
60+
Ok(f(elts, full))
61+
}
62+
//
63+
//
64+
// failure
65+
// atomic
66+
Self::Empty
67+
| Self::Leaf(_)
68+
| Self::ParensBlock(_)
69+
// child is none
70+
| Self::Unary(Unary{arg:None, ..})
71+
| Self::Binary(Binary{arg_r:None, ..})
72+
// full lists
73+
| Self::Block(Block{full: true, ..})
74+
| Self::FunctionCall(FunctionCall{full: true, ..})
75+
| Self::ListInitialiser(ListInitialiser{full: true, ..}) => Err(()),
76+
//
77+
//
78+
// recurse
79+
Self::Unary(Unary { arg: Some(arg), .. })
80+
| Self::Binary(Binary { arg_r: Some(arg), .. })
81+
| Self::Ternary(Ternary { failure: Some(arg), .. } | Ternary { condition: arg, .. }) => {
82+
arg.apply_to_last_list_initialiser(f)
83+
}
84+
//
85+
//
86+
// try recurse on non-full lists
87+
Self::FunctionCall(FunctionCall {
88+
full: false, args: vec, ..
89+
})
90+
| Self::Block(Block { elts: vec, full: false }) => vec
91+
.last_mut()
92+
.map_or(Err(()), |node| node.apply_to_last_list_initialiser(f)),
93+
}
94+
}
95+
3496
/// Checks if a `{` is meant as a [`ListInitialiser`] or as a [`Block`].
3597
///
3698
/// # Returns
@@ -90,73 +152,11 @@ impl Node {
90152
Self::Block(Block { elts: vec, full: false })
91153
| Self::FunctionCall(FunctionCall { args: vec, full: false, .. })
92154
| Self::ListInitialiser(ListInitialiser { elts: vec, full: false }) => {
93-
vec.last().map_or_else(|| Ok(false), Self::can_push_list_initialiser)
155+
vec.last().map_or( Ok(false), Self::can_push_list_initialiser)
94156
}
95157
}
96158
}
97159

98-
/// Applies a closure to the current [`ListInitialiser`].
99-
///
100-
/// It applies the closure somewhere in the [`Node`]. If this closure
101-
/// returns a value, it is returns in `Ok(_)`. If no list initialiser is
102-
/// found, `Err(())` is returned.
103-
///
104-
/// In the case of nested [`ListInitialiser`]s, the closure is applied to
105-
/// the one closest from the leaves.
106-
#[allow(clippy::min_ident_chars)]
107-
pub fn edit_list_initialiser<T, F: Fn(&mut Vec<Self>, &mut bool) -> T>(
108-
&mut self,
109-
f: &F,
110-
) -> Result<T, ()> {
111-
match self {
112-
//
113-
//
114-
// success
115-
Self::ListInitialiser(ListInitialiser {
116-
elts,
117-
full: full @ false,
118-
}) => {
119-
if let Some(last) = elts.last_mut() {
120-
if let res @ Ok(_) = last.edit_list_initialiser(f) {
121-
return res;
122-
}
123-
}
124-
Ok(f(elts, full))
125-
}
126-
//
127-
//
128-
// failure
129-
// atomic
130-
Self::Empty
131-
| Self::Leaf(_)
132-
| Self::ParensBlock(_)
133-
// child is none
134-
| Self::Unary(Unary{arg:None, ..})
135-
| Self::Binary(Binary{arg_r:None, ..})
136-
// full lists
137-
| Self::Block(Block{full: true, ..})
138-
| Self::FunctionCall(FunctionCall{full: true, ..})
139-
| Self::ListInitialiser(ListInitialiser{full: true, ..}) => Err(()),
140-
//
141-
//
142-
// recurse
143-
Self::Unary(Unary { arg: Some(arg), .. })
144-
| Self::Binary(Binary { arg_r: Some(arg), .. })
145-
| Self::Ternary(Ternary { failure: Some(arg), .. } | Ternary { condition: arg, .. }) => {
146-
arg.edit_list_initialiser(f)
147-
}
148-
//
149-
//
150-
// try recurse on non-full lists
151-
Self::FunctionCall(FunctionCall {
152-
full: false, args: vec, ..
153-
})
154-
| Self::Block(Block { elts: vec, full: false }) => vec
155-
.last_mut()
156-
.map_or_else(|| Err(()), |node| node.edit_list_initialiser(f)),
157-
}
158-
}
159-
160160
/// Adds the colon of a [`super::TernaryOperator`].
161161
///
162162
/// This method finds a ternary operator, and changes its reading state to
@@ -205,6 +205,28 @@ impl Node {
205205
}
206206
}
207207

208+
/// Checks if a [`Node`] is pushable
209+
///
210+
/// # Returns
211+
/// - `false` if one child on the right branch is empty
212+
/// - `true` otherwise
213+
fn is_full(&self) -> bool {
214+
match self {
215+
Self::Empty => false,
216+
Self::Leaf(_) | Self::ParensBlock(_) => false,
217+
Self::Unary(Unary { arg, .. })
218+
| Self::Binary(Binary { arg_r: arg, .. })
219+
| Self::Ternary(Ternary { failure: arg, .. }) => {
220+
arg.as_ref().is_some_and(|node| node.is_full())
221+
}
222+
Self::Block(Block { elts: vec, full })
223+
| Self::ListInitialiser(ListInitialiser { full, elts: vec })
224+
| Self::FunctionCall(FunctionCall {
225+
full, args: vec, ..
226+
}) => *full || vec.last().is_some_and(|node| node.is_full()),
227+
}
228+
}
229+
208230
/// Pushes a node at the bottom of the [`Node`].
209231
///
210232
/// This methods consideres `node` as a leaf, and pushes it as a leaf into
@@ -232,7 +254,7 @@ impl Node {
232254
// full: ok, but create a new block
233255
Self::Block(Block { full: true, .. }) => {
234256
*self = Self::Block(Block {
235-
elts: vec![mem::take(self)],
257+
elts: vec![mem::take(self), node],
236258
full: false,
237259
});
238260
Ok(())
@@ -279,10 +301,12 @@ impl Node {
279301
elts: vec,
280302
full: false,
281303
}) => {
282-
if let Some(last) = vec.last_mut() {
304+
if let Some(last) = vec.last_mut()
305+
&& !last.is_full()
306+
{
283307
last.push_block_as_leaf(node)
284308
} else {
285-
*vec = vec![node];
309+
vec.push(node);
286310
Ok(())
287311
}
288312
}

tests/parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn parser_nested_braces() {
7777
c=3;
7878
}
7979
",
80-
"[[(a = 1), (b = 2), \u{2205} ], (c = 3), \u{2205} ]",
80+
"[\u{2205} , \u{2205} , \u{2205} , \u{2205} , [(a = 1), (b = 2), \u{2205} ], (c = 3), \u{2205} ]",
8181
);
8282
}
8383

@@ -87,14 +87,14 @@ fn parser_nested_functions() {
8787
"f(a+b) { g(!x) { a = 1; b = 2; } c = 3;
8888
}
8989
",
90-
"[(f°((a + b))), [(g°((!x))), [(a = 1), (b = 2), (c = 3)], \u{2205} ]]",
90+
"[(f°((a + b))), [(g°((!x))), [(a = 1), (b = 2), \u{2205} ], (c = 3), \u{2205} ]..]",
9191
)
9292
}
9393

9494
#[test]
9595
fn parser_functions() {
9696
test_parser_on_string(
9797
"main() { a = f(b) + d; }c = 3;",
98-
"[(main°()), [(a = ((f°(b)) + d)), \u{2205} ], (c = 3), \u{2205} ]",
98+
"[(main°()), [(a = ((f°(b)) + d)), \u{2205} ], (c = 3), \u{2205} ..]",
9999
)
100100
}

0 commit comments

Comments
 (0)