diff --git a/schala-lang/src/parsing/combinator.rs b/schala-lang/src/parsing/combinator.rs index 24e420e..444cc5f 100644 --- a/schala-lang/src/parsing/combinator.rs +++ b/schala-lang/src/parsing/combinator.rs @@ -32,6 +32,11 @@ fn fresh_id(span: &Span) -> Id { table_handle.fresh() } +fn fresh_id_rc(store_ref: &StoreRef) -> Id { + let mut table_handle = store_ref.borrow_mut(); + table_handle.fresh() +} + fn tok<'a, O>( input_parser: impl Parser, O, VerboseError>>, ) -> impl FnMut(Span<'a>) -> IResult, O, VerboseError>> { @@ -127,7 +132,50 @@ fn type_singleton_name(input: Span) -> ParseResult { } pub fn expression_kind(input: Span) -> ParseResult { - context("expression-kind", primary_expr)(input) + context("expression-kind", prefix_expr)(input) +} + +fn precedence_expr(input: Span) -> ParseResult { + map(pair(prefix_expr, many0(precedence_continuation)), + |(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!())(input) +} + +fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> { + pair(operator, prefix_expr)(input) +} + +fn operator(input: Span) -> ParseResult { + tok( + map( + tuple(( + not(tag("*/")), + recognize(many1(one_of("+-*/%<>=!$&|?^`"))), + )), |(_, sigil_span): ((), Span)| BinOp::from_sigil(sigil_span.fragment())))(input) +} + +fn prefix_op(input: Span) -> ParseResult { + tok( + map(recognize(one_of("+-!")), + |sigil: Span| PrefixOp::from_sigil(sigil.fragment())))(input) +} + +fn prefix_expr(input: Span) -> ParseResult { + let handle = input.extra.clone(); + context("prefix-expr", + map( + pair(opt(prefix_op), extended_expr), move |(prefix, expr)| { + if let Some(prefix) = prefix { + let expr = Expression::new(fresh_id_rc(&handle), expr); + ExpressionKind::PrefixExp(prefix, Box::new(expr)) + } else { + expr + } + }))(input) +} + +fn extended_expr(input: Span) -> ParseResult { + context("extended-expr", + primary_expr)(input) } fn primary_expr(input: Span) -> ParseResult { @@ -295,6 +343,26 @@ mod test { span!(expression_kind, " /*yolo*/ barnaby").unwrap().1, ExpressionKind::Value(qn!(barnaby)) ); + + + let source = "!4"; + let parsed = span!(expression_kind, source).map_err(|err| match err { + Err::Error(err) | Err::Failure(err) => { + let err = VerboseError { + errors: err.errors.into_iter().map(|(sp, kind)| (*sp.fragment(), kind)).collect(), + }; + nom::error::convert_error(source, err) + } + _ => panic!(), + }); + + if let Err(err) = parsed { + println!("{}", err); + panic!("parse error desu!"); + } + + assert_eq!(parsed.unwrap().1, ExpressionKind::PrefixExp(PrefixOp::from_sigil("!"), + Box::new(Expression::new(Default::default(), ExpressionKind::NatLiteral(4))))); } #[test]