Skip to content

Commit f071efd

Browse files
committed
(parser) add: control flow support
1 parent 156ede9 commit f071efd

File tree

11 files changed

+208
-82
lines changed

11 files changed

+208
-82
lines changed
Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
use core::fmt;
44

5-
use super::super::Ast;
6-
use super::PushInNode;
5+
use super::super::tree::binary::Binary;
6+
use super::super::tree::blocks::Block;
7+
use super::super::tree::literal::{Literal, Variable};
8+
use super::super::tree::unary::Unary;
9+
use super::super::tree::{FunctionCall, ListInitialiser, Ternary};
10+
use super::Ast;
11+
use super::controlflow::ControlFlow as _;
12+
use super::types::PushInNode;
713
use crate::lexer::api::Keyword;
8-
use crate::parser::tree::binary::Binary;
9-
use crate::parser::tree::blocks::Block;
10-
use crate::parser::tree::literal::{Literal, Variable};
11-
use crate::parser::tree::unary::Unary;
12-
use crate::parser::tree::{FunctionCall, ListInitialiser, Ternary};
1314

1415
macro_rules! define_attribute_keywords {
1516
($($name:ident: $($variant:ident)*,)*) => {
@@ -86,7 +87,7 @@ impl PushInNode for AttributeKeyword {
8687
Ast::ListInitialiser(ListInitialiser { full: true, .. })
8788
| Ast::FunctionCall(FunctionCall { full: true, .. }) => {
8889
return Err(format!(
89-
"Attributes can only be placed before variables, but found {self}"
90+
"Attribute {self} can only be placed before variables, but found {node}"
9091
));
9192
}
9293
Ast::ListInitialiser(ListInitialiser { elts, .. })
@@ -95,6 +96,15 @@ impl PushInNode for AttributeKeyword {
9596
Some(last) => return self.push_in_node(last),
9697
None => elts.push(self.into_node()),
9798
},
99+
Ast::ControlFlow(ctrl) => {
100+
return if let Some(last) = ctrl.last_mut() {
101+
self.push_in_node(last)
102+
} else {
103+
Err(format!(
104+
"Attribute {self} can only be placed before variables, but found {node}"
105+
))
106+
};
107+
}
98108
}
99109
Ok(())
100110
}

src/parser/keyword/controlflow.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#![expect(clippy::arbitrary_source_item_ordering)]
2+
#![allow(
3+
clippy::todo,
4+
unused_variables,
5+
clippy::needless_pass_by_ref_mut,
6+
clippy::needless_pass_by_value,
7+
reason = "not yet implemented"
8+
)]
9+
10+
use super::Ast;
11+
use super::types::PushInNode;
12+
use crate::parser::tree::blocks::Block;
13+
14+
pub trait ControlFlow {
15+
fn is_full(&self) -> bool;
16+
fn last(&self) -> Option<&Ast>;
17+
fn last_mut(&mut self) -> Option<&mut Ast>;
18+
}
19+
20+
macro_rules! define_control_flows {
21+
($($pascal:tt,)*) => {
22+
#[derive(Debug, PartialEq, Eq)]
23+
pub enum ControlFlowKeyword {
24+
$($pascal,)*
25+
}
26+
27+
#[derive(Debug, PartialEq)]
28+
pub enum ControlFlowNode {
29+
$($pascal($pascal),)*
30+
}
31+
32+
33+
impl ControlFlow for ControlFlowNode {
34+
fn is_full(&self) -> bool {
35+
match self {
36+
$(Self::$pascal(val) => val.is_full(),)*
37+
}
38+
}
39+
40+
fn last(&self) -> Option<&Ast> {
41+
match self {
42+
$(Self::$pascal(val) => val.last(),)*
43+
}
44+
}
45+
46+
fn last_mut(&mut self) -> Option<&mut Ast> {
47+
match self {
48+
$(Self::$pascal(val) => val.last_mut(),)*
49+
}
50+
}
51+
}
52+
53+
$(
54+
#[derive(Debug, PartialEq)]
55+
pub struct $pascal {
56+
full: bool,
57+
last: Box<Ast>//TODO: this is fake
58+
}
59+
60+
impl ControlFlow for $pascal {
61+
fn is_full(&self) -> bool {
62+
self.full
63+
}
64+
65+
fn last(&self) -> Option<&Ast> {
66+
if self.full {
67+
None
68+
} else {
69+
Some(&self.last)
70+
}
71+
}
72+
73+
fn last_mut(&mut self) -> Option<&mut Ast> {
74+
if self.full {
75+
None
76+
} else {
77+
Some(&mut self.last)
78+
}
79+
}
80+
81+
82+
}
83+
)*
84+
};
85+
}
86+
87+
define_control_flows! {
88+
// cases & loops
89+
Break,
90+
Case,
91+
Continue,
92+
Default,
93+
Do,
94+
For,
95+
Goto,
96+
Switch,
97+
While,
98+
// condition
99+
Else,
100+
If,
101+
// user defined types
102+
Typedef,
103+
Struct,
104+
Union,
105+
Enum,
106+
//
107+
Return,
108+
}
109+
110+
impl ControlFlowNode {
111+
pub fn push_colon(&mut self) -> Result<(), String> {
112+
todo!()
113+
}
114+
pub fn push_block_as_leaf(&mut self) -> Result<(), String> {
115+
todo!()
116+
}
117+
pub fn push_op<T>(&mut self, op: T) -> Result<(), String> {
118+
todo!()
119+
}
120+
}
121+
122+
pub fn is_in_case_context(node: &Ast) -> bool {
123+
match node {
124+
//
125+
//
126+
// true
127+
Ast::ControlFlow(ControlFlowNode::Case(case)) if !case.is_full() => true,
128+
//
129+
//
130+
// false
131+
// empty
132+
Ast::Empty
133+
| Ast::Leaf(_)
134+
| Ast::ParensBlock(_)
135+
// control flows are not expressions
136+
| Ast::Unary(_)
137+
| Ast::Binary(_)
138+
| Ast::Ternary(_)
139+
| Ast::FunctionCall(_)
140+
| Ast::ListInitialiser(_)
141+
// content is full
142+
| Ast::Block(Block { full: true, .. }) => false,
143+
//
144+
//
145+
// recurse
146+
Ast::Block(Block { elts, full: false }) => elts.last().is_some_and(is_in_case_context),
147+
Ast::ControlFlow(ctrl ) => ctrl.last().is_some_and(is_in_case_context),
148+
}
149+
}
150+
151+
impl PushInNode for ControlFlowKeyword {
152+
fn push_in_node(self, node: &mut Ast) -> Result<(), String> {
153+
todo!()
154+
}
155+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::fmt;
22

3-
use super::super::Ast;
4-
use super::PushInNode;
3+
use super::Ast;
4+
use super::types::PushInNode;
55
use crate::parser::tree::literal::{Literal, Variable};
66

77
#[derive(Debug, PartialEq, Eq)]

src/parser/keyword/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
extern crate alloc;
2+
pub mod attributes;
3+
pub mod controlflow;
4+
pub mod functions;
25
pub mod types;
36

47
use alloc::vec::IntoIter;
58

6-
use types::controlflow::ControlFlowKeyword;
9+
use controlflow::is_in_case_context;
710
use types::{KeywordParsing, PushInNode as _};
811

912
use super::parse_content::parse_block;
@@ -21,7 +24,7 @@ pub fn handle_keyword(
2124
tokens: &mut IntoIter<Token>,
2225
location: Location,
2326
) -> Result<(), CompileError> {
24-
let case_context = ControlFlowKeyword::is_in_case_context(current);
27+
let case_context = is_in_case_context(current);
2528
let parsed_keyword = KeywordParsing::from((keyword, case_context));
2629
parsed_keyword
2730
.push_in_node(current)
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
1-
#![allow(
2-
dead_code,
3-
unused_variables,
4-
clippy::todo,
5-
reason = "not yet implemented"
6-
)]
7-
8-
pub mod attributes;
9-
pub mod controlflow;
10-
pub mod functions;
11-
12-
use attributes::{AttributeKeyword as Attr, UnsortedAttributeKeyword as UnsortedAttr};
13-
use controlflow::ControlFlowKeyword as CtrlFlow;
14-
use functions::FunctionKeyword as Func;
15-
161
use super::super::tree::ast::Ast;
2+
use super::attributes::{AttributeKeyword as Attr, UnsortedAttributeKeyword as UnsortedAttr};
3+
use super::controlflow::ControlFlowKeyword as CtrlFlow;
4+
use super::functions::FunctionKeyword as Func;
175
use crate::lexer::api::Keyword;
186
use crate::parser::tree::literal::Literal;
197

src/parser/keyword/types/controlflow.rs

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/parser/symbols/handlers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub fn handle_colon(current: &mut Ast) -> Result<(), String> {
6666
elts: vec,
6767
full: false,
6868
}) => handle_colon(vec.last_mut().expect("Created with one elt")),
69+
Ast::ControlFlow(ctrl) => ctrl.push_colon(),
6970
}
7071
}
7172

0 commit comments

Comments
 (0)