add function value
This commit is contained in:
parent
a29bc95f3b
commit
76cf35e72e
10
src/ast.rs
10
src/ast.rs
@ -24,6 +24,10 @@ pub enum Expr {
|
|||||||
truthy: Box<Node<Expr>>,
|
truthy: Box<Node<Expr>>,
|
||||||
falsy: Option<Box<Node<Expr>>>,
|
falsy: Option<Box<Node<Expr>>>,
|
||||||
},
|
},
|
||||||
|
FunctionValue {
|
||||||
|
parameters: Vec<Node<Parameter>>,
|
||||||
|
body: Box<Node<Expr>>,
|
||||||
|
},
|
||||||
|
|
||||||
Member {
|
Member {
|
||||||
subject: Box<Node<Expr>>,
|
subject: Box<Node<Expr>>,
|
||||||
@ -70,6 +74,11 @@ pub enum Expr {
|
|||||||
condition: Box<Node<Expr>>,
|
condition: Box<Node<Expr>>,
|
||||||
body: Box<Node<Expr>>,
|
body: Box<Node<Expr>>,
|
||||||
},
|
},
|
||||||
|
For {
|
||||||
|
subject: Node<Parameter>,
|
||||||
|
value: Box<Node<Expr>>,
|
||||||
|
body: Box<Node<Expr>>,
|
||||||
|
},
|
||||||
Return(Option<Box<Node<Expr>>>),
|
Return(Option<Box<Node<Expr>>>),
|
||||||
Function {
|
Function {
|
||||||
name: String,
|
name: String,
|
||||||
@ -116,6 +125,7 @@ pub enum BinaryType {
|
|||||||
GT,
|
GT,
|
||||||
GTE,
|
GTE,
|
||||||
In,
|
In,
|
||||||
|
NotIn,
|
||||||
Equal,
|
Equal,
|
||||||
Inequal,
|
Inequal,
|
||||||
And,
|
And,
|
||||||
|
124
src/parser.rs
124
src/parser.rs
@ -58,10 +58,12 @@ where
|
|||||||
}
|
}
|
||||||
match self.current().token_type {
|
match self.current().token_type {
|
||||||
TokenType::Fn => self.parse_function(),
|
TokenType::Fn => self.parse_function(),
|
||||||
TokenType::Return => self.parse_function(),
|
TokenType::Return => self.parse_return(),
|
||||||
TokenType::While => self.parse_function(),
|
TokenType::For => self.parse_for(),
|
||||||
TokenType::Break => self.parse_function(),
|
TokenType::While => self.parse_while(),
|
||||||
TokenType::Continue => self.parse_function(),
|
TokenType::Break => self.parse_break(),
|
||||||
|
TokenType::Continue => self.parse_continue(),
|
||||||
|
TokenType::Let => self.parse_let(),
|
||||||
_ => self.parse_assign(),
|
_ => self.parse_assign(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,10 +75,39 @@ where
|
|||||||
}
|
}
|
||||||
let name = self.token_string(self.current());
|
let name = self.token_string(self.current());
|
||||||
self.step();
|
self.step();
|
||||||
|
let (parameters, body) = match self.parse_function_details() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
self.node(Expr::Function {
|
||||||
|
name,
|
||||||
|
parameters,
|
||||||
|
body: Box::new(body),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_details(&mut self) -> Result<(Vec<Node<Parameter>>, Node<Expr>), Node<Expr>> {
|
||||||
if self.done() || !self.current_is(TokenType::LParen) {
|
if self.done() || !self.current_is(TokenType::LParen) {
|
||||||
return self.error("expected '('");
|
return Err(self.error("expected '('"));
|
||||||
}
|
}
|
||||||
self.step();
|
self.step();
|
||||||
|
let mut parameters = self.parse_function_parameters();
|
||||||
|
if self.done() || !self.current_is(TokenType::RParen) {
|
||||||
|
return Err(self.error("expected ')'"));
|
||||||
|
}
|
||||||
|
self.step();
|
||||||
|
let body = if !self.done() && self.current_is(TokenType::LBrace) {
|
||||||
|
self.parse_block()
|
||||||
|
} else if !self.done() && self.current_is(TokenType::EqualLessThan) {
|
||||||
|
self.step();
|
||||||
|
self.parse_expr()
|
||||||
|
} else {
|
||||||
|
return Err(self.error("expected '{'"));
|
||||||
|
};
|
||||||
|
Ok((parameters, body))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_parameters(&mut self) -> Vec<Node<Parameter>> {
|
||||||
let mut parameters = Vec::<Node<Parameter>>::new();
|
let mut parameters = Vec::<Node<Parameter>>::new();
|
||||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||||
if self.current_is(TokenType::DotDotDot) {
|
if self.current_is(TokenType::DotDotDot) {
|
||||||
@ -100,19 +131,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.done() || !self.current_is(TokenType::RParen) {
|
parameters
|
||||||
return self.error("expected ')'");
|
|
||||||
}
|
|
||||||
self.step();
|
|
||||||
if self.done() || !self.current_is(TokenType::LBrace) {
|
|
||||||
return self.error("expected '{'");
|
|
||||||
}
|
|
||||||
let body = self.parse_block();
|
|
||||||
self.node(Expr::Function {
|
|
||||||
name,
|
|
||||||
parameters,
|
|
||||||
body: Box::new(body),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_parameter(&mut self) -> Node<Parameter> {
|
fn parse_parameter(&mut self) -> Node<Parameter> {
|
||||||
@ -139,6 +158,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_for(&mut self) -> Node<Expr> {
|
||||||
|
self.step();
|
||||||
|
let subject = self.parse_parameter();
|
||||||
|
if self.done() || !self.current_is(TokenType::In) {
|
||||||
|
return self.error("expected 'in'");
|
||||||
|
}
|
||||||
|
self.step();
|
||||||
|
let value = self.parse_expr();
|
||||||
|
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||||
|
return self.error("expected '{'");
|
||||||
|
}
|
||||||
|
let body = self.parse_block();
|
||||||
|
self.node(Expr::For {
|
||||||
|
subject,
|
||||||
|
value: Box::new(value),
|
||||||
|
body: Box::new(body),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_while(&mut self) -> Node<Expr> {
|
fn parse_while(&mut self) -> Node<Expr> {
|
||||||
self.step();
|
self.step();
|
||||||
let condition = self.parse_expr();
|
let condition = self.parse_expr();
|
||||||
@ -357,6 +395,18 @@ where
|
|||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
right: Box::new(right),
|
right: Box::new(right),
|
||||||
});
|
});
|
||||||
|
} else if self.current_is(TokenType::Not) {
|
||||||
|
self.step();
|
||||||
|
if self.done() || !self.current_is(TokenType::In) {
|
||||||
|
return self.error("expected 'in'");
|
||||||
|
}
|
||||||
|
self.step();
|
||||||
|
let right = self.parse_prec_range();
|
||||||
|
left = self.node(Expr::Binary {
|
||||||
|
binary_type: BinaryType::NotIn,
|
||||||
|
left: Box::new(left),
|
||||||
|
right: Box::new(right),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -585,9 +635,10 @@ where
|
|||||||
TokenType::True => self.step_and_node(Expr::Bool(true)),
|
TokenType::True => self.step_and_node(Expr::Bool(true)),
|
||||||
TokenType::LParen => self.parse_unit_group_or_tuple(),
|
TokenType::LParen => self.parse_unit_group_or_tuple(),
|
||||||
TokenType::LBrace => self.parse_block(),
|
TokenType::LBrace => self.parse_block(),
|
||||||
TokenType::Underscore => todo!(),
|
TokenType::Underscore => self.parse_object(),
|
||||||
TokenType::LBracket => self.parse_array(),
|
TokenType::LBracket => self.parse_array(),
|
||||||
TokenType::If => self.parse_if(),
|
TokenType::If => self.parse_if(),
|
||||||
|
TokenType::Fn => self.parse_function_value(),
|
||||||
TokenType::MalformedString => self.error("malformed string"),
|
TokenType::MalformedString => self.error("malformed string"),
|
||||||
other => self.node(Expr::Error(format!("expected value, got {:?}", other))),
|
other => self.node(Expr::Error(format!("expected value, got {:?}", other))),
|
||||||
}
|
}
|
||||||
@ -605,8 +656,19 @@ where
|
|||||||
self.step();
|
self.step();
|
||||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
if !self.done() && !self.current_is(TokenType::LParen) {
|
||||||
let first_value = self.parse_expr();
|
let first_value = self.parse_expr();
|
||||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||||
todo!()
|
let mut values = vec![first_value];
|
||||||
|
while !self.done() && self.current_is(TokenType::Comma) {
|
||||||
|
self.step();
|
||||||
|
if self.done() || self.current_is(TokenType::RParen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
values.push(self.parse_expr());
|
||||||
|
}
|
||||||
|
if self.done() || !self.current_is(TokenType::RParen) {
|
||||||
|
return self.error("expected ')'");
|
||||||
|
}
|
||||||
|
self.step_and_node(Expr::Tuple(values))
|
||||||
} else {
|
} else {
|
||||||
self.step_and(first_value)
|
self.step_and(first_value)
|
||||||
}
|
}
|
||||||
@ -616,6 +678,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_object(&mut self) -> Node<Expr> {
|
fn parse_object(&mut self) -> Node<Expr> {
|
||||||
|
self.step();
|
||||||
|
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||||
|
return self.error("expected '{' of object literal");
|
||||||
|
}
|
||||||
self.step();
|
self.step();
|
||||||
let mut values = Vec::<Node<ObjectEntry>>::new();
|
let mut values = Vec::<Node<ObjectEntry>>::new();
|
||||||
if !self.done() && !self.current_is(TokenType::RBracket) {
|
if !self.done() && !self.current_is(TokenType::RBracket) {
|
||||||
@ -709,11 +775,23 @@ where
|
|||||||
}
|
}
|
||||||
falsy = Some(self.parse_block());
|
falsy = Some(self.parse_block());
|
||||||
}
|
}
|
||||||
return self.node(Expr::If {
|
self.node(Expr::If {
|
||||||
condition: Box::new(condition),
|
condition: Box::new(condition),
|
||||||
truthy: Box::new(truthy),
|
truthy: Box::new(truthy),
|
||||||
falsy: falsy.map(Box::new),
|
falsy: falsy.map(Box::new),
|
||||||
});
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_value(&mut self) -> Node<Expr> {
|
||||||
|
self.step();
|
||||||
|
let (parameters, body) = match self.parse_function_details() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
self.node(Expr::FunctionValue {
|
||||||
|
parameters,
|
||||||
|
body: Box::new(body),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn token_string(&self, token: &Token) -> String {
|
fn token_string(&self, token: &Token) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user