latest pushes
This commit is contained in:
parent
61604e25bd
commit
1c53bc887d
120
src/bellos.rs
120
src/bellos.rs
@ -314,21 +314,9 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(&mut self) -> Result<ASTNode, String> {
|
|
||||||
self.position += 1; // Consume left paren
|
|
||||||
let mut statements = Vec::new();
|
|
||||||
while self.position < self.tokens.len() && self.tokens[self.position] != Token::RightParen {
|
|
||||||
statements.push(self.parse_statement()?);
|
|
||||||
self.consume_if(Token::Semicolon);
|
|
||||||
self.consume_if(Token::NewLine);
|
|
||||||
}
|
|
||||||
self.position += 1; // Consume right paren
|
|
||||||
Ok(ASTNode::Block(statements))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_if(&mut self) -> Result<ASTNode, String> {
|
fn parse_if(&mut self) -> Result<ASTNode, String> {
|
||||||
self.position += 1; // Consume 'if'
|
self.position += 1; // Consume 'if'
|
||||||
let condition = Box::new(self.parse_statement()?);
|
let condition = Box::new(self.parse_command()?);
|
||||||
self.expect_token(Token::Then)?;
|
self.expect_token(Token::Then)?;
|
||||||
let then_block = Box::new(self.parse_block()?);
|
let then_block = Box::new(self.parse_block()?);
|
||||||
let else_block = if self.consume_if(Token::Else) {
|
let else_block = if self.consume_if(Token::Else) {
|
||||||
@ -346,7 +334,7 @@ impl Parser {
|
|||||||
|
|
||||||
fn parse_while(&mut self) -> Result<ASTNode, String> {
|
fn parse_while(&mut self) -> Result<ASTNode, String> {
|
||||||
self.position += 1; // Consume 'while'
|
self.position += 1; // Consume 'while'
|
||||||
let condition = Box::new(self.parse_statement()?);
|
let condition = Box::new(self.parse_command()?);
|
||||||
self.expect_token(Token::Do)?;
|
self.expect_token(Token::Do)?;
|
||||||
let block = Box::new(self.parse_block()?);
|
let block = Box::new(self.parse_block()?);
|
||||||
self.expect_token(Token::Done)?;
|
self.expect_token(Token::Done)?;
|
||||||
@ -357,12 +345,7 @@ impl Parser {
|
|||||||
self.position += 1; // Consume 'for'
|
self.position += 1; // Consume 'for'
|
||||||
let var = match &self.tokens[self.position] {
|
let var = match &self.tokens[self.position] {
|
||||||
Token::Word(w) => w.clone(),
|
Token::Word(w) => w.clone(),
|
||||||
_ => {
|
_ => return Err("Expected variable name after 'for'".to_string()),
|
||||||
return Err(format!(
|
|
||||||
"Expected variable name after 'for', found {:?}",
|
|
||||||
self.tokens[self.position]
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
self.expect_token(Token::In)?;
|
self.expect_token(Token::In)?;
|
||||||
@ -381,6 +364,46 @@ impl Parser {
|
|||||||
Ok(ASTNode::For { var, list, block })
|
Ok(ASTNode::For { var, list, block })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_block(&mut self) -> Result<ASTNode, String> {
|
||||||
|
let mut statements = Vec::new();
|
||||||
|
while self.position < self.tokens.len()
|
||||||
|
&& !matches!(
|
||||||
|
self.tokens[self.position],
|
||||||
|
Token::Fi | Token::Done | Token::Else
|
||||||
|
)
|
||||||
|
{
|
||||||
|
statements.push(self.parse_statement()?);
|
||||||
|
self.consume_if(Token::Semicolon);
|
||||||
|
self.consume_if(Token::NewLine);
|
||||||
|
}
|
||||||
|
Ok(ASTNode::Block(statements))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_command(&mut self) -> Result<ASTNode, String> {
|
||||||
|
let mut args = Vec::new();
|
||||||
|
while self.position < self.tokens.len()
|
||||||
|
&& !matches!(
|
||||||
|
self.tokens[self.position],
|
||||||
|
Token::Then | Token::Do | Token::Done | Token::Fi | Token::Else
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if let Token::Word(w) = &self.tokens[self.position] {
|
||||||
|
args.push(w.clone());
|
||||||
|
self.position += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if args.is_empty() {
|
||||||
|
Err("Expected command".to_string())
|
||||||
|
} else {
|
||||||
|
Ok(ASTNode::Command {
|
||||||
|
name: args[0].clone(),
|
||||||
|
args: args[1..].to_vec(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_function(&mut self) -> Result<ASTNode, String> {
|
fn parse_function(&mut self) -> Result<ASTNode, String> {
|
||||||
self.position += 1; // Consume 'function'
|
self.position += 1; // Consume 'function'
|
||||||
let name = match &self.tokens[self.position] {
|
let name = match &self.tokens[self.position] {
|
||||||
@ -467,16 +490,15 @@ impl Interpreter {
|
|||||||
then_block,
|
then_block,
|
||||||
else_block,
|
else_block,
|
||||||
} => {
|
} => {
|
||||||
if self.interpret_node(condition)? == Some(0) {
|
if self.evaluate_condition(&condition)? {
|
||||||
self.interpret_node(then_block)
|
self.interpret_node(then_block)?;
|
||||||
} else if let Some(else_block) = else_block {
|
} else if let Some(else_block) = else_block {
|
||||||
self.interpret_node(else_block)
|
self.interpret_node(else_block)?;
|
||||||
} else {
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ASTNode::While { condition, block } => {
|
ASTNode::While { condition, block } => {
|
||||||
while self.interpret_node(Box::new(*condition.clone()))? == Some(0) {
|
while self.evaluate_condition(&condition)? {
|
||||||
self.interpret_node(Box::new(*block.clone()))?;
|
self.interpret_node(Box::new(*block.clone()))?;
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -560,44 +582,49 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_arithmetic(&self, expr: &str) -> i32 {
|
fn evaluate_arithmetic(&self, expr: &str) -> Result<i32, String> {
|
||||||
let tokens: Vec<&str> = expr.split_whitespace().collect();
|
let tokens: Vec<&str> = expr.split_whitespace().collect();
|
||||||
if tokens.len() != 3 {
|
if tokens.len() != 3 {
|
||||||
return 0; // Invalid expression
|
return Err("Invalid arithmetic expression".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = self.get_var_value(tokens[0]);
|
let a = self.get_var_value(tokens[0])?;
|
||||||
let b = self.get_var_value(tokens[2]);
|
let b = self.get_var_value(tokens[2])?;
|
||||||
|
|
||||||
match tokens[1] {
|
match tokens[1] {
|
||||||
"+" => a + b,
|
"+" => Ok(a + b),
|
||||||
"-" => a - b,
|
"-" => Ok(a - b),
|
||||||
"*" => a * b,
|
"*" => Ok(a * b),
|
||||||
"/" => {
|
"/" => {
|
||||||
if b != 0 {
|
if b != 0 {
|
||||||
a / b
|
Ok(a / b)
|
||||||
} else {
|
} else {
|
||||||
0
|
Err("Division by zero".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"%" => {
|
"%" => {
|
||||||
if b != 0 {
|
if b != 0 {
|
||||||
a % b
|
Ok(a % b)
|
||||||
} else {
|
} else {
|
||||||
0
|
Err("Modulo by zero".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => 0, // Unsupported operation
|
_ => Err(format!("Unsupported operation: {}", tokens[1])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_var_value(&self, var: &str) -> i32 {
|
fn get_var_value(&self, var: &str) -> Result<i32, String> {
|
||||||
if let Some(value) = self.variables.get(var) {
|
if let Some(value) = self.variables.get(var) {
|
||||||
value.parse().unwrap_or(0)
|
value
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| format!("Invalid integer: {}", value))
|
||||||
} else if let Ok(value) = env::var(var) {
|
} else if let Ok(value) = env::var(var) {
|
||||||
value.parse().unwrap_or(0)
|
value
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| format!("Invalid integer: {}", value))
|
||||||
} else {
|
} else {
|
||||||
var.parse().unwrap_or(0)
|
var.parse()
|
||||||
|
.map_err(|_| format!("Invalid integer or undefined variable: {}", var))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,8 +652,6 @@ impl Interpreter {
|
|||||||
>= expanded_args[2].parse::<i32>().unwrap_or(0)),
|
>= expanded_args[2].parse::<i32>().unwrap_or(0)),
|
||||||
"-z" => Ok(expanded_args[0].is_empty()),
|
"-z" => Ok(expanded_args[0].is_empty()),
|
||||||
"-n" => Ok(!expanded_args[0].is_empty()),
|
"-n" => Ok(!expanded_args[0].is_empty()),
|
||||||
"=" => Ok(expanded_args[0] == expanded_args[2]),
|
|
||||||
"!=" => Ok(expanded_args[0] != expanded_args[2]),
|
|
||||||
_ => Err(format!("Unsupported test condition: {}", expanded_args[1])),
|
_ => Err(format!("Unsupported test condition: {}", expanded_args[1])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,6 +664,7 @@ impl Interpreter {
|
|||||||
_ => Err("Invalid condition node".to_string()),
|
_ => Err("Invalid condition node".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_pipeline(&mut self, commands: Vec<ASTNode>) -> Result<Option<i32>, String> {
|
fn execute_pipeline(&mut self, commands: Vec<ASTNode>) -> Result<Option<i32>, String> {
|
||||||
let mut previous_stdout = None;
|
let mut previous_stdout = None;
|
||||||
let mut processes = Vec::new();
|
let mut processes = Vec::new();
|
||||||
@ -755,7 +781,10 @@ impl Interpreter {
|
|||||||
if expr.starts_with('(') && expr.ends_with(')') {
|
if expr.starts_with('(') && expr.ends_with(')') {
|
||||||
// Arithmetic expression
|
// Arithmetic expression
|
||||||
let arithmetic_expr = &expr[1..expr.len() - 1];
|
let arithmetic_expr = &expr[1..expr.len() - 1];
|
||||||
result.push_str(&self.evaluate_arithmetic(arithmetic_expr).to_string());
|
match self.evaluate_arithmetic(arithmetic_expr) {
|
||||||
|
Ok(value) => result.push_str(&value.to_string()),
|
||||||
|
Err(e) => result.push_str(&format!("Error: {}", e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let var_name: String = chars
|
let var_name: String = chars
|
||||||
@ -869,6 +898,7 @@ fn run_interactive_mode(interpreter: &mut Interpreter) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for Lexer {
|
impl Iterator for Lexer {
|
||||||
type Item = Token;
|
type Item = Token;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user