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>> { fn parse_definitions(tokens: &mut Tokens) -> ParseResult<Vec<ast::Definition>> {
tokens.many(parse_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> { fn parse_definition(tokens: &mut Tokens) -> ParseResult<ast::Definition> {
if let Some(_) = tokens.next_if(&Token::Let) { if let Some(_) = tokens.next_if(&Token::Let) {
if let Some(name) = parse_identifier_name(tokens)? { 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> { fn parse_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
if let Some(expr1) = parse_simple_expr(tokens)? { 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| { if let Some(args) = tokens.between(&Token::OpenParen, &Token::CloseParen, |ts| {
ts.many_sep_by(&Token::Comma, parse_expr) ts.many_sep_by(&Token::Comma, parse_expr)
})? { })? {
Ok(Some(ast::Expr::FunCall { Ok(Some(ast::Expr::FunCall {
func: Box::new(expr1), func: Box::new(expr1),
args: args, args,
})) }))
} else { } else {
Ok(parse_set(tokens)? 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> { fn parse_statement(tokens: &mut Tokens) -> ParseResult<ast::Statement> {
tokens.one_of(vec![ 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| Ok(parse_definition(tokens)?.map(ast::Statement::Let)),
|tokens| { |tokens| {
if let Some(_) = tokens.next_if(&Token::Return) { if let Some(_) = tokens.next_if(&Token::Return) {
@ -321,7 +359,7 @@ mod tests {
} }
#[test] #[test]
fn fn_def() { 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); let result = parse(&mut scan(program), parse_expr);
insta::assert_debug_snapshot!(result); insta::assert_debug_snapshot!(result);
} }
@ -333,7 +371,7 @@ mod tests {
} }
#[test] #[test]
fn paren_fncall() { 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); let result = parse(&mut scan(program), parse_expr);
insta::assert_debug_snapshot!(result); insta::assert_debug_snapshot!(result);
} }

View file

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

View file

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