diff --git a/schala-lang/language/src/parser.rs b/schala-lang/language/src/parser.rs index ce02067..260ac46 100644 --- a/schala-lang/language/src/parser.rs +++ b/schala-lang/language/src/parser.rs @@ -8,14 +8,14 @@ use nom::character::complete::{one_of, space0, alphanumeric0}; use nom::bytes::complete::{tag, take, take_while, take_until}; use nom::combinator::{map, map_res, value, opt, verify}; use nom::multi::{separated_list, separated_nonempty_list, many1, many0}; -//use nom::error::{ParseError, ErrorKind}; +use nom::error::{context, VerboseError}; use nom::branch::alt; use nom::sequence::{pair, delimited}; use crate::ast::*; use crate::builtin::Builtin; -type ParseResult<'a, T> = IResult<&'a str, T>; +type ParseResult<'a, T> = IResult<&'a str, T, VerboseError<&'a str>>; fn single_alphabetic_character(text: &str) -> ParseResult { @@ -40,7 +40,7 @@ fn identifier(text: &str) -> ParseResult> { const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|"; fn parse_binop(text: &str) -> ParseResult { - let (text, op): (_, Vec) = many1(one_of(OPERATOR_CHARS))(text)?; + let (text, op): (_, Vec) = context("binop yo", many1(one_of(OPERATOR_CHARS)))(text)?; let sigil: String = op.into_iter().collect(); Ok((text, BinOp::from_sigil(&sigil))) } @@ -110,7 +110,7 @@ fn literal(input: &str) -> ParseResult { fn paren_expr(text: &str) -> ParseResult { use nom::character::complete::char; - delimited(char('('), expression_kind, char(')'))(text) + context("Paren expression", delimited(char('('), expression_kind, char(')')))(text) } fn prefix_op(input: &str) -> ParseResult { @@ -181,32 +181,37 @@ fn prefix_expr(text: &str) -> ParseResult { } // 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) -> ParseResult { - let (mut outer_rest, mut lhs) = prefix_expr(input)?; - loop { - let (rest, _) = space0(outer_rest)?; - let (rest, maybe_binop) = opt(parse_binop)(rest)?; - let (new_precedence, binop) = match maybe_binop { - Some(binop) => (binop.precedence(), binop), - None => break, - }; +fn precedence_expr(text: &str) -> ParseResult { + fn inner_precedence_expr(input: &str, precedence: i32) -> ParseResult { + let (mut outer_rest, mut lhs) = prefix_expr(input)?; + loop { + let (rest, _) = space0(outer_rest)?; + let (rest, maybe_binop) = opt(parse_binop)(rest)?; + let (new_precedence, binop) = match maybe_binop { + Some(binop) => (binop.precedence(), binop), + None => break, + }; - if precedence >= new_precedence { - break; + if precedence >= new_precedence { + break; + } + let (rest, _) = space0(rest)?; + let (rest, rhs) = inner_precedence_expr(rest, new_precedence)?; + outer_rest = rest; + lhs = ExpressionKind::BinExp(binop, + bx!(Expression::new(ItemId::new(0), lhs)), + bx!(Expression::new(ItemId::new(0), rhs)) + ); } - let (rest, _) = space0(rest)?; - let (rest, rhs) = precedence_expr(rest, new_precedence)?; - outer_rest = rest; - lhs = ExpressionKind::BinExp(binop, - bx!(Expression::new(ItemId::new(0), lhs)), - bx!(Expression::new(ItemId::new(0), rhs)) - ); + Ok((outer_rest, lhs)) } - Ok((outer_rest, lhs)) + context("Precedence expression", + |input| inner_precedence_expr(input, BinOp::min_precedence()) + )(text) } -fn expression_kind(input: &str) -> ParseResult { - precedence_expr(input, BinOp::min_precedence()) +fn expression_kind(text: &str) -> ParseResult { + precedence_expr(text) } pub fn perform_parsing(input: &str) -> Result {