dot and return

This commit is contained in:
me 2025-12-16 23:43:43 +02:00
parent 08a0a8a5db
commit 4738ad92bf
3 changed files with 54 additions and 12 deletions

View file

@ -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);
}

View file

@ -24,10 +24,12 @@ Ok(
],
body: Block(
[
Expr(
Value(
Int(
108,
Return(
Some(
Value(
Int(
108,
),
),
),
),

View file

@ -25,10 +25,12 @@ Ok(
],
body: Block(
[
Expr(
Value(
Int(
108,
Return(
Some(
Value(
Int(
108,
),
),
),
),