scarf_parser/parser/
utils.rs

1// =======================================================================
2// utils.rs
3// =======================================================================
4// Helper functions for implementing parsers
5
6use crate::*;
7use chumsky::input::ValueInput;
8use chumsky::prelude::*;
9use scarf_syntax::Span;
10use scarf_syntax::*;
11
12// Fold parsed text into a vector
13pub fn foldl_vector<T>(mut a: Vec<T>, b: T) -> Vec<T> {
14    a.push(b);
15    a
16}
17
18// Span conversion
19pub fn convert_span(simple_span: ParserSpan) -> Span {
20    simple_span.into()
21}
22
23// A parser for matching extra nodes
24pub fn extra_node_parser<'a, I>() -> impl Parser<'a, I, Vec<(ExtraNode<'a>, Span)>, ParserError<'a>>
25where
26    I: ValueInput<'a, Token = Token<'a>, Span = ParserSpan>,
27{
28    select! {
29        Token::OnelineComment(text) = e => (ExtraNode::OnelineComment(text), convert_span(e.span())),
30        Token::BlockComment(text) = e => (ExtraNode::BlockComment(text), convert_span(e.span())),
31        Token::Newline = e => (ExtraNode::Newline, convert_span(e.span()))
32    }
33    .labelled("whitespace/comment")
34    .repeated()
35    .collect::<Vec<(ExtraNode<'a>, Span)>>()
36}
37
38// A mapping function for replacing extra nodes in metadata
39pub fn replace_nodes<'a>(
40    old_metadata: Metadata<'a>,
41    new_nodes: Vec<(ExtraNode<'a>, Span)>,
42) -> Metadata<'a> {
43    Metadata {
44        span: old_metadata.span,
45        extra_nodes: new_nodes,
46    }
47}
48
49// A parser for matching a token and extra nodes, producing metadata
50pub fn token<'a, I>(token_to_match: Token<'a>) -> impl Parser<'a, I, Metadata<'a>, ParserError<'a>>
51where
52    I: ValueInput<'a, Token = Token<'a>, Span = ParserSpan>,
53{
54    just(token_to_match)
55        .map_with(|_, e| Metadata {
56            span: convert_span(e.span()),
57            extra_nodes: Vec::default(),
58        })
59        .then(extra_node_parser())
60        .map(|(a, b)| replace_nodes(a, b))
61}
62
63pub fn todo_parser<'a, I>() -> impl Parser<'a, I, (), ParserError<'a>>
64where
65    I: ValueInput<'a, Token = Token<'a>, Span = ParserSpan>,
66{
67    // Match against nothing
68    just(Token::Error).to(())
69}