Skip to content

Commit

Permalink
call initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
cezaris13 committed Dec 8, 2024
1 parent 06c1df3 commit 57ef2ec
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 18 deletions.
6 changes: 5 additions & 1 deletion loxGrammar.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@
<factor> ::= <unary> ( ("/" | "*") <unary> )*

<unary> ::= ("-" | "!") <unary>
| <primary>
| <call>

<call> ::= <primary> ( "(" <arguments>? ")" )*

<arguments> ::= <expression> ("," <expression>)*

<primary> ::= <number>
| <string>
Expand Down
48 changes: 33 additions & 15 deletions src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ pub enum Expression {
operator: Token,
right: Box<Expression>,
},
Call {
callee: Box<Expression>,
paren: Token,
arguments: Vec<Box<Expression>>,
},
}

impl Display for Expression {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str = match self {
Expression::Binary {
Self::Binary {
left,
operator,
right,
Expand All @@ -56,7 +61,7 @@ impl Display for Expression {
right.to_string()
)
}
Expression::Logical {
Self::Logical {
left,
operator,
right,
Expand All @@ -68,14 +73,14 @@ impl Display for Expression {
right.to_string()
)
}
Expression::Grouping { group } => {
Self::Grouping { group } => {
format!("(group {})", group.to_string())
}
Expression::Literal { value } => value.to_string(),
Expression::Unary { operator, right } => {
Self::Literal { value } => value.to_string(),
Self::Unary { operator, right } => {
format!("({} {})", operator.lexeme, right.to_string())
}
Expression::Variable { token } => {
Self::Variable { token } => {
if let Some(_) = &token.literal {
format!(
"(defvar {} {})",
Expand All @@ -86,7 +91,12 @@ impl Display for Expression {
format!("(defvar {})", token.lexeme)
}
}
Expression::Assign { name, value } => format!("(= {} {})", name, value.to_string()),
Self::Assign { name, value } => format!("(= {} {})", name, value.to_string()),
Self::Call {
callee,
paren: _,
arguments,
} => format!("({} {:?})", callee, arguments),
};
write!(f, "{}", str)
}
Expand All @@ -95,9 +105,9 @@ impl Display for Expression {
impl Expression {
pub fn evaluate(&self, environment: &mut Environment) -> Result<LiteralValue, String> {
match self {
Expression::Literal { value } => Ok(value.clone()),
Expression::Grouping { group } => group.evaluate(environment),
Expression::Unary { operator, right } => {
Self::Literal { value } => Ok(value.clone()),
Self::Grouping { group } => group.evaluate(environment),
Self::Unary { operator, right } => {
let right = (*right).evaluate(environment)?;

match (&right, &operator.token_type) {
Expand All @@ -112,7 +122,7 @@ impl Expression {
)),
}
}
Expression::Binary {
Self::Binary {
left,
operator,
right,
Expand All @@ -121,7 +131,7 @@ impl Expression {
let right = (*right).evaluate(environment)?;

match &operator.token_type {
Plus => left + right,
Plus => left + right,
Minus => left - right,
Star => left * right,
Slash => left / right,
Expand All @@ -138,13 +148,13 @@ impl Expression {
),
}
}
Expression::Variable { token } => environment.get(&token.lexeme),
Expression::Assign { name, value } => {
Self::Variable { token } => environment.get(&token.lexeme),
Self::Assign { name, value } => {
let value = value.evaluate(environment)?;
environment.assign(name.clone(), value.clone())?; // temp fix
Ok(value)
}
Expression::Logical {
Self::Logical {
left,
operator,
right,
Expand All @@ -163,6 +173,14 @@ impl Expression {

right.evaluate(environment)
}
Self::Call {
callee,
paren,
arguments,
} => {
println!("{:?} {:?} {:?}", callee, paren, arguments);
todo!()
}
}
}
}
42 changes: 41 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,47 @@ impl Parser {
});
}

self.primary()
self.call()
}

fn call(&mut self) -> Result<Expression, String> {
let mut expr = self.primary()?;

loop {
if self.match_tokens(vec![LeftParen]) {
expr = self.finish_call(expr)?;
} else {
break;
}
}

Ok(expr)
}

fn finish_call(&mut self, callee: Expression) -> Result<Expression, String> {
let mut arguments = vec![];

if !self.check(RightParen) {
loop {
if arguments.len() >= 255 {
return Err(format!("Cant't have more than 255 arguments"));
}

arguments.push(Box::new(self.expression()?));

if !self.match_tokens(vec![Comma]) {
break;
}
}
}

let right_paren = self.consume(RightParen, "Expected ')' after arguments.")?;

Ok(Expression::Call {
callee: Box::new(callee),
paren: right_paren,
arguments: arguments,
})
}

fn primary(&mut self) -> Result<Expression, String> {
Expand Down
2 changes: 1 addition & 1 deletion src/tests/parser_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
mod tests {
use crate::expression::Expression::*;
use crate::expression_literal_value::LiteralValue as ExpressionLiteralValue;
use crate::statement::Statement::{Block, Expression, Variable, Print};
use crate::statement::Statement::{Block, Expression, Print, Variable};
use crate::token::{LiteralValue, Token, TokenType::*};
use crate::Parser;
use crate::Scanner;
Expand Down

0 comments on commit 57ef2ec

Please sign in to comment.