diff --git a/schala-lang/src/parsing/combinator.rs b/schala-lang/src/parsing/combinator.rs index 5f2e8cc..24e420e 100644 --- a/schala-lang/src/parsing/combinator.rs +++ b/schala-lang/src/parsing/combinator.rs @@ -1,17 +1,20 @@ +use std::{cell::RefCell, rc::Rc}; + use nom::{ - Err, branch::alt, - bytes::complete::{take_till, tag}, - character::complete::{alpha1, alphanumeric0, not_line_ending,none_of, char, one_of, space0, space1, multispace0, line_ending}, - combinator::{opt, peek, not, value, map, recognize}, - error::{context, VerboseError, ParseError}, - multi::{fold_many1, many1, many0, separated_list1, separated_list0}, - sequence::{pair, tuple, preceded}, - IResult, Parser, + bytes::complete::{tag, take_till}, + character::complete::{ + alpha1, alphanumeric0, char, line_ending, multispace0, none_of, not_line_ending, one_of, space0, + space1, + }, + combinator::{map, not, opt, peek, recognize, value}, + error::{context, ParseError, VerboseError}, + multi::{fold_many1, many0, many1, separated_list0, separated_list1}, + sequence::{pair, preceded, tuple}, + Err, IResult, Parser, }; use nom_locate::{position, LocatedSpan}; -use std::rc::Rc; -use std::cell::RefCell; + use crate::identifier::{Id, IdStore}; type StoreRef = Rc>>; @@ -29,92 +32,80 @@ fn fresh_id(span: &Span) -> Id { table_handle.fresh() } -fn tok<'a, O>(input_parser: impl Parser, O, VerboseError>>) -> impl FnMut(Span<'a>) --> IResult, O, VerboseError>> { - - context("tok", - map(tuple((ws0, input_parser)), |(_, output)| - output)) +fn tok<'a, O>( + input_parser: impl Parser, O, VerboseError>>, +) -> impl FnMut(Span<'a>) -> IResult, O, VerboseError>> { + context("tok", map(tuple((ws0, input_parser)), |(_, output)| output)) } fn kw<'a>(keyword_str: &'static str) -> impl FnMut(Span<'a>) -> ParseResult<()> { - context("keyword", - tok(value((), tag(keyword_str)))) + context("keyword", tok(value((), tag(keyword_str)))) } - // whitespace does consume at least one piece of whitespace - use ws0 for maybe none fn whitespace(input: Span) -> ParseResult<()> { - context("whitespace", - alt(( - block_comment, - line_comment, - value((), space1), - )))(input) + context("whitespace", alt((block_comment, line_comment, value((), space1))))(input) } fn ws0(input: Span) -> ParseResult<()> { - context("WS0", - value((), many0(whitespace)))(input) + context("WS0", value((), many0(whitespace)))(input) } fn line_comment(input: Span) -> ParseResult<()> { - value((), - tuple((tag("//"), not_line_ending)), - )(input) + value((), tuple((tag("//"), not_line_ending)))(input) } fn block_comment(input: Span) -> ParseResult<()> { - context("Block-comment", - value((), - tuple(( - tag("/*"), - many0(alt(( - value((), none_of("*/")), - value((), none_of("/*")), - block_comment, - ))), - tag("*/") - ))))(input) -} - -fn statement_delimiter(input: Span) -> ParseResult<()> { - tok(alt(( - value((), line_ending), - value((), char(';')) - )) + context( + "Block-comment", + value( + (), + tuple(( + tag("/*"), + many0(alt((value((), none_of("*/")), value((), none_of("/*")), block_comment))), + tag("*/"), + )), + ), )(input) } +fn statement_delimiter(input: Span) -> ParseResult<()> { + tok(alt((value((), line_ending), value((), char(';')))))(input) +} + fn block(input: Span) -> ParseResult { - context("block", - map( - tuple(( - tok(char('{')), - many0(statement_delimiter), - separated_list0(statement_delimiter, statement), - many0(statement_delimiter), - tok(char('}')), - )), |(_, _, items, _, _)| items.into()))(input) + context( + "block", + map( + tuple(( + tok(char('{')), + many0(statement_delimiter), + separated_list0(statement_delimiter, statement), + many0(statement_delimiter), + tok(char('}')), + )), + |(_, _, items, _, _)| items.into(), + ), + )(input) } fn statement(input: Span) -> ParseResult { let (input, pos) = position(input)?; let pos: usize = pos.location_offset(); let id = fresh_id(&input); - context("Parsing-statement", - map(expression, move |expr| Statement { - id, - location: pos.into(), - kind: StatementKind::Expression(expr), - }))(input) + context( + "Parsing-statement", + map(expression, move |expr| Statement { + id, + location: pos.into(), + kind: StatementKind::Expression(expr), + }), + )(input) } fn expression(input: Span) -> ParseResult { let id = fresh_id(&input); - map(pair(expression_kind, opt(type_anno)), move |(kind, maybe_anno)| { - Expression::new(id, kind) - })(input) + map(pair(expression_kind, opt(type_anno)), move |(kind, maybe_anno)| Expression::new(id, kind))(input) } fn type_anno(input: Span) -> ParseResult { @@ -140,13 +131,7 @@ pub fn expression_kind(input: Span) -> ParseResult { } fn primary_expr(input: Span) -> ParseResult { - context("primary-expr", - alt(( - number_literal, - bool_literal, - identifier_expr, - )))(input) - + context("primary-expr", alt((number_literal, bool_literal, identifier_expr)))(input) } fn identifier_expr(input: Span) -> ParseResult { @@ -155,27 +140,23 @@ fn identifier_expr(input: Span) -> ParseResult { fn qualified_identifier(input: Span) -> ParseResult { let id = fresh_id(&input); - tok( - map( - separated_list1(tag("::"), map(identifier, |x| rc_string(x.fragment()))), - move |items| QualifiedName { id, components: items } - ))(input) + tok(map(separated_list1(tag("::"), map(identifier, |x| rc_string(x.fragment()))), move |items| { + QualifiedName { id, components: items } + }))(input) } fn identifier(input: Span) -> ParseResult { - recognize( - tuple(( - alt((tag("_"), alpha1)), - alphanumeric0, - )))(input) + recognize(tuple((alt((tag("_"), alpha1)), alphanumeric0)))(input) } fn bool_literal(input: Span) -> ParseResult { - context("bool-literal", - alt(( - map(kw("true"), |_| ExpressionKind::BoolLiteral(true)), - map(kw("false"), |_| ExpressionKind::BoolLiteral(false)), - )))(input) + context( + "bool-literal", + alt(( + map(kw("true"), |_| ExpressionKind::BoolLiteral(true)), + map(kw("false"), |_| ExpressionKind::BoolLiteral(false)), + )), + )(input) } fn number_literal(input: Span) -> ParseResult { @@ -282,14 +263,11 @@ mod test { } macro_rules! span { - ($func:expr, $input:expr) => { - { + ($func:expr, $input:expr) => {{ let id_store: IdStore = IdStore::new(); - let span = Span::new_extra($input, - Rc::new(RefCell::new(id_store))); + let span = Span::new_extra($input, Rc::new(RefCell::new(id_store))); $func(span).map(|(span, x)| (*span.fragment(), x)) - } - }; + }}; } #[test] @@ -313,7 +291,10 @@ mod test { } assert_eq!(span!(expression_kind, " /*gay*/ true").unwrap().1, ExpressionKind::BoolLiteral(true)); - assert_eq!(span!(expression_kind, " /*yolo*/ barnaby").unwrap().1, ExpressionKind::Value(qn!(barnaby))); + assert_eq!( + span!(expression_kind, " /*yolo*/ barnaby").unwrap().1, + ExpressionKind::Value(qn!(barnaby)) + ); } #[test] @@ -328,10 +309,12 @@ mod test { }"#; let parsed = span!(block, 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() }; + let err = VerboseError { + errors: err.errors.into_iter().map(|(sp, kind)| (*sp.fragment(), kind)).collect(), + }; nom::error::convert_error(source, err) - }, - _ => panic!() + } + _ => panic!(), }); if let Err(err) = parsed { @@ -339,16 +322,35 @@ mod test { panic!("parse error desu!"); } - assert_eq!(parsed.unwrap().1, vec![ - Statement { id: Default::default(), location: - Default::default(), kind: StatementKind::Expression(Expression::new(Default::default(), - ExpressionKind::NatLiteral(45))) }, - Statement { id: Default::default(), location: - Default::default(), kind: StatementKind::Expression(Expression::new(Default::default(), - ExpressionKind::NatLiteral(11))) }, - Statement { id: Default::default(), location: - Default::default(), kind: StatementKind::Expression(Expression::new(Default::default(), - ExpressionKind::NatLiteral(15))) }, - ].into()); + assert_eq!( + parsed.unwrap().1, + vec![ + Statement { + id: Default::default(), + location: Default::default(), + kind: StatementKind::Expression(Expression::new( + Default::default(), + ExpressionKind::NatLiteral(45) + )) + }, + Statement { + id: Default::default(), + location: Default::default(), + kind: StatementKind::Expression(Expression::new( + Default::default(), + ExpressionKind::NatLiteral(11) + )) + }, + Statement { + id: Default::default(), + location: Default::default(), + kind: StatementKind::Expression(Expression::new( + Default::default(), + ExpressionKind::NatLiteral(15) + )) + }, + ] + .into() + ); } } diff --git a/schala-lang/src/parsing/test.rs b/schala-lang/src/parsing/test.rs index 299b129..4169e1e 100644 --- a/schala-lang/src/parsing/test.rs +++ b/schala-lang/src/parsing/test.rs @@ -1352,5 +1352,3 @@ fn backtick_operators() { assert_eq!(output, vec![digit!("1"), op!("plus"), digit!("2")]); } */ - -