diff --git a/schala-lang/language/src/parser.rs b/schala-lang/language/src/parser.rs index 849fb7a..ce02067 100644 --- a/schala-lang/language/src/parser.rs +++ b/schala-lang/language/src/parser.rs @@ -15,18 +15,20 @@ use nom::sequence::{pair, delimited}; use crate::ast::*; use crate::builtin::Builtin; +type ParseResult<'a, T> = IResult<&'a str, T>; -fn single_alphabetic_character(text: &str) -> IResult<&str, char> { + +fn single_alphabetic_character(text: &str) -> ParseResult { let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphabetic()).unwrap_or(false)); map(p, |s: &str| s.chars().nth(0).unwrap())(text) } -fn single_alphanumeric_character(text: &str) -> IResult<&str, char> { +fn single_alphanumeric_character(text: &str) -> ParseResult { let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphanumeric() || c == '_').unwrap_or(false)); map(p, |s: &str| s.chars().nth(0).unwrap())(text) } -fn identifier(text: &str) -> IResult<&str, Rc> { +fn identifier(text: &str) -> ParseResult> { use nom::character::complete::char; map(alt(( pair(char('_'), many1(single_alphanumeric_character)), @@ -37,37 +39,37 @@ fn identifier(text: &str) -> IResult<&str, Rc> { } const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|"; -fn parse_binop(input: &str) -> IResult<&str, BinOp> { - let (rest, op): (_, Vec) = many1(one_of(OPERATOR_CHARS))(input)?; +fn parse_binop(text: &str) -> ParseResult { + let (text, op): (_, Vec) = many1(one_of(OPERATOR_CHARS))(text)?; let sigil: String = op.into_iter().collect(); - Ok((rest, BinOp::from_sigil(&sigil))) + Ok((text, BinOp::from_sigil(&sigil))) } -fn parse_bool_literal(input: &str) -> IResult<&str, ExpressionKind> { +fn parse_bool_literal(text: &str) -> ParseResult { let p = alt(( value(true, tag("true")), value(false, tag("false")) )); - map(p, ExpressionKind::BoolLiteral)(input) + map(p, ExpressionKind::BoolLiteral)(text) } -fn parse_number_literal(input: &str) -> IResult<&str, ExpressionKind> { +fn parse_number_literal(text: &str) -> ParseResult { let num_lit = many1(alt(( map(one_of("1234567890"), |s: char| Some(s)), map(nom::character::complete::char('_'), |_| None) ))); - let (rest, n) = map_res(num_lit, + let (text, n) = map_res(num_lit, |digits: Vec>| { let num_str: String = digits.into_iter().filter_map(|x| x).collect(); u64::from_str_radix(&num_str, 10) - })(input)?; + })(text)?; - Ok((rest, ExpressionKind::NatLiteral(n))) + Ok((text, ExpressionKind::NatLiteral(n))) } -fn parse_binary_literal(input: &str) -> IResult<&str, ExpressionKind> { +fn parse_binary_literal(input: &str) -> ParseResult { let (rest, _) = tag("0b")(input)?; let (rest, n): (&str, u64) = map_res( take_while(|c: char| c == '0' || c == '1'), @@ -77,7 +79,7 @@ fn parse_binary_literal(input: &str) -> IResult<&str, ExpressionKind> { Ok((rest, expr)) } -fn parse_hex_literal(input: &str) -> IResult<&str, ExpressionKind> { +fn parse_hex_literal(input: &str) -> ParseResult { let (rest, _) = tag("0x")(input)?; let (rest, n): (&str, u64) = map_res( take_while(|c: char| c.is_digit(16)), @@ -87,7 +89,7 @@ fn parse_hex_literal(input: &str) -> IResult<&str, ExpressionKind> { Ok((rest, expr)) } -fn parse_string_literal(text: &str) -> IResult<&str, ExpressionKind> { +fn parse_string_literal(text: &str) -> ParseResult { use nom::character::complete::char; let (text, string_output) = delimited( char('"'), take_until("\""), char('"') @@ -96,7 +98,7 @@ fn parse_string_literal(text: &str) -> IResult<&str, ExpressionKind> { Ok((text, expr)) } -fn literal(input: &str) -> IResult<&str, ExpressionKind> { +fn literal(input: &str) -> ParseResult { alt(( parse_string_literal, parse_hex_literal, @@ -106,18 +108,18 @@ fn literal(input: &str) -> IResult<&str, ExpressionKind> { ))(input) } -fn paren_expr(text: &str) -> IResult<&str, ExpressionKind> { +fn paren_expr(text: &str) -> ParseResult { use nom::character::complete::char; delimited(char('('), expression_kind, char(')'))(text) } -fn prefix_op(input: &str) -> IResult<&str, PrefixOp> { +fn prefix_op(input: &str) -> ParseResult { use nom::character::complete::char; let p = alt((char('+'), char('-'), char('!'))); map(p, |sigil| PrefixOp::from_str(&sigil.to_string()).unwrap())(input) } -fn identifier_expr(text: &str) -> IResult<&str, ExpressionKind> { +fn identifier_expr(text: &str) -> ParseResult { let (text, qualified_identifier) = map( qualified_identifier_list, |components| QualifiedName { id: ItemId::new(0), components } @@ -127,11 +129,11 @@ fn identifier_expr(text: &str) -> IResult<&str, ExpressionKind> { Ok((text, exp.kind)) } -fn qualified_identifier_list(text: &str) -> IResult<&str, Vec>> { +fn qualified_identifier_list(text: &str) -> ParseResult>> { separated_nonempty_list(tag("::"), identifier)(text) } -fn primary_expr(text: &str) -> IResult<&str, ExpressionKind> { +fn primary_expr(text: &str) -> ParseResult { // primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr alt(( @@ -141,7 +143,7 @@ fn primary_expr(text: &str) -> IResult<&str, ExpressionKind> { ))(text) } -fn invocation_argument(text: &str) -> IResult<&str, InvocationArgument> { +fn invocation_argument(text: &str) -> ParseResult { use nom::character::complete::char; alt(( value(InvocationArgument::Ignored, pair(char('_'), alphanumeric0)), @@ -151,7 +153,7 @@ fn invocation_argument(text: &str) -> IResult<&str, InvocationArgument> { ))(text) } -fn call_expr(text: &str) -> IResult<&str, ExpressionKind> { +fn call_expr(text: &str) -> ParseResult { use nom::character::complete::char; let (text, expr) = primary_expr(text)?; let (text, call_part) = opt( @@ -166,7 +168,7 @@ fn call_expr(text: &str) -> IResult<&str, ExpressionKind> { Ok((text, output)) } -fn prefix_expr(text: &str) -> IResult<&str, ExpressionKind> { +fn prefix_expr(text: &str) -> ParseResult { let (text, pfx) = delimited(space0, opt(prefix_op), space0)(text)?; let (text, result) = call_expr(text)?; match pfx { @@ -179,7 +181,7 @@ fn prefix_expr(text: &str) -> IResult<&str, ExpressionKind> { } // this implements Pratt parsing, see http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ -fn precedence_expr(input: &str, precedence: i32) -> IResult<&str, ExpressionKind> { +fn precedence_expr(input: &str, precedence: i32) -> ParseResult { let (mut outer_rest, mut lhs) = prefix_expr(input)?; loop { let (rest, _) = space0(outer_rest)?; @@ -203,7 +205,7 @@ fn precedence_expr(input: &str, precedence: i32) -> IResult<&str, ExpressionKind Ok((outer_rest, lhs)) } -fn expression_kind(input: &str) -> IResult<&str, ExpressionKind> { +fn expression_kind(input: &str) -> ParseResult { precedence_expr(input, BinOp::min_precedence()) }