about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-13 18:31:51 -0700
committerbors <bors@rust-lang.org>2014-05-13 18:31:51 -0700
commitb2b383cab5959b1ec331e1d77583fa944b7fd593 (patch)
tree79540b4f5f7e125a260b9ca00f25e796241425f9 /src/libsyntax/parse
parentcb115ac2d4f57d8b590c8d46d8f9e2958ed9a527 (diff)
parentf09592a5d154177f0c9d739c9fe60742ec4cd951 (diff)
downloadrust-b2b383cab5959b1ec331e1d77583fa944b7fd593.tar.gz
rust-b2b383cab5959b1ec331e1d77583fa944b7fd593.zip
auto merge of #14187 : alexcrichton/rust/rollup, r=alexcrichton
Closes #14184 (std: Move the owned module from core to std)
Closes #14183 (Allow blocks in const expressions)
Closes #14176 (Add tests for from_bits.)
Closes #14175 (Replaced ~T by Box<T> in manual)
Closes #14173 (Implements Default trait for BigInt and BigUint)
Closes #14171 (Fix #8391)
Closes #14159 (Clean up unicode code in libstd)
Closes #14126 (docs: Add a not found page)
Closes #14123 (add a line to the example to clarify semantics)
Closes #14106 (Pretty printer improvements)
Closes #14083 (rustllvm: Add LLVMRustArrayType)
Closes #13957 (io: Implement process wait timeouts)
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs63
-rw-r--r--src/libsyntax/parse/token.rs8
2 files changed, 59 insertions, 12 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2201b08f2ca..92e5f8da6aa 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -587,16 +587,64 @@ impl<'a> Parser<'a> {
                 self.replace_token(token::BINOP(token::OR), lo, self.span.hi)
             }
             _ => {
-                let token_str = self.this_token_to_str();
-                let found_token =
+                let found_token = self.this_token_to_str();
+                let token_str =
                     Parser::token_to_str(&token::BINOP(token::OR));
                 self.fatal(format!("expected `{}`, found `{}`",
-                                   found_token,
-                                   token_str))
+                                   token_str, found_token))
             }
         }
     }
 
+    // Attempt to consume a `<`. If `<<` is seen, replace it with a single
+    // `<` and continue. If a `<` is not seen, return false.
+    //
+    // This is meant to be used when parsing generics on a path to get the
+    // starting token. The `force` parameter is used to forcefully break up a
+    // `<<` token. If `force` is false, then `<<` is only broken when a lifetime
+    // shows up next. For example, consider the expression:
+    //
+    //      foo as bar << test
+    //
+    // The parser needs to know if `bar <<` is the start of a generic path or if
+    // it's a left-shift token. If `test` were a lifetime, then it's impossible
+    // for the token to be a left-shift, but if it's not a lifetime, then it's
+    // considered a left-shift.
+    //
+    // The reason for this is that the only current ambiguity with `<<` is when
+    // parsing closure types:
+    //
+    //      foo::<<'a> ||>();
+    //      impl Foo<<'a> ||>() { ... }
+    fn eat_lt(&mut self, force: bool) -> bool {
+        match self.token {
+            token::LT => { self.bump(); true }
+            token::BINOP(token::SHL) => {
+                let next_lifetime = self.look_ahead(1, |t| match *t {
+                    token::LIFETIME(..) => true,
+                    _ => false,
+                });
+                if force || next_lifetime {
+                    let lo = self.span.lo + BytePos(1);
+                    self.replace_token(token::LT, lo, self.span.hi);
+                    true
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
+
+    fn expect_lt(&mut self) {
+        if !self.eat_lt(true) {
+            let found_token = self.this_token_to_str();
+            let token_str = Parser::token_to_str(&token::LT);
+            self.fatal(format!("expected `{}`, found `{}`",
+                               token_str, found_token))
+        }
+    }
+
     // Parse a sequence bracketed by `|` and `|`, stopping before the `|`.
     fn parse_seq_to_before_or<T>(
                               &mut self,
@@ -1500,7 +1548,7 @@ impl<'a> Parser<'a> {
 
             // Parse the `<` before the lifetime and types, if applicable.
             let (any_lifetime_or_types, lifetimes, types) = {
-                if mode != NoTypesAllowed && self.eat(&token::LT) {
+                if mode != NoTypesAllowed && self.eat_lt(false) {
                     let (lifetimes, types) =
                         self.parse_generic_values_after_lt();
                     (true, lifetimes, OwnedSlice::from_vec(types))
@@ -1948,7 +1996,7 @@ impl<'a> Parser<'a> {
                     hi = self.span.hi;
                     self.bump();
                     let (_, tys) = if self.eat(&token::MOD_SEP) {
-                        self.expect(&token::LT);
+                        self.expect_lt();
                         self.parse_generic_values_after_lt()
                     } else {
                         (Vec::new(), Vec::new())
@@ -2241,9 +2289,6 @@ impl<'a> Parser<'a> {
               ExprVec(..) if m == MutImmutable => {
                 ExprVstore(e, ExprVstoreSlice)
               }
-              ExprLit(lit) if lit_is_str(lit) && m == MutImmutable => {
-                ExprVstore(e, ExprVstoreSlice)
-              }
               ExprVec(..) if m == MutMutable => {
                 ExprVstore(e, ExprVstoreMutSlice)
               }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 3888ed6b8d1..68ce8cb2bc1 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -203,9 +203,11 @@ pub fn to_str(t: &Token) -> StrBuf {
           res.push_char('\'');
           res
       }
-      LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
-      LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
-      LIT_INT_UNSUFFIXED(i) => { i.to_str().to_strbuf() }
+      LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i),
+                                               ast_util::ForceSuffix),
+      LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u),
+                                                 ast_util::ForceSuffix),
+      LIT_INT_UNSUFFIXED(i) => { (i as u64).to_str().to_strbuf() }
       LIT_FLOAT(s, t) => {
         let mut body = StrBuf::from_str(get_ident(s).get());
         if body.as_slice().ends_with(".") {