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>>,
|
||||
falsy: Option<Box<Node<Expr>>>,
|
||||
},
|
||||
FunctionValue {
|
||||
parameters: Vec<Node<Parameter>>,
|
||||
body: Box<Node<Expr>>,
|
||||
},
|
||||
|
||||
Member {
|
||||
subject: Box<Node<Expr>>,
|
||||
@ -70,6 +74,11 @@ pub enum Expr {
|
||||
condition: Box<Node<Expr>>,
|
||||
body: Box<Node<Expr>>,
|
||||
},
|
||||
For {
|
||||
subject: Node<Parameter>,
|
||||
value: Box<Node<Expr>>,
|
||||
body: Box<Node<Expr>>,
|
||||
},
|
||||
Return(Option<Box<Node<Expr>>>),
|
||||
Function {
|
||||
name: String,
|
||||
@ -116,6 +125,7 @@ pub enum BinaryType {
|
||||
GT,
|
||||
GTE,
|
||||
In,
|
||||
NotIn,
|
||||
Equal,
|
||||
Inequal,
|
||||
And,
|
||||
|
124
src/parser.rs
124
src/parser.rs
@ -58,10 +58,12 @@ where
|
||||
}
|
||||
match self.current().token_type {
|
||||
TokenType::Fn => self.parse_function(),
|
||||
TokenType::Return => self.parse_function(),
|
||||
TokenType::While => self.parse_function(),
|
||||
TokenType::Break => self.parse_function(),
|
||||
TokenType::Continue => self.parse_function(),
|
||||
TokenType::Return => self.parse_return(),
|
||||
TokenType::For => self.parse_for(),
|
||||
TokenType::While => self.parse_while(),
|
||||
TokenType::Break => self.parse_break(),
|
||||
TokenType::Continue => self.parse_continue(),
|
||||
TokenType::Let => self.parse_let(),
|
||||
_ => self.parse_assign(),
|
||||
}
|
||||
}
|
||||
@ -73,10 +75,39 @@ where
|
||||
}
|
||||
let name = self.token_string(self.current());
|
||||
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) {
|
||||
return self.error("expected '('");
|
||||
return Err(self.error("expected '('"));
|
||||
}
|
||||
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();
|
||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
@ -100,19 +131,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RParen) {
|
||||
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),
|
||||
})
|
||||
parameters
|
||||
}
|
||||
|
||||
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> {
|
||||
self.step();
|
||||
let condition = self.parse_expr();
|
||||
@ -357,6 +395,18 @@ where
|
||||
left: Box::new(left),
|
||||
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 {
|
||||
break;
|
||||
}
|
||||
@ -585,9 +635,10 @@ where
|
||||
TokenType::True => self.step_and_node(Expr::Bool(true)),
|
||||
TokenType::LParen => self.parse_unit_group_or_tuple(),
|
||||
TokenType::LBrace => self.parse_block(),
|
||||
TokenType::Underscore => todo!(),
|
||||
TokenType::Underscore => self.parse_object(),
|
||||
TokenType::LBracket => self.parse_array(),
|
||||
TokenType::If => self.parse_if(),
|
||||
TokenType::Fn => self.parse_function_value(),
|
||||
TokenType::MalformedString => self.error("malformed string"),
|
||||
other => self.node(Expr::Error(format!("expected value, got {:?}", other))),
|
||||
}
|
||||
@ -605,8 +656,19 @@ where
|
||||
self.step();
|
||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
||||
let first_value = self.parse_expr();
|
||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
||||
todo!()
|
||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||
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 {
|
||||
self.step_and(first_value)
|
||||
}
|
||||
@ -616,6 +678,10 @@ where
|
||||
}
|
||||
|
||||
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();
|
||||
let mut values = Vec::<Node<ObjectEntry>>::new();
|
||||
if !self.done() && !self.current_is(TokenType::RBracket) {
|
||||
@ -709,11 +775,23 @@ where
|
||||
}
|
||||
falsy = Some(self.parse_block());
|
||||
}
|
||||
return self.node(Expr::If {
|
||||
self.node(Expr::If {
|
||||
condition: Box::new(condition),
|
||||
truthy: Box::new(truthy),
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user