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>> {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,15 @@ Ok(
|
||||||
],
|
],
|
||||||
body: Block(
|
body: Block(
|
||||||
[
|
[
|
||||||
Expr(
|
Return(
|
||||||
|
Some(
|
||||||
Value(
|
Value(
|
||||||
Int(
|
Int(
|
||||||
108,
|
108,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,15 @@ Ok(
|
||||||
],
|
],
|
||||||
body: Block(
|
body: Block(
|
||||||
[
|
[
|
||||||
Expr(
|
Return(
|
||||||
|
Some(
|
||||||
Value(
|
Value(
|
||||||
Int(
|
Int(
|
||||||
108,
|
108,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue