dot and return
This commit is contained in:
parent
08a0a8a5db
commit
4738ad92bf
3 changed files with 54 additions and 12 deletions
|
|
@ -14,6 +14,10 @@ pub fn parse<T>(tokens: &mut Tokens, parser: Parser<T>) -> Result<T, Error> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_program(tokens: &mut Tokens) -> ParseResult<ast::Program> {
|
||||
Ok(parse_definitions(tokens)?.map(ast::Program))
|
||||
}
|
||||
|
||||
fn parse_definitions(tokens: &mut Tokens) -> ParseResult<Vec<ast::Definition>> {
|
||||
tokens.many(parse_definition)
|
||||
}
|
||||
|
|
@ -40,6 +44,26 @@ fn parse_set(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_dot(tokens: &mut Tokens, expr: ast::Expr) -> Result<ast::Expr, Error> {
|
||||
if let Some(_dot) = tokens.next_if(&Token::Dot) {
|
||||
if let Some(labels) = tokens.many_sep_by(&Token::Dot, parse_identifier_label)? {
|
||||
Ok(labels
|
||||
.into_iter()
|
||||
.fold(expr, |acc, label| ast::Expr::Access {
|
||||
expr: Box::new(acc),
|
||||
field: label,
|
||||
}))
|
||||
} else {
|
||||
Err(Error::UnexpectedToken {
|
||||
expected: Token::Dot,
|
||||
got: tokens.next(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Ok(expr)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_definition(tokens: &mut Tokens) -> ParseResult<ast::Definition> {
|
||||
if let Some(_) = tokens.next_if(&Token::Let) {
|
||||
if let Some(name) = parse_identifier_name(tokens)? {
|
||||
|
|
@ -64,12 +88,13 @@ fn parse_definition(tokens: &mut Tokens) -> ParseResult<ast::Definition> {
|
|||
|
||||
fn parse_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
|
||||
if let Some(expr1) = parse_simple_expr(tokens)? {
|
||||
let expr1 = parse_dot(tokens, expr1)?;
|
||||
if let Some(args) = tokens.between(&Token::OpenParen, &Token::CloseParen, |ts| {
|
||||
ts.many_sep_by(&Token::Comma, parse_expr)
|
||||
})? {
|
||||
Ok(Some(ast::Expr::FunCall {
|
||||
func: Box::new(expr1),
|
||||
args: args,
|
||||
args,
|
||||
}))
|
||||
} else {
|
||||
Ok(parse_set(tokens)?
|
||||
|
|
@ -131,7 +156,20 @@ fn parse_block(tokens: &mut Tokens) -> ParseResult<Vec<ast::Statement>> {
|
|||
|
||||
fn parse_statement(tokens: &mut Tokens) -> ParseResult<ast::Statement> {
|
||||
tokens.one_of(vec![
|
||||
|tokens| Ok(parse_expr(tokens)?.map(ast::Statement::Expr)),
|
||||
|tokens| {
|
||||
if let Some(expr) = parse_expr(tokens)?.map(ast::Statement::Expr) {
|
||||
if let Some(_) = tokens.next_if(&Token::Semicolon) {
|
||||
Ok(Some(expr))
|
||||
} else {
|
||||
Err(Error::UnexpectedToken {
|
||||
expected: Token::Semicolon,
|
||||
got: tokens.next(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
},
|
||||
|tokens| Ok(parse_definition(tokens)?.map(ast::Statement::Let)),
|
||||
|tokens| {
|
||||
if let Some(_) = tokens.next_if(&Token::Return) {
|
||||
|
|
@ -321,7 +359,7 @@ mod tests {
|
|||
}
|
||||
#[test]
|
||||
fn fn_def() {
|
||||
let program = "fn(a1, boco, c_c) { 108 }".to_string();
|
||||
let program = "fn(a1, boco, c_c) { return 108; }".to_string();
|
||||
let result = parse(&mut scan(program), parse_expr);
|
||||
insta::assert_debug_snapshot!(result);
|
||||
}
|
||||
|
|
@ -333,7 +371,7 @@ mod tests {
|
|||
}
|
||||
#[test]
|
||||
fn paren_fncall() {
|
||||
let program = "(fn(a1, boco, c_c) { 108 })()".to_string();
|
||||
let program = "(fn(a1, boco, c_c) { return 108; })()".to_string();
|
||||
let result = parse(&mut scan(program), parse_expr);
|
||||
insta::assert_debug_snapshot!(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,15 @@ Ok(
|
|||
],
|
||||
body: Block(
|
||||
[
|
||||
Expr(
|
||||
Return(
|
||||
Some(
|
||||
Value(
|
||||
Int(
|
||||
108,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -25,13 +25,15 @@ Ok(
|
|||
],
|
||||
body: Block(
|
||||
[
|
||||
Expr(
|
||||
Return(
|
||||
Some(
|
||||
Value(
|
||||
Int(
|
||||
108,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue