parse record

This commit is contained in:
me 2025-12-16 15:48:23 +02:00
parent fb37bae29f
commit 8836f95149
2 changed files with 78 additions and 1 deletions

View file

@ -78,6 +78,7 @@ fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
parse_string, parse_string,
parse_bool, parse_bool,
parse_fn, parse_fn,
parse_record,
|t| t.between(&Token::OpenParen, &Token::CloseParen, parse_expr), |t| t.between(&Token::OpenParen, &Token::CloseParen, parse_expr),
]) ])
} }
@ -110,6 +111,40 @@ fn parse_args(tokens: &mut Tokens) -> ParseResult<Vec<ast::Arg>> {
}) })
} }
fn parse_record(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
if let Some(vect) = tokens.between(&Token::OpenCurly, &Token::CloseCurly, |tokens| {
tokens.many_sep_by(&Token::Comma, parse_record_field_expr)
})? {
Ok(Some(ast::Expr::Value(ast::Value::Record(ast::Record(
vect.into_iter().collect(),
)))))
} else {
Ok(None)
}
}
fn parse_record_field_expr(tokens: &mut Tokens) -> ParseResult<(ast::Label, ast::Expr)> {
if let Some(label) = parse_identifier_label(tokens)? {
if let Some(_) = tokens.next_if(&Token::Colon) {
if let Some(expr) = parse_expr(tokens)? {
Ok(Some((label, expr)))
} else {
Err(Error::UnexpectedTokenForParser(
"parse_record_field_expr_expr".into(),
tokens.next(),
))
}
} else {
Err(Error::UnexpectedToken {
expected: Token::Colon,
got: tokens.next(),
})
}
} else {
Ok(None)
}
}
fn parse_string(tokens: &mut Tokens) -> ParseResult<ast::Expr> { fn parse_string(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
if let Some(LocatedToken { if let Some(LocatedToken {
token: Token::String(string), token: Token::String(string),
@ -143,12 +178,20 @@ fn parse_identifier_arg(tokens: &mut Tokens) -> ParseResult<ast::Arg> {
} }
fn parse_identifier_name(tokens: &mut Tokens) -> ParseResult<ast::Name> { fn parse_identifier_name(tokens: &mut Tokens) -> ParseResult<ast::Name> {
Ok(parse_identifier_string(tokens)?.map(|string| ast::Name(string)))
}
fn parse_identifier_label(tokens: &mut Tokens) -> ParseResult<ast::Label> {
Ok(parse_identifier_string(tokens)?.map(|string| ast::Label(string)))
}
fn parse_identifier_string(tokens: &mut Tokens) -> ParseResult<String> {
if let Some(LocatedToken { if let Some(LocatedToken {
token: Token::Identifier(string), token: Token::Identifier(string),
.. ..
}) = tokens.next_if(&Token::Identifier("".into())) }) = tokens.next_if(&Token::Identifier("".into()))
{ {
Ok(Some(ast::Name(string))) Ok(Some(string))
} else { } else {
Ok(None) Ok(None)
} }
@ -195,6 +238,12 @@ mod tests {
insta::assert_debug_snapshot!(result); insta::assert_debug_snapshot!(result);
} }
#[test] #[test]
fn record() {
let program = "{ hello: 17, hi: \"cool\"}".to_string();
let result = parse(&mut scan(program), parse_expr);
insta::assert_debug_snapshot!(result);
}
#[test]
fn fn_def() { fn fn_def() {
let program = "fn(a1, boco, c_c) { 108 }".to_string(); let program = "fn(a1, boco, c_c) { 108 }".to_string();
let result = parse(&mut scan(program), parse_expr); let result = parse(&mut scan(program), parse_expr);

View file

@ -0,0 +1,28 @@
---
source: src/parser/parser.rs
expression: result
---
Ok(
Value(
Record(
Record(
{
Label(
"hello",
): Value(
Int(
17,
),
),
Label(
"hi",
): Value(
String(
"cool",
),
),
},
),
),
),
)