@@ -6,6 +6,8 @@ enum TokenType {
66 RAW_STRING_LITERAL ,
77 FLOAT_LITERAL ,
88 BLOCK_COMMENT ,
9+ LINE_COMMENT ,
10+ DOC_COMMENT ,
911};
1012
1113void * tree_sitter_rust_external_scanner_create () { return NULL ; }
@@ -143,7 +145,100 @@ bool tree_sitter_rust_external_scanner_scan(void *payload, TSLexer *lexer,
143145
144146 if (lexer -> lookahead == '/' ) {
145147 advance (lexer );
148+
149+ if ((valid_symbols [LINE_COMMENT ] || valid_symbols [DOC_COMMENT ]) && lexer -> lookahead == '/' ) {
150+ advance (lexer );
151+
152+ bool started_with_slash = lexer -> lookahead == '/' ;
153+ switch (lexer -> lookahead ) {
154+ case '!' :
155+ case '/' : {
156+ advance (lexer );
157+
158+ // If three consecutive slashes were seen and this is the fourth one,
159+ // the line turns back to a normal comment.
160+ // The above rule does not apply for "//!" which is also a doc
161+ // comment, hence why it is relevant to track started_with_slash.
162+ if (started_with_slash == false || lexer -> lookahead != '/' ) {
163+ lexer -> result_symbol = DOC_COMMENT ;
164+
165+ while (true) {
166+ while (true) {
167+ switch (lexer -> lookahead ) {
168+ case '\n' : {
169+ lexer -> mark_end (lexer );
170+ advance (lexer );
171+ goto finished_doc_comment_line ;
172+ }
173+ case 0 : {
174+ goto doc_comment_exit ;
175+ }
176+ default : {
177+ advance (lexer );
178+ }
179+ }
180+ }
181+
182+ finished_doc_comment_line :
183+
184+ // Go forward until a newline or non-whitespace character is found.
185+ // That will be either the start of another node or the
186+ // continuation of this comment.
187+ while (lexer -> lookahead != '\n' && iswspace (lexer -> lookahead )) {
188+ lexer -> advance (lexer , false);
189+ };
190+
191+ if (lexer -> lookahead == '\n' ) {
192+ // Even if there's another comment ahead, it'll be part of a
193+ // separate node. Break here.
194+ break ;
195+ }
196+
197+ if (lexer -> lookahead == '/' ) {
198+ advance (lexer );
199+ if (lexer -> lookahead == '/' ) {
200+ advance (lexer );
201+ if (started_with_slash ) {
202+ if (lexer -> lookahead == '/' ) {
203+ advance (lexer );
204+ // If a fourth slash is found, the line turns back to a normal comment
205+ if (lexer -> lookahead == '/' ) {
206+ break ;
207+ }
208+ } else {
209+ break ;
210+ }
211+ } else if (lexer -> lookahead != '!' ) {
212+ break ;
213+ }
214+ } else {
215+ break ;
216+ }
217+ } else {
218+ break ;
219+ }
220+ }
221+ }
222+
223+ break ;
224+ }
225+ }
226+
227+ doc_comment_exit :
228+
229+ // Might have already processed a doc comment in the loop above
230+ if (lexer -> result_symbol != DOC_COMMENT ) {
231+ lexer -> result_symbol = LINE_COMMENT ;
232+ while (lexer -> lookahead != '\n' && lexer -> lookahead != 0 ) {
233+ advance (lexer );
234+ }
235+ }
236+
237+ return true;
238+ }
239+
146240 if (lexer -> lookahead != '*' ) return false;
241+
147242 advance (lexer );
148243
149244 bool after_star = false;
0 commit comments