Skip to content

Commit e90aba9

Browse files
authored
refactor: organize parser into modular components (#263)
Split the large `parser.rs` file into logical submodules within `front/parser/src/parser/` to improve code structure and maintainability. Changes: - **New Module Structure**: - `asm.rs`: `parse_asm_block` - `control.rs`: `parse_if`, `parse_while`, `parse_for` - `decl.rs`: `parse_variable_decl`, `parse_const`, `parse_let`, `parse_var` - `expr.rs`: `parse_function_call`, `parse_parentheses` - `functions.rs`: `parse_function`, `parse_parameters`, `extract_body` - `io.rs`: `parse_println`, `parse_print`, `parse_input` - `items.rs`: `parse_import`, `parse_proto`, `parse_struct` - `stmt.rs`: `parse_assignment`, `parse_block`, `parse_statement` - `types.rs`: Type parsing logic moved from `type_system.rs` (`parse_type`, `parse_type_from_token`, etc.) - `parse.rs`: Main `parse()` entry point and module declarations. - **Cleanup**: - Removed `type_system.rs` (logic moved to `types.rs`). - Updated `mod.rs` to expose the new structure. - Fixed imports across the crate to point to new module locations. - Resolved unused import warnings in `main.rs` and `runner.rs`. This refactoring decouples parser components, making it easier to navigate and extend individual language features. Signed-off-by: LunaStev <luna@lunastev.org>
1 parent 882e769 commit e90aba9

File tree

22 files changed

+1873
-1829
lines changed

22 files changed

+1873
-1829
lines changed

front/parser/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
pub mod parser;
2+
pub mod ast;
3+
pub mod format;
4+
pub mod import;
5+
pub mod stdlib;
6+
pub mod type_system;
7+
pub mod verification;
28

39
pub use parser::*;

front/parser/src/parser/asm.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use std::iter::Peekable;
2+
use std::slice::Iter;
3+
use lexer::{Token, TokenType};
4+
use crate::ast::{ASTNode, StatementNode};
5+
6+
pub fn parse_asm_block(tokens: &mut Peekable<Iter<Token>>) -> Option<ASTNode> {
7+
if tokens.peek()?.token_type != TokenType::Lbrace {
8+
println!("Expected '{{' after 'asm'");
9+
return None;
10+
}
11+
tokens.next();
12+
13+
let mut instructions = vec![];
14+
let mut inputs = vec![];
15+
let mut outputs = vec![];
16+
17+
while let Some(token) = tokens.next() {
18+
match &token.token_type {
19+
TokenType::Rbrace => break,
20+
21+
TokenType::In | TokenType::Out => {
22+
let is_input = matches!(token.token_type, TokenType::In);
23+
24+
if tokens.next().map(|t| t.token_type.clone()) != Some(TokenType::Lparen) {
25+
println!("Expected '(' after in/out");
26+
return None;
27+
}
28+
29+
let reg_token = tokens.next();
30+
let reg = match reg_token {
31+
Some(Token {
32+
token_type: TokenType::String(s),
33+
..
34+
}) => s.clone(),
35+
Some(Token {
36+
token_type: TokenType::Identifier(s),
37+
..
38+
}) => s.clone(),
39+
Some(other) => {
40+
println!(
41+
"Expected register string or identifier, got {:?}",
42+
other.token_type
43+
);
44+
return None;
45+
}
46+
None => {
47+
println!("Expected register in in/out(...)");
48+
return None;
49+
}
50+
};
51+
52+
if tokens.next().map(|t| t.token_type.clone()) != Some(TokenType::Rparen) {
53+
println!("Expected ')' after in/out");
54+
return None;
55+
}
56+
57+
let value_token = tokens.next();
58+
let value = match value_token {
59+
Some(Token {
60+
token_type: TokenType::Minus,
61+
..
62+
}) => match tokens.next() {
63+
Some(Token {
64+
token_type: TokenType::Number(n),
65+
..
66+
}) => format!("-{}", n),
67+
Some(other) => {
68+
println!("Expected number after '-', got {:?}", other.token_type);
69+
return None;
70+
}
71+
None => {
72+
println!("Expected number after '-'");
73+
return None;
74+
}
75+
},
76+
Some(Token {
77+
token_type: TokenType::AddressOf,
78+
..
79+
}) => match tokens.next() {
80+
Some(Token {
81+
token_type: TokenType::Identifier(s),
82+
..
83+
}) => format!("&{}", s),
84+
Some(other) => {
85+
println!("Expected identifier after '&', got {:?}", other.token_type);
86+
return None;
87+
}
88+
None => {
89+
println!("Expected identifier after '&'");
90+
return None;
91+
}
92+
},
93+
Some(Token {
94+
token_type: TokenType::Identifier(s),
95+
..
96+
}) => s.clone(),
97+
Some(Token {
98+
token_type: TokenType::Number(n),
99+
..
100+
}) => n.to_string(),
101+
Some(Token {
102+
token_type: TokenType::String(n),
103+
..
104+
}) => n.to_string(),
105+
Some(other) => {
106+
println!(
107+
"Expected identifier or number after in/out(...), got {:?}",
108+
other.token_type
109+
);
110+
return None;
111+
}
112+
None => {
113+
println!("Expected value after in/out(...)");
114+
return None;
115+
}
116+
};
117+
118+
if is_input {
119+
inputs.push((reg.clone(), value));
120+
} else {
121+
outputs.push((reg.clone(), value));
122+
}
123+
}
124+
125+
TokenType::String(s) => {
126+
instructions.push(s.clone());
127+
}
128+
129+
other => {
130+
println!("Unexpected token in asm expression {:?}", other);
131+
}
132+
}
133+
}
134+
135+
Some(ASTNode::Statement(StatementNode::AsmBlock {
136+
instructions,
137+
inputs,
138+
outputs,
139+
}))
140+
}

front/parser/src/parser/control.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
use std::iter::Peekable;
2+
use std::slice::Iter;
3+
use lexer::{Token, TokenType};
4+
use crate::ast::{ASTNode, Expression, StatementNode};
5+
use crate::format::parse_expression;
6+
use crate::parser::stmt::parse_block;
7+
8+
pub fn parse_if(tokens: &mut Peekable<Iter<Token>>) -> Option<ASTNode> {
9+
if tokens.peek()?.token_type != TokenType::Lparen {
10+
println!("Error: Expected '(' after 'if'");
11+
return None;
12+
}
13+
tokens.next(); // Consume '('
14+
15+
let condition = parse_expression(tokens)?;
16+
17+
if tokens.peek()?.token_type != TokenType::Rparen {
18+
println!("Error: Expected ')' after 'if' condition");
19+
return None;
20+
}
21+
tokens.next(); // Consume ')'
22+
23+
if tokens.peek()?.token_type != TokenType::Lbrace {
24+
println!("Error: Expected '{{' after 'if' condition");
25+
return None;
26+
}
27+
tokens.next(); // Consume '{'
28+
let body = parse_block(tokens)?;
29+
30+
let mut else_if_blocks: Vec<(Expression, Vec<ASTNode>)> = Vec::new(); // Changed to store conditions and bodies
31+
let mut else_block = None;
32+
33+
while let Some(token) = tokens.peek() {
34+
if token.token_type != TokenType::Else {
35+
break;
36+
}
37+
tokens.next(); // consume 'else'
38+
39+
if let Some(Token {
40+
token_type: TokenType::If,
41+
..
42+
}) = tokens.peek()
43+
{
44+
tokens.next(); // consume 'if'
45+
46+
if tokens.peek()?.token_type != TokenType::Lparen {
47+
println!("Error: Expected '(' after 'else if'");
48+
return None;
49+
}
50+
tokens.next();
51+
let else_if_condition = parse_expression(tokens)?;
52+
53+
if tokens.peek()?.token_type != TokenType::Rparen {
54+
println!("Error: Expected ')' after 'else if' condition");
55+
return None;
56+
}
57+
tokens.next();
58+
59+
if tokens.peek()?.token_type != TokenType::Lbrace {
60+
println!("Error: Expected '{{' after 'else if'");
61+
return None;
62+
}
63+
tokens.next();
64+
let else_if_body = parse_block(tokens)?;
65+
66+
// Store condition and body directly instead of nested If node
67+
else_if_blocks.push((else_if_condition, else_if_body));
68+
} else {
69+
if tokens.peek()?.token_type != TokenType::Lbrace {
70+
println!("Error: Expected '{{' after 'else'");
71+
return None;
72+
}
73+
tokens.next();
74+
else_block = Some(Box::new(parse_block(tokens)?));
75+
break;
76+
}
77+
}
78+
79+
Some(ASTNode::Statement(StatementNode::If {
80+
condition,
81+
body,
82+
else_if_blocks: if else_if_blocks.is_empty() {
83+
None
84+
} else {
85+
Some(Box::new(else_if_blocks))
86+
},
87+
else_block,
88+
}))
89+
}
90+
91+
// FOR parsing
92+
pub fn parse_for(_tokens: &mut Peekable<Iter<Token>>) -> Option<ASTNode> {
93+
// TODO: Implement proper for loop parsing
94+
/*
95+
// Check 'for' keyword and see if there is '()
96+
if tokens.peek()?.token_type != TokenType::Lparen {
97+
println!("Error: Expected '(' after 'if'");
98+
return None;
99+
}
100+
tokens.next(); // '(' Consumption
101+
102+
// Conditional parsing (where condition must be made ASTNode)
103+
let initialization = parse_expression(tokens)?; // Parsing conditions with expressions
104+
let condition = parse_expression(tokens)?;
105+
let increment = parse_expression(tokens)?;
106+
let body = parse_expression(tokens)?;
107+
108+
if tokens.peek()?.token_type != TokenType::Rparen {
109+
println!("Error: Expected ')' after condition");
110+
return None;
111+
}
112+
tokens.next(); // ')' Consumption
113+
114+
Some(ASTNode::Statement(StatementNode::For {
115+
initialization,
116+
condition,
117+
increment,
118+
body,
119+
}))
120+
*/
121+
None
122+
}
123+
124+
// WHILE parsing
125+
pub fn parse_while(tokens: &mut Peekable<Iter<Token>>) -> Option<ASTNode> {
126+
if tokens.peek()?.token_type != TokenType::Lparen {
127+
println!("Error: Expected '(' after 'while'");
128+
return None;
129+
}
130+
tokens.next(); // Consume '('
131+
132+
let condition = parse_expression(tokens)?;
133+
134+
if tokens.peek()?.token_type != TokenType::Rparen {
135+
println!("Error: Expected ')' after 'while' condition");
136+
return None;
137+
}
138+
tokens.next(); // Consume ')'
139+
140+
if tokens.peek()?.token_type != TokenType::Lbrace {
141+
println!("Error: Expected '{{' after 'while'");
142+
return None;
143+
}
144+
tokens.next(); // Consume '{'
145+
146+
let body = parse_block(tokens)?;
147+
148+
Some(ASTNode::Statement(StatementNode::While { condition, body }))
149+
}

0 commit comments

Comments
 (0)