summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorKevin Butler <haqkrs@gmail.com>2015-11-12 02:43:43 +0000
committerKevin Butler <haqkrs@gmail.com>2016-01-16 00:57:12 +0000
commit24578e0fe555f267bef40528b8ac79bc7e898007 (patch)
tree336f724d68ee4dc447ced71e23636de956d16870 /src/libsyntax
parent9e3e43f3f6bb0d87da5f5b7fd92db0cc990e62a3 (diff)
downloadrust-24578e0fe555f267bef40528b8ac79bc7e898007.tar.gz
rust-24578e0fe555f267bef40528b8ac79bc7e898007.zip
libsyntax: accept only whitespace with the PATTERN_WHITE_SPACE property
This aligns with unicode recommendations and should be stable for all future
unicode releases. See http://unicode.org/reports/tr31/#R3.

This renames `libsyntax::lexer::is_whitespace` to `is_pattern_whitespace`
so potentially breaks users of libsyntax.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/lexer/comments.rs4
-rw-r--r--src/libsyntax/parse/lexer/mod.rs17
-rw-r--r--src/libsyntax/util/parser_testing.rs39
4 files changed, 32 insertions, 29 deletions
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 795f4044f6e..6fe741794cf 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -37,6 +37,7 @@ extern crate term;
 extern crate libc;
 #[macro_use] extern crate log;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
+extern crate rustc_unicode;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index e336c98f03c..629edced804 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -15,7 +15,7 @@ use codemap::{BytePos, CharPos, CodeMap, Pos};
 use errors;
 use parse::lexer::is_block_doc_comment;
 use parse::lexer::{StringReader, TokenAndSpan};
-use parse::lexer::{is_whitespace, Reader};
+use parse::lexer::{is_pattern_whitespace, Reader};
 use parse::lexer;
 use print::pprust;
 use str::char_at;
@@ -153,7 +153,7 @@ fn push_blank_line_comment(rdr: &StringReader, comments: &mut Vec<Comment>) {
 }
 
 fn consume_whitespace_counting_blank_lines(rdr: &mut StringReader, comments: &mut Vec<Comment>) {
-    while is_whitespace(rdr.curr) && !rdr.is_eof() {
+    while is_pattern_whitespace(rdr.curr) && !rdr.is_eof() {
         if rdr.col == CharPos(0) && rdr.curr_is('\n') {
             push_blank_line_comment(rdr, &mut *comments);
         }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 3e61aaff3c9..88a876cac73 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -16,6 +16,7 @@ use ext::tt::transcribe::tt_next_token;
 use parse::token::str_to_ident;
 use parse::token;
 use str::char_at;
+use rustc_unicode::property::Pattern_White_Space;
 
 use std::borrow::Cow;
 use std::char;
@@ -546,10 +547,10 @@ impl<'a> StringReader<'a> {
                 let c = self.scan_comment();
                 debug!("scanning a comment {:?}", c);
                 c
-            }
-            c if is_whitespace(Some(c)) => {
+            },
+            c if is_pattern_whitespace(Some(c)) => {
                 let start_bpos = self.last_pos;
-                while is_whitespace(self.curr) {
+                while is_pattern_whitespace(self.curr) {
                     self.bump();
                 }
                 let c = Some(TokenAndSpan {
@@ -1435,7 +1436,7 @@ impl<'a> StringReader<'a> {
     }
 
     fn consume_whitespace(&mut self) {
-        while is_whitespace(self.curr) && !self.is_eof() {
+        while is_pattern_whitespace(self.curr) && !self.is_eof() {
             self.bump();
         }
     }
@@ -1460,7 +1461,7 @@ impl<'a> StringReader<'a> {
     }
 
     fn consume_non_eol_whitespace(&mut self) {
-        while is_whitespace(self.curr) && !self.curr_is('\n') && !self.is_eof() {
+        while is_pattern_whitespace(self.curr) && !self.curr_is('\n') && !self.is_eof() {
             self.bump();
         }
     }
@@ -1591,8 +1592,10 @@ impl<'a> StringReader<'a> {
     }
 }
 
-pub fn is_whitespace(c: Option<char>) -> bool {
-    c.map_or(false, char::is_whitespace)
+// This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which
+// is guaranteed to be forward compatible. http://unicode.org/reports/tr31/#R3
+pub fn is_pattern_whitespace(c: Option<char>) -> bool {
+    c.map_or(false, Pattern_White_Space)
 }
 
 fn in_range(c: Option<char>, lo: char, hi: char) -> bool {
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index c19033f2347..a78950e959f 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -10,7 +10,7 @@
 
 use ast;
 use parse::{ParseSess,PResult,filemap_to_tts};
-use parse::new_parser_from_source_str;
+use parse::{lexer, new_parser_from_source_str};
 use parse::parser::Parser;
 use parse::token;
 use ptr::P;
@@ -97,8 +97,8 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool {
         let (a, b) = match (a_iter.peek(), b_iter.peek()) {
             (None, None) => return true,
             (None, _) => return false,
-            (Some(a), None) => {
-                if a.is_whitespace() {
+            (Some(&a), None) => {
+                if is_pattern_whitespace(a) {
                     break // trailing whitespace check is out of loop for borrowck
                 } else {
                     return false
@@ -107,11 +107,11 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool {
             (Some(&a), Some(&b)) => (a, b)
         };
 
-        if a.is_whitespace() && b.is_whitespace() {
+        if is_pattern_whitespace(a) && is_pattern_whitespace(b) {
             // skip whitespace for a and b
             scan_for_non_ws_or_end(&mut a_iter);
             scan_for_non_ws_or_end(&mut b_iter);
-        } else if a.is_whitespace() {
+        } else if is_pattern_whitespace(a) {
             // skip whitespace for a
             scan_for_non_ws_or_end(&mut a_iter);
         } else if a == b {
@@ -123,23 +123,18 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool {
     }
 
     // check if a has *only* trailing whitespace
-    a_iter.all(|c| c.is_whitespace())
+    a_iter.all(is_pattern_whitespace)
 }
 
 /// Advances the given peekable `Iterator` until it reaches a non-whitespace character
 fn scan_for_non_ws_or_end<I: Iterator<Item= char>>(iter: &mut Peekable<I>) {
-    loop {
-        match iter.peek() {
-            Some(c) if c.is_whitespace() => {} // fall through; borrowck
-            _ => return
-        }
-
+    while lexer::is_pattern_whitespace(iter.peek().cloned()) {
         iter.next();
     }
 }
 
-pub fn is_whitespace(c: char) -> bool {
-    c.is_whitespace()
+pub fn is_pattern_whitespace(c: char) -> bool {
+    lexer::is_pattern_whitespace(Some(c))
 }
 
 #[cfg(test)]
@@ -162,14 +157,18 @@ mod tests {
     }
 
     #[test]
-    fn more_whitespace() {
+    fn pattern_whitespace() {
         assert_eq!(matches_codepattern("","\x0C"), false);
-        assert_eq!(matches_codepattern("a b","a\u{2002}b"),true);
         assert_eq!(matches_codepattern("a b ","a   \u{0085}\n\t\r  b"),true);
         assert_eq!(matches_codepattern("a b","a   \u{0085}\n\t\r  b "),false);
-        assert_eq!(matches_codepattern("a   b","a\u{2002}b"),true);
-        assert_eq!(matches_codepattern("ab","a\u{2003}b"),false);
-        assert_eq!(matches_codepattern("a  \u{3000}b","ab"),true);
-        assert_eq!(matches_codepattern("\u{205F}a   b","ab"),true);
+    }
+
+    #[test]
+    fn non_pattern_whitespace() {
+        // These have the property 'White_Space' but not 'Pattern_White_Space'
+        assert_eq!(matches_codepattern("a b","a\u{2002}b"), false);
+        assert_eq!(matches_codepattern("a   b","a\u{2002}b"), false);
+        assert_eq!(matches_codepattern("\u{205F}a   b","ab"), false);
+        assert_eq!(matches_codepattern("a  \u{3000}b","ab"), false);
     }
 }