about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorGeorges Dubus <georges.dubus@compiletoi.net>2013-10-18 22:51:57 +0200
committerGeorges Dubus <georges.dubus@compiletoi.net>2013-10-21 21:58:34 +0200
commit1dc3d0bf86c7e3db3e9b1cb9cfb1f344f9420f0f (patch)
tree32542a3752890539ccd9982df86ee153e079b335 /src/libsyntax/parse
parent69e46f3aa922fa651fe53b36a295011c590f09e4 (diff)
downloadrust-1dc3d0bf86c7e3db3e9b1cb9cfb1f344f9420f0f.tar.gz
rust-1dc3d0bf86c7e3db3e9b1cb9cfb1f344f9420f0f.zip
Add support for nested comments
Fixes #9468.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/lexer.rs74
1 files changed, 41 insertions, 33 deletions
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index a43e018cf49..8edc171fcac 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -373,49 +373,49 @@ pub fn is_block_non_doc_comment(s: &str) -> bool {
 fn consume_block_comment(rdr: @mut StringReader)
                       -> Option<TokenAndSpan> {
     // block comments starting with "/**" or "/*!" are doc-comments
-    let res = if rdr.curr == '*' || rdr.curr == '!' {
-        let start_bpos = rdr.pos - BytePos(3u);
-        while !(rdr.curr == '*' && nextch(rdr) == '/') && !is_eof(rdr) {
-            bump(rdr);
-        }
+    let is_doc_comment = rdr.curr == '*' || rdr.curr == '!';
+    let start_bpos = rdr.pos - BytePos(if is_doc_comment {3u} else {2u});
+
+    let mut level: int = 1;
+    while level > 0 {
         if is_eof(rdr) {
-            fatal_span(rdr, start_bpos, rdr.last_pos,
-                       ~"unterminated block doc-comment");
-        } else {
+            let msg = if is_doc_comment {
+                ~"unterminated block doc-comment"
+            } else {
+                ~"unterminated block comment"
+            };
+            fatal_span(rdr, start_bpos, rdr.last_pos, msg);
+        } else if rdr.curr == '/' && nextch(rdr) == '*' {
+            level += 1;
             bump(rdr);
             bump(rdr);
-            do with_str_from(rdr, start_bpos) |string| {
-                // but comments with only "*"s between two "/"s are not
-                if !is_block_non_doc_comment(string) {
-                    Some(TokenAndSpan{
-                         tok: token::DOC_COMMENT(str_to_ident(string)),
-                         sp: codemap::mk_sp(start_bpos, rdr.pos)
-                         })
-                } else {
-                    None
-                }
-            }
+        } else if rdr.curr == '*' && nextch(rdr) == '/' {
+            level -= 1;
+            bump(rdr);
+            bump(rdr);
+        } else {
+            bump(rdr);
         }
-    } else {
-        let start_bpos = rdr.last_pos - BytePos(2u);
-        loop {
-            if is_eof(rdr) {
-                fatal_span(rdr, start_bpos, rdr.last_pos,
-                           ~"unterminated block comment");
-            }
-            if rdr.curr == '*' && nextch(rdr) == '/' {
-                bump(rdr);
-                bump(rdr);
-                break;
+    }
+
+    let res = if is_doc_comment {
+        do with_str_from(rdr, start_bpos) |string| {
+            // but comments with only "*"s between two "/"s are not
+            if !is_block_non_doc_comment(string) {
+                Some(TokenAndSpan{
+                        tok: token::DOC_COMMENT(str_to_ident(string)),
+                        sp: codemap::mk_sp(start_bpos, rdr.pos)
+                    })
             } else {
-                bump(rdr);
+                None
             }
         }
+    } else {
         None
     };
-    // restart whitespace munch.
 
-   if res.is_some() { res } else { consume_whitespace_and_comments(rdr) }
+    // restart whitespace munch.
+    if res.is_some() { res } else { consume_whitespace_and_comments(rdr) }
 }
 
 fn scan_exponent(rdr: @mut StringReader, start_bpos: BytePos) -> Option<~str> {
@@ -1056,4 +1056,12 @@ mod test {
         assert!(!is_line_non_doc_comment("/// blah"));
         assert!(is_line_non_doc_comment("////"));
     }
+
+    #[test] fn nested_block_comments() {
+        let env = setup(@"/* /* */ */'a'");
+        let TokenAndSpan {tok, sp: _} =
+            env.string_reader.next_token();
+        assert_eq!(tok,token::LIT_CHAR('a' as u32));
+    }
+
 }