mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Add parens and function application
This commit is contained in:
parent
5db85ab23e
commit
21826c6e29
40
src/parse.rs
40
src/parse.rs
@ -3,9 +3,9 @@ use expr::Expr;
|
||||
|
||||
use std::char;
|
||||
|
||||
use combine::parser::char::{char, spaces, digit, hex_digit, HexDigit, alpha_num};
|
||||
use combine::parser::char::{char, space, spaces, digit, hex_digit, HexDigit, alpha_num};
|
||||
use combine::parser::repeat::{many, count_min_max};
|
||||
use combine::parser::item::{any, satisfy, satisfy_map, value};
|
||||
use combine::parser::item::{any, satisfy, satisfy_map, value, token};
|
||||
use combine::{choice, many1, parser, Parser, optional, between, unexpected_any, look_ahead, eof};
|
||||
use combine::error::{Consumed, ParseError};
|
||||
use combine::stream::{Stream};
|
||||
@ -17,7 +17,6 @@ pub fn expr<I>() -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
// TODO change to expr() to reproduce rust compiler bug
|
||||
expr_()
|
||||
}
|
||||
|
||||
@ -28,8 +27,24 @@ parser! {
|
||||
where [ I: Stream<Item = char> ]
|
||||
{
|
||||
choice((
|
||||
between(token('('), token(')'), expr()).and(
|
||||
// Parenthetical expressions can optionally be followed by
|
||||
// whitespace and an expr, meaning this is function application!
|
||||
optional(
|
||||
many1::<Vec<_>, _>(space())
|
||||
.with(expr())
|
||||
)
|
||||
).map(|(expr1, maybe_expr2)|
|
||||
match maybe_expr2 {
|
||||
None => expr1,
|
||||
Some(expr2) => {
|
||||
Expr::Apply(Box::new(expr1), Box::new(expr2))
|
||||
},
|
||||
}
|
||||
),
|
||||
number_literal(),
|
||||
ident().map(|str| Expr::Var(str)),
|
||||
var(),
|
||||
func(),
|
||||
)).skip(spaces()).and(
|
||||
// Optionally follow the expression with an operator,
|
||||
//
|
||||
@ -63,6 +78,23 @@ where I: Stream<Item = char>,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn var<I>() -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
ident().map(|str| Expr::Var(str))
|
||||
}
|
||||
|
||||
pub fn func<I>() -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
ident()
|
||||
.skip(many1::<Vec<_>, _>(space()))
|
||||
.and(expr())
|
||||
.map(|(str, arg)| Expr::Func(str, Box::new(arg)))
|
||||
}
|
||||
|
||||
pub fn ident<I>() -> impl Parser<Input = I, Output = String>
|
||||
where I: Stream<Item = char>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
|
@ -236,6 +236,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// VAR
|
||||
|
||||
fn expect_parsed_var<'a>(expected_str: &'a str) {
|
||||
let expected = expected_str.to_string();
|
||||
|
||||
@ -271,4 +273,51 @@ mod tests {
|
||||
expect_parsed_var_error("Foo");
|
||||
expect_parsed_var_error("Foo2Furious");
|
||||
}
|
||||
|
||||
// APPLY
|
||||
|
||||
// TODO write a bunch of parenthetical expression tests - try to repeat
|
||||
// all of the above tests except with parens too!
|
||||
// Also, verify them all with variable paren counts; ((foo)) should work.
|
||||
|
||||
// FUNC
|
||||
|
||||
|
||||
// TODO try it with operators, e.g. foo bar + baz qux
|
||||
|
||||
// fn expect_parsed_func<'a>(expected_str: &'a str) {
|
||||
// let expected = expected_str.to_string();
|
||||
|
||||
// assert_eq!(Ok((Var(expected), "")), parse::expr().parse(expected_str));
|
||||
// }
|
||||
|
||||
// fn expect_parsed_func_error<'a>(actual_str: &'a str) {
|
||||
// // TODO someday, this should work! It should parse as a variant.
|
||||
// assert!(
|
||||
// parse::expr().parse(actual_str).is_err(),
|
||||
// "Expected parsing error"
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn parse_var() {
|
||||
// expect_parsed_var("x");
|
||||
// expect_parsed_var("x2");
|
||||
// expect_parsed_var("foo");
|
||||
// expect_parsed_var("foo2furious");
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn parse_invalid_var() {
|
||||
// expect_parsed_var_error("5x");
|
||||
// expect_parsed_var_error("2foo2furious");
|
||||
// expect_parsed_var_error("2Foo2Furious");
|
||||
|
||||
// // TODO someday, capitalized vars should parse successfully as variants.
|
||||
// // At that point, turn these into variant tests!
|
||||
// expect_parsed_var_error("X");
|
||||
// expect_parsed_var_error("X2");
|
||||
// expect_parsed_var_error("Foo");
|
||||
// expect_parsed_var_error("Foo2Furious");
|
||||
// }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user