parse record
This commit is contained in:
parent
fb37bae29f
commit
8836f95149
2 changed files with 78 additions and 1 deletions
|
|
@ -78,6 +78,7 @@ fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
|
|||
parse_string,
|
||||
parse_bool,
|
||||
parse_fn,
|
||||
parse_record,
|
||||
|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> {
|
||||
if let Some(LocatedToken {
|
||||
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> {
|
||||
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 {
|
||||
token: Token::Identifier(string),
|
||||
..
|
||||
}) = tokens.next_if(&Token::Identifier("".into()))
|
||||
{
|
||||
Ok(Some(ast::Name(string)))
|
||||
Ok(Some(string))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
|
@ -195,6 +238,12 @@ mod tests {
|
|||
insta::assert_debug_snapshot!(result);
|
||||
}
|
||||
#[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() {
|
||||
let program = "fn(a1, boco, c_c) { 108 }".to_string();
|
||||
let result = parse(&mut scan(program), parse_expr);
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue