leap_lang/parser/
commentsparser.rs1use std::{
2 iter::{Enumerate, Peekable},
3 str::Chars,
4};
5
6use crate::{
7 leaptypes::{Comment, CommentType},
8 parser::position::Position,
9};
10
11pub fn parse(data: &str) -> Vec<Comment> {
13 let mut comments = vec![];
14 let mut chars = data.chars().enumerate().peekable();
15 while let Some((i, v)) = chars.next() {
17 if v == '/' {
18 let (comment, length) = parse_comment(&mut chars);
20 comments.push(Comment {
21 comment,
22 comment_type: CommentType::Line,
23 position: Position::new(i, length),
24 });
25 } else if v.is_whitespace() {
26 let mut v = v;
27 while let Some((_, next_v)) = chars.peek() {
28 if v == '\n' {
29 break;
30 };
31 if !next_v.is_whitespace() {
32 break;
34 }
35 v = if let Some((_, new_v)) = chars.next() {
36 new_v
37 } else {
38 break;
39 };
40 }
41 if v == '\n' {
42 comments.push(Comment {
45 comment: String::new(),
46 comment_type: CommentType::Separator,
47 position: Position::new(i, 0),
48 });
49 }
50 } else if !v.is_whitespace() {
51 for (i, v) in &mut chars {
54 match v {
55 '/' => {
56 let (comment, length) = parse_comment(&mut chars);
57 comments.push(Comment {
58 comment,
59 comment_type: CommentType::Trail,
60 position: Position::new(i, length),
61 });
62 break;
63 }
64 '\n' => break,
65 _ => {}
66 };
67 }
68 }
69 }
70 comments
71}
72
73fn parse_comment(chars: &mut Peekable<Enumerate<Chars>>) -> (String, usize) {
74 let mut comment_mark_len = 1;
75 while chars.peek().map(|(_, c)| *c == '-').unwrap_or(false) {
76 chars.next();
77 comment_mark_len += 1;
78 if comment_mark_len == 3 {
79 break;
81 }
82 }
83 let comment = consume_up_to_line_end(chars);
84 (comment.trim().to_owned(), comment_mark_len + comment.len())
85}
86
87fn consume_up_to_line_end(chars: &mut impl Iterator<Item = (usize, char)>) -> String {
88 let mut s = vec![];
89 for (_, v) in chars {
90 if v == '\n' {
91 break;
92 }
93 s.push(v);
94 }
95 s.into_iter().collect()
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_parse() {
104 assert_eq!(parse("aaa\nbbb\nccc").len(), 0);
105 let comments = parse(" /-- aaaa ");
106 assert_eq!(comments[0].position.start, 4);
107 assert_eq!(comments[0].position.length, 12);
108 assert_eq!(comments[0].comment, "aaaa");
109 assert_eq!(comments[0].comment_type, CommentType::Line);
110 let comments = parse(" /- aaaa ");
111 assert_eq!(comments[0].position.start, 4);
112 assert_eq!(comments[0].position.length, 11);
113 assert_eq!(comments[0].comment, "aaaa");
114 assert_eq!(comments[0].comment_type, CommentType::Line);
115 let comments = parse(" / aaaa ");
116 assert_eq!(comments[0].position.start, 4);
117 assert_eq!(comments[0].position.length, 10);
118 assert_eq!(comments[0].comment, "aaaa");
119 assert_eq!(comments[0].comment_type, CommentType::Line);
120 let comments = parse(" /--- aaaa ");
121 assert_eq!(comments[0].position.start, 4);
122 assert_eq!(comments[0].position.length, 13);
123 assert_eq!(comments[0].comment, "- aaaa");
124 assert_eq!(comments[0].comment_type, CommentType::Line);
125 let comments = parse(" /-- aaaa \n \nbbb");
126 assert_eq!(comments[0].position.start, 4);
127 assert_eq!(comments[0].position.length, 12);
128 assert_eq!(comments[0].comment, "aaaa");
129 assert_eq!(comments[0].comment_type, CommentType::Line);
130 assert_eq!(comments[1].position.start, 17);
131 assert_eq!(comments[1].position.length, 0);
132 assert_eq!(comments[1].comment_type, CommentType::Separator);
133 let comments = parse(" text /-- aaaa ");
134 assert_eq!(comments[0].position.start, 7);
135 assert_eq!(comments[0].position.length, 12);
136 assert_eq!(comments[0].comment, "aaaa");
137 assert_eq!(comments[0].comment_type, CommentType::Trail);
138 let comments = parse(".struct some-my-struct /-- text4\n\n/text5\n\nv: int");
139 assert_eq!(comments[1].comment_type, CommentType::Separator);
140 assert_eq!(comments[0].comment_type, CommentType::Trail);
141 assert_eq!(comments[1].comment_type, CommentType::Separator);
142 let comments = parse(".struct some-my-struct\n\n\n\n\n");
143 assert_eq!(comments.len(), 4);
144 let comments = parse("\n\n\n\n\n.struct some-my-struct");
145 assert_eq!(comments.len(), 5);
146 let comments = parse(".enum my-enum\n\n\n\n\n.struct some-my-struct");
147 assert_eq!(comments.len(), 4);
148 let comments = parse("/-- text");
149 assert_eq!(comments[0].comment, "text");
150 }
151}