about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-10-21 14:21:54 -0700
committerbors <bors@rust-lang.org>2013-10-21 14:21:54 -0700
commit6dd6623b71ccee5b24117fa14df2bf3e5533e0c7 (patch)
treebdf4d3761cc767115812ec8aa2bb3f59e7b54437 /src/libsyntax/parse
parentece5028a8be4183ccb203dac59e734f1ca753714 (diff)
parent1dc3d0bf86c7e3db3e9b1cb9cfb1f344f9420f0f (diff)
downloadrust-6dd6623b71ccee5b24117fa14df2bf3e5533e0c7.tar.gz
rust-6dd6623b71ccee5b24117fa14df2bf3e5533e0c7.zip
auto merge of #9936 : madjar/rust/master, r=alexcrichton
This should close #9468.

I removed the test stating that nested comments should not be implemented.

I had a little chicken-and-egg problem because a comment of the std contains "/*", and adding support for nested comment creates a backward incompatibility in that case, so I had to use a dirty hack to get stage1 and stage2 to compile. This part should be revert when this commit lands in a snapshot.

This is my first non-typo contribution, so I'm open to any comment.
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));
+    }
+
 }