@@ -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,87 @@ 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+ goto finished_doc_comment_line ;
170+ }
171+ case 0 : {
172+ goto doc_comment_exit ;
173+ }
174+ default : {
175+ advance (lexer );
176+ }
177+ }
178+ }
179+
180+ finished_doc_comment_line :
181+
182+ lexer -> mark_end (lexer );
183+ advance (lexer );
184+ if (lexer -> lookahead == '/' ) {
185+ advance (lexer );
186+ if (lexer -> lookahead == '/' ) {
187+ advance (lexer );
188+ if (started_with_slash ) {
189+ if (lexer -> lookahead == '/' ) {
190+ advance (lexer );
191+ // If a fourth slash is found, the line turns back to a normal comment
192+ if (lexer -> lookahead == '/' ) {
193+ break ;
194+ }
195+ } else {
196+ break ;
197+ }
198+ } else if (lexer -> lookahead != '!' ) {
199+ break ;
200+ }
201+ } else {
202+ break ;
203+ }
204+ } else {
205+ break ;
206+ }
207+ }
208+ }
209+
210+ break ;
211+ }
212+ }
213+
214+ doc_comment_exit :
215+
216+ // Might have already processed a doc comment in the loop above
217+ if (lexer -> result_symbol != DOC_COMMENT ) {
218+ lexer -> result_symbol = LINE_COMMENT ;
219+ while (lexer -> lookahead != '\n' && lexer -> lookahead != 0 ) {
220+ advance (lexer );
221+ }
222+ }
223+
224+ return true;
225+ }
226+
146227 if (lexer -> lookahead != '*' ) return false;
228+
147229 advance (lexer );
148230
149231 bool after_star = false;
0 commit comments