rustidy_parse/
whitespace.rs1use {
5 crate::{self as rustidy_parse, Parse, ParseError, Parser, ParserError, ParserTag},
6 rustidy_util::{
7 ArenaIdx,
8 whitespace::{
9 BlockComment,
10 Comment,
11 LineComment,
12 PureWhitespace,
13 Whitespace,
14 WhitespaceInner,
15 },
16 },
17};
18
19impl Parse for Whitespace {
20 type Error = WhitespaceError;
21
22 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
23 if parser.has_tag(ParserTag::SkipWhitespace) {
24 let (s, ()) = parser.update_with(|_| ());
25 let inner = WhitespaceInner { first: PureWhitespace(s), rest: vec![], };
26 let idx = ArenaIdx::new(inner);
27
28 return Ok(Self(idx));
29 }
30
31 parser
32 .parse::<ArenaIdx<WhitespaceInner>>()
33 .map(Self).map_err(WhitespaceError)
34 }
35}
36
37#[derive(Debug, derive_more::From, ParseError)]
38#[parse_error(transparent)]
39pub struct WhitespaceError(ParserError<ArenaIdx<WhitespaceInner>>);
40
41
42impl Parse for WhitespaceInner {
43 type Error = WhitespaceInnerError;
44
45 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
46 let first = parser.parse::<PureWhitespace>()?;
47 let mut rest = vec![];
48 while let Ok(comment) = parser.try_parse::<Comment>()? {
49 let pure = parser.parse::<PureWhitespace>()?;
50 rest.push((comment, pure));
51 }
52
53 Ok(Self { first, rest })
54 }
55}
56
57#[derive(Debug, derive_more::From, ParseError)]
58pub enum WhitespaceInnerError {
59 Pure(ParserError<PureWhitespace>),
60 Comment(ParserError<Comment>),
61}
62
63
64impl Parse for Comment {
65 type Error = CommentError;
66
67 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
68 let block_err = match parser.try_parse().map_err(CommentError::Block)? {
69 Ok(block) => return Ok(Self::Block(block)),
70 Err(err) => err,
71 };
72
73 let line_err = match parser.try_parse().map_err(CommentError::Line)? {
74 Ok(line) => return Ok(Self::Line(line)),
75 Err(err) => err,
76 };
77
78 Err(
79 CommentError::None { block: block_err, line: line_err, }
80 )
81 }
82}
83
84#[derive(Debug, ParseError)]
85pub enum CommentError {
86 #[parse_error(transparent)]
87 Block(ParserError<BlockComment>),
88 #[parse_error(transparent)]
89 Line(ParserError<LineComment>),
90
91 #[parse_error(fmt = "Expected a block or line comment")]
92 #[parse_error(multiple)]
93 None {
94 block: ParserError<BlockComment>,
95 line: ParserError<LineComment>,
96 },
97}
98
99
100impl Parse for BlockComment {
101 type Error = BlockCommentError;
102
103 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
104 parser.try_update_with(|s| {
105 let is_doc_comment = (s.starts_with("/**") && !s.starts_with("/***") && !s.starts_with("/**/")) || s.starts_with("/*!");
106
107 match s.strip_prefix("/*") {
108 Some(rest) if !is_doc_comment => {
109 *s = rest;
110 let mut depth = 1;
111 while depth != 0 {
112 let close_idx = s
113 .find("*/")
114 .ok_or(BlockCommentError::MissingCommentEnd)?;
115
116 match s[..close_idx].find("/*") {
117 Some(open_idx) => {
118 *s = &s[open_idx + 2..];
119 depth += 1;
120 },
121 None => {
122 *s = &s[close_idx + 2..];
123 depth -= 1;
124 },
125 }
126 }
127 Ok(())
128 },
129 _ => Err(BlockCommentError::NoComment),
130 }
131 }).map(|(s, ())| Self(s))
132 }
133}
134
135#[derive(Debug, ParseError)]
136pub enum BlockCommentError {
137 #[parse_error(fmt = "Expected `/*` (except `/*!` or `/**`)")]
138 NoComment,
139 #[parse_error(fmt = "Expected `*/` after `/*`")]
140 #[parse_error(fatal)]
141 MissingCommentEnd,
142}
143
144
145impl Parse for LineComment {
146 type Error = LineCommentError;
147
148 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
149 parser.try_update_with(|s| {
150 let is_doc_comment = (s.starts_with("///") && !s.starts_with("////")) || s.starts_with("//!");
151 match s.starts_with("//") && !is_doc_comment {
152 true => {
153 *s = match s.find('\n') {
154 Some(idx) => &s[idx + 1..],
155 None => &s[s.len()..],
156 };
157 Ok(())
158 },
159 false => Err(LineCommentError::NoComment),
160 }
161 }).map(|(s, ())| Self(s))
162 }
163}
164
165#[derive(Debug, ParseError)]
166pub enum LineCommentError {
167 #[parse_error(fmt = "Expected `//` (except `///` or `//!`)")]
168 NoComment,
169}
170
171
172impl Parse for PureWhitespace {
173 type Error = !;
174
175 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
176 let (s, ()) = parser.update_with(|s| *s = s.trim_start());
177 Ok(Self(s))
178 }
179}