wagon_parser/parser/
helpers.rs1use wagon_lexer::productions::Productions;
2use wagon_utils::string_vec;
3use super::{Parse, LexerBridge, ParseResult, Tokens, Spannable, WagParseError, ResultNext, Peek, ResultPeek};
4
5impl Parse for String {
6 fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> {
7 Ok(lexer.next_result()?.to_string())
8 }
9}
10
11pub(super) trait TokenMapper {
13 fn token_to_enum(token: &Tokens) -> Option<Self> where Self: Sized;
14}
15
16type ParseFunc<T> = Box<dyn FnOnce(&mut LexerBridge) -> ParseResult<T>>;
18
19fn __between_right<T>(lexer: &mut LexerBridge, right: &Tokens, fun: ParseFunc<T>) -> ParseResult<T> {
20 let resp = fun(lexer)?;
21 let span = lexer.span();
22 let token = lexer.peek_result()?;
23 if token == right {
24 lexer.next();
25 Ok(resp)
26 } else {
27 Err(WagParseError::Unexpected { span, offender: token.clone(), expected: string_vec!(right) })
28 }
29}
30
31fn __between<T>(lexer: &mut LexerBridge, left: &Tokens, right: &Tokens, fun: ParseFunc<T>) -> ParseResult<T> {
32 let span = lexer.span();
33 let token = lexer.peek_result()?;
34 if token == left {
35 lexer.next();
36 __between_right(lexer, right, fun)
37 } else {
38 Err(WagParseError::Unexpected { span, offender: token.clone(), expected: string_vec!(left) })
39 }
40}
41
42pub(super) fn between_right<T: Parse>(lexer: &mut LexerBridge, right: &Tokens) -> ParseResult<T> {
44 __between_right(lexer, right, Box::new(|x| T::parse(x)))
45}
46
47pub(super) fn between<T: Parse>(lexer: &mut LexerBridge, left: &Tokens, right: &Tokens) -> ParseResult<T> {
49 __between(lexer, left, right, Box::new(|x| T::parse(x)))
50}
51
52pub(super) fn between_sep<T: Parse>(lexer: &mut LexerBridge, left: &Tokens, right: &Tokens, sep: Tokens) -> ParseResult<Vec<T>> {
54 __between(lexer, left, right, Box::new(|x| T::parse_sep(x, sep)))
55}
56
57#[macro_export]
59macro_rules! either_token {
60 ($variant:ident($($arg:tt)*)) => {
61 wagon_lexer::Tokens::ProductionToken(wagon_lexer::productions::Productions::$variant($($arg)*))
62 | wagon_lexer::Tokens::MathToken(wagon_lexer::math::Math::$variant($($arg)*))
63 };
64 ($variant:ident) => {
65 wagon_lexer::Tokens::ProductionToken(wagon_lexer::productions::Productions::$variant)
66 | wagon_lexer::Tokens::MathToken(wagon_lexer::math::Math::$variant)
67 };
68}
69
70#[macro_export]
72macro_rules! either_token_ref {
73 ($variant:ident($($arg:tt)*)) => {
74 &wagon_lexer::Tokens::ProductionToken(wagon_lexer::productions::Productions::$variant($($arg)*))
75 | &wagon_lexer::Tokens::MathToken(wagon_lexer::math::Math::$variant($($arg)*))
76 };
77 ($variant:ident) => {
78 &wagon_lexer::Tokens::ProductionToken(wagon_lexer::productions::Productions::$variant)
79 | &wagon_lexer::Tokens::MathToken(wagon_lexer::math::Math::$variant)
80 };
81}
82
83#[macro_export]
85macro_rules! any_token {
86 ($variant:ident($($arg:tt)*)) => {
87 either_token!($variant)
88 | wagon_lexer::Tokens::MetadataToken(wagon_lexer::metadata::Metadata::$variant($($arg)*))
89 };
90 ($variant:ident) => {
91 either_token!($variant)
92 | wagon_lexer::Tokens::MetadataToken(wagon_lexer::metadata::Metadata::$variant)
93 };
94}
95
96#[allow(clippy::unnested_or_patterns)]
97pub(super) fn check_semi(lexer: &mut LexerBridge) -> Result<(), WagParseError> {
99 if lexer.next_if(|x| matches!(x, Ok(any_token!(Semi)))).is_none() {
100 Err(WagParseError::Unexpected { span: lexer.span(), offender: lexer.next_result()?, expected: string_vec![Tokens::ProductionToken(Productions::Semi)] })
101 } else {
102 Ok(())
103 }
104}
105
106#[allow(clippy::unnested_or_patterns)]
107pub(super) fn check_colon(lexer: &mut LexerBridge) -> Result<(), WagParseError> {
109 if lexer.next_if(|x| matches!(x, Ok(any_token!(Colon)))).is_none() {
110 Err(WagParseError::Unexpected { span: lexer.span(), offender: lexer.next_result()?, expected: string_vec![Tokens::ProductionToken(Productions::Colon)] })
111 } else {
112 Ok(())
113 }
114}