logical operators, uhhh, others?

This commit is contained in:
Tristan 2025-05-08 08:09:45 -04:00
parent 9db8be38f5
commit 6c61db4b57
3 changed files with 100 additions and 21 deletions

View File

@ -69,7 +69,7 @@ define $number := 5;
print(`The square of $number is ${math.square($number)}`);
```
(Note: This feature is under development, and string interpolation is planned for a future update.)
(Note: This feature is under development, and string interpolation is planned for the future.)
---
@ -84,9 +84,10 @@ fddl is very much a work in progress, with lots of planned improvements and addi
- **Parser**:
- [x] Parser parsing tilde and minus successfully
- [ ] Parser parsing the rest of the operators
- [x] Parser parsing function calls
- [x] Parser parsing the rest of the operators (mostly complete)
- [ ] Working on building out functions to parse simple functionality in the language (if, while, for), and to read their expressions and values
- [ ] Implement parsing for function calls, expressions, checks, literally everything.
- [ ] Implement parsing for ~~~function calls,~~~ expressions, checks, literally everything.
- **Compiler**:
- [ ] Currently a placeholder. Implement the compiler to compile parsed code.

View File

@ -40,6 +40,10 @@ pub enum Operator {
GreaterEqual,
LessEqual,
// Logical operators
And, // For logical AND e.g. true && false
Or, // For logical OR e.g. true || false
// Equality (we'll add these logic for these later)
EqualEqual, // For equality e.g. 5 == 5
NotEqual, // For inequality e.g. 5 != 5

View File

@ -179,11 +179,13 @@ impl Parser {
}
fn parse_expression(&mut self) -> Option<Expression> {
// self.parse_primary(); // Now redundant // Start with the simplest elements
// Keeping old tests here for reference until release.
// self.parse_primary(); // Start with the simplest elements
// self.parse_unary() // handles unary operators ('-' and '~')
// self.parse_term() // handles binary operators ('+', '-', '*', '/')
// self.parse_comparison() // handles comparison operators ('<', '>', '<=', '>=')
self.parse_equality() // handles equality operators ('==', '!=')
// self.parse_equality() // handles equality operators ('==', '!=')
self.parse_logical_or() // handles logical operators ('&&', '||')
}
// Each function below is fed into the function below it
@ -212,11 +214,9 @@ impl Parser {
Some(Expression::Variable(name))
}
Token::LeftParen => {
self.advance(); // Consume '('
// Recursively parse the expression inside the parentheses
let expr = self.parse_expression()?; // Call the main expression parser
self.advance();
let expr = self.parse_expression()?;
// Expect and consume the closing parenthesis
if self.match_token(Token::RightParen) {
// Return the inner expression, wrapped in Grouping AST node
Some(Expression::Grouping(Box::new(expr)))
@ -235,24 +235,22 @@ impl Parser {
}
fn parse_unary(&mut self) -> Option<Expression> {
let current_tok = self.current_token().clone();
let operator_token_snapshot = self.current_token().clone();
match current_tok {
match operator_token_snapshot {
Token::Minus | Token::Tilde => {
self.advance();
let operator = match current_tok {
let ast_operator = match operator_token_snapshot {
Token::Minus => Operator::Minus,
Token::Tilde => Operator::Almost,
_ => unreachable!("Lexer should not produce other tokens here if first match is minus/tilde"),
_ => unreachable!("Lexer should not produce other tokens here if first match is minus/tilde. Checked by matches! macro."),
};
let right_operand = self.parse_primary()?;
Some(Expression::Unary(operator, Box::new(right_operand)))
let right_operand = self.parse_unary()?;
Some(Expression::Unary(ast_operator, Box::new(right_operand)))
}
_ => {
// If not a unary operator, just return the primary expression
self.parse_primary()
self.parse_call_expression()
}
}
}
@ -339,6 +337,82 @@ impl Parser {
Some(expr)
}
fn parse_logical_or(&mut self) -> Option<Expression> {
let mut expr = self.parse_logical_and()?;
while matches!(self.current_token(), Token::Or) {
let operator_token = self.current_token().clone();
self.advance();
let ast_operator = Operator::Or;
let right_operand = self.parse_logical_and()?;
expr = Expression::Binary(Box::new(expr), ast_operator, Box::new(right_operand));
}
Some(expr)
}
fn parse_logical_and(&mut self) -> Option<Expression> {
let mut expr = self.parse_equality()?;
while matches!(self.current_token(), Token::And) {
let operator_token = self.current_token().clone();
self.advance();
let ast_operator = Operator::And;
let right_operand = self.parse_equality()?;
expr = Expression::Binary(Box::new(expr), ast_operator, Box::new(right_operand));
}
Some(expr)
}
fn parse_call_expression(&mut self) -> Option<Expression> {
let mut expr = self.parse_primary()?;
loop {
if self.check(&Token::LeftParen) {
expr = self.finish_call(expr)?;
} else {
break;
}
}
Some(expr)
}
fn finish_call(&mut self, callee: Expression) -> Option<Expression> {
self.advance();
let arguments = self.parse_arguments()?;
if !self.match_token(Token::RightParen) {
eprintln!("Error: Expected ')' after arguments in function call.");
return None;
}
Some(Expression::FunctionCall(Box::new(callee), arguments))
}
fn parse_arguments(&mut self) -> Option<Vec<Expression>> {
let mut arguments = Vec::new();
if self.check(&Token::RightParen) {
return Some(arguments);
}
match self.parse_expression() {
Some(arg) => arguments.push(arg),
None => return None,
}
while self.match_token(Token::Comma) {
match self.parse_expression() {
Some(arg) => arguments.push(arg),
None => return None,
}
}
Some(arguments)
}
fn check(&self, expected: &Token) -> bool {
if self.is_at_end() {
return false;