Prepared for supporting multiple function arguments. The types now support several arguments, and the only thing left is to parse this.

This commit is contained in:
PaddiM8 2020-05-29 00:27:08 +02:00
parent 94722ed27e
commit 6d67797565
3 changed files with 64 additions and 24 deletions

View File

@ -75,11 +75,16 @@ impl Visitor<f64, f64> for Interpreter {
self.symbol_table.insert(identifier.clone(), stmt.clone());
0f64
}
Stmt::FnDecl(identifier, argument, _) => {
self.visit_stmt(&Stmt::VarDecl(
argument.clone(),
Box::new(Expr::Literal(String::from("0"))),
));
Stmt::FnDecl(identifier, arguments, _) => {
// Initialise each of the arguments as their own variable.
for argument in arguments {
self.visit_stmt(&Stmt::VarDecl(
argument.clone(),
Box::new(Expr::Literal(String::from("0"))),
));
}
// Add the function to the symbol table.
self.symbol_table
.insert(format!("{}()", identifier.clone()), stmt.clone());
0f64
@ -134,9 +139,16 @@ impl Visitor<f64, f64> for Interpreter {
}
Expr::Literal(value) => value.parse().unwrap(),
Expr::Group(expr) => self.visit_expr(&expr),
Expr::FnCall(identifier, expr) => {
let x = self.visit_expr(&expr);
if let Some(result) = self.prelude.call_unary_func(identifier, x) {
Expr::FnCall(identifier, expressions) => {
let prelude_func = match expressions.len() {
1 => {
let x = self.visit_expr(&expressions[0]);
self.prelude.call_unary_func(identifier, x)
}
_ => None,
};
if let Some(result) = prelude_func {
result
} else {
let stmt = self
@ -144,13 +156,24 @@ impl Visitor<f64, f64> for Interpreter {
.get(&format!("{}()", identifier))
.expect("Undefined function")
.clone();
match stmt {
Stmt::FnDecl(_, argument, fn_body) => {
self.visit_stmt(&Stmt::VarDecl(argument.clone(), expr.clone()));
self.visit_expr(&*fn_body)
if let Stmt::FnDecl(_, arguments, fn_body) = stmt {
if arguments.len() != expressions.len() {
panic!("Incorrect amount of arguments.");
}
_ => panic!(),
// Initialise the arguments as their own variables.
for (i, argument) in arguments.iter().enumerate() {
self.visit_stmt(&Stmt::VarDecl(
argument.clone(),
Box::new(expressions[i].clone()),
));
}
return self.visit_expr(&*fn_body);
}
panic!("Unexpected error.");
}
}
}

View File

@ -5,17 +5,22 @@ pub enum TokenKind {
Unknown,
Literal,
Identifier,
Plus,
Minus,
Star,
Slash,
Power,
Equals,
Deg,
Rad,
Pipe,
OpenParenthesis,
ClosedParenthesis,
Comma,
EOF,
}
@ -101,6 +106,10 @@ impl<'a> Lexer<'a> {
self.advance();
self.build(TokenKind::Equals, "")
}
',' => {
self.advance();
self.build(TokenKind::Comma, "")
}
_ => {
if c.is_digit(10) {
self.next_number_literal()

View File

@ -5,7 +5,7 @@ use crate::lexer::{Token, TokenKind};
#[derive(Debug, Clone)]
pub enum Stmt {
VarDecl(String, Box<Expr>),
FnDecl(String, String, Box<Expr>),
FnDecl(String, Vec<String>, Box<Expr>),
Expr(Box<Expr>),
}
@ -16,7 +16,7 @@ pub enum Expr {
Unit(Box<Expr>, TokenKind),
Var(String),
Group(Box<Expr>),
FnCall(String, Box<Expr>),
FnCall(String, Vec<Expr>),
Literal(String),
}
@ -85,15 +85,23 @@ impl Parser {
self.advance();
let expr = self.parse_expr();
match primary {
Expr::FnCall(identifier, argument) => match *argument {
Expr::Var(argument_identifier) => {
Stmt::FnDecl(identifier, argument_identifier, Box::new(expr))
// Use the "function call" expression that was parsed, and put its values into a function declaration statement instead.
if let Expr::FnCall(identifier, parameters) = primary {
let mut parameter_identifiers = Vec::new();
// All the "arguments" are expected to be parsed as variables,
// since parameter definitions look the same as variable references.
// Extract these.
for parameter in parameters {
if let Expr::Var(parameter_identifier) = parameter {
parameter_identifiers.push(parameter_identifier);
}
_ => panic!("Unexpected error."),
},
_ => panic!("Unexpected error."),
}
return Stmt::FnDecl(identifier, parameter_identifiers, Box::new(expr));
}
panic!("Unexpected error.");
} else {
// It is a function call, not a function declaration.
// Redo the parsing for this specific part.
@ -199,7 +207,7 @@ impl Parser {
let group_expr = Expr::Group(Box::new(self.parse_expr()));
self.consume(TokenKind::Pipe);
Expr::FnCall(String::from("abs"), Box::new(group_expr))
Expr::FnCall(String::from("abs"), vec![group_expr])
}
fn parse_identifier(&mut self) -> Expr {
@ -210,7 +218,7 @@ impl Parser {
let parameter = self.parse_expr();
self.consume(TokenKind::ClosedParenthesis);
Expr::FnCall(identifier.value, Box::new(parameter))
Expr::FnCall(identifier.value, vec![parameter])
} else {
Expr::Var(identifier.value)
}