Skip to content

Commit e2295fe

Browse files
committed
---
yaml --- r: 153836 b: refs/heads/try2 c: 79e9f14 h: refs/heads/master v: v3
1 parent 5b6d20b commit e2295fe

File tree

5 files changed

+99
-8
lines changed

5 files changed

+99
-8
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: d7993153a49cf849cd41c259037f2d50ec2ab67c
8+
refs/heads/try2: 79e9f14abf50eecb7d3c53f10ad900615bb2d397
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/grammar/raw-string-literal-ambiguity.md

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
Rust's lexical grammar is not context-free. Raw string literals are the source
22
of the problem. Informally, a raw string literal is an `r`, followed by `N`
33
hashes (where N can be zero), a quote, any characters, then a quote followed
4-
by `N` hashes. This grammar describes this as best possible:
4+
by `N` hashes. Critically, once inside the first pair of quotes,
5+
another quote cannot be followed by `N` consecutive hashes. e.g.
6+
`r###""###"###` is invalid.
7+
8+
This grammar describes this as best possible:
59

610
R -> 'r' S
711
S -> '"' B '"'
@@ -22,8 +26,39 @@ accepted as one by the above grammar, using the derivation:
2226
(Where `T : U` means the rule `T` is applied, and `U` is the remainder of the
2327
string.) The difficulty arises from the fact that it is fundamentally
2428
context-sensitive. In particular, the context needed is the number of hashes.
25-
I know of no way to resolve this, but also have not come up with a proof that
26-
it is not context sensitive. Such a proof would probably use the pumping lemma
27-
for context-free languages, but I (cmr) could not come up with a proof after
28-
spending a few hours on it, and decided my time best spent elsewhere. Pull
29-
request welcome!
29+
30+
To prove that Rust's string literals are not context-free, we will use
31+
the fact that context-free languages are closed under intersection with
32+
regular languages, and the
33+
[pumping lemma for context-free languages](https://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages).
34+
35+
Consider the regular language `R = r#+""#*"#+`. If Rust's raw string literals are
36+
context-free, then their intersection with `R`, `R'`, should also be context-free.
37+
Therefore, to prove that raw string literals are not context-free,
38+
it is sufficient to prove that `R'` is not context-free.
39+
40+
The language `R'` is `{r#^n""#^m"#^n | m < n}`.
41+
42+
Assume `R'` *is* context-free. Then `R'` has some pumping length `p > 0` for which
43+
the pumping lemma applies. Consider the following string `s` in `R'`:
44+
45+
`r#^p""#^{p-1}"#^p`
46+
47+
e.g. for `p = 2`: `s = r##""#"##`
48+
49+
Then `s = uvwxy` for some choice of `uvwxy` such that `vx` is non-empty,
50+
`|vwx| < p+1`, and `uv^iwx^iy` is in `R'` for all `i >= 0`.
51+
52+
Neither `v` nor `x` can contain a `"` or `r`, as the number of these characters
53+
in any string in `R'` is fixed. So `v` and `x` contain only hashes.
54+
Consequently, of the three sequences of hashes, `v` and `x` combined
55+
can only pump two of them.
56+
If we ever choose the central sequence of hashes, then one of the outer sequences
57+
will not grow when we pump, leading to an imbalance between the outer sequences.
58+
Therefore, we must pump both outer sequences of hashes. However,
59+
there are `p+2` characters between these two sequences of hashes, and `|vwx|` must
60+
be less than `p+1`. Therefore we have a contradiction, and `R'` must not be
61+
context-free.
62+
63+
Since `R'` is not context-free, it follows that the Rust's raw string literals
64+
must not be context-free.

branches/try2/src/libcollections/ringbuf.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use core::cmp;
1919
use core::default::Default;
2020
use core::fmt;
2121
use core::iter::RandomAccessIterator;
22+
use core::iter;
23+
use std::hash::{Writer, Hash};
2224

2325
use {Deque, Collection, Mutable, MutableSeq};
2426
use vec::Vec;
@@ -450,6 +452,21 @@ impl<A: PartialEq> PartialEq for RingBuf<A> {
450452
}
451453
}
452454

455+
impl<A: PartialOrd> PartialOrd for RingBuf<A> {
456+
fn partial_cmp(&self, other: &RingBuf<A>) -> Option<Ordering> {
457+
iter::order::partial_cmp(self.iter(), other.iter())
458+
}
459+
}
460+
461+
impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
462+
fn hash(&self, state: &mut S) {
463+
self.len().hash(state);
464+
for elt in self.iter() {
465+
elt.hash(state);
466+
}
467+
}
468+
}
469+
453470
impl<A> FromIterator<A> for RingBuf<A> {
454471
fn from_iter<T: Iterator<A>>(iterator: T) -> RingBuf<A> {
455472
let (lower, _) = iterator.size_hint();
@@ -485,6 +502,7 @@ mod tests {
485502
use std::fmt::Show;
486503
use std::prelude::*;
487504
use std::gc::{GC, Gc};
505+
use std::hash;
488506
use test::Bencher;
489507
use test;
490508

@@ -912,6 +930,37 @@ mod tests {
912930
assert!(e == RingBuf::new());
913931
}
914932

933+
#[test]
934+
fn test_hash() {
935+
let mut x = RingBuf::new();
936+
let mut y = RingBuf::new();
937+
938+
x.push(1i);
939+
x.push(2);
940+
x.push(3);
941+
942+
y.push(0i);
943+
y.push(1i);
944+
y.pop_front();
945+
y.push(2);
946+
y.push(3);
947+
948+
assert!(hash::hash(&x) == hash::hash(&y));
949+
}
950+
951+
#[test]
952+
fn test_ord() {
953+
let x = RingBuf::new();
954+
let mut y = RingBuf::new();
955+
y.push(1i);
956+
y.push(2);
957+
y.push(3);
958+
assert!(x < y);
959+
assert!(y > x);
960+
assert!(x <= x);
961+
assert!(x >= x);
962+
}
963+
915964
#[test]
916965
fn test_show() {
917966
let ringbuf: RingBuf<int> = range(0i, 10).collect();

branches/try2/src/librustdoc/html/render.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,12 @@ impl DocFolder for Cache {
845845
}
846846
_ => (None, Some(self.stack.as_slice()))
847847
};
848+
let hidden_field = match item.inner {
849+
clean::StructFieldItem(clean::HiddenStructField) => true,
850+
_ => false
851+
};
848852
match parent {
849-
(parent, Some(path)) if !self.privmod => {
853+
(parent, Some(path)) if !self.privmod && !hidden_field => {
850854
self.search_index.push(IndexItem {
851855
ty: shortty(&item),
852856
name: s.to_string(),

branches/try2/src/libstd/collections/hashmap.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
18501850
///
18511851
/// # Example
18521852
///
1853+
/// ```
18531854
/// use std::collections::HashSet;
18541855
/// let mut set: HashSet<int> = HashSet::new();
18551856
/// ```
@@ -1863,6 +1864,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
18631864
///
18641865
/// # Example
18651866
///
1867+
/// ```
18661868
/// use std::collections::HashSet;
18671869
/// let mut set: HashSet<int> = HashSet::with_capacity(10);
18681870
/// ```
@@ -1920,6 +1922,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
19201922
///
19211923
/// # Example
19221924
///
1925+
/// ```
19231926
/// use std::collections::HashSet;
19241927
/// let mut set: HashSet<int> = HashSet::new();
19251928
/// set.reserve(10);

0 commit comments

Comments
 (0)