Skip to content

Commit ae037bc

Browse files
committed
Restructure parsing of paths, which is quite tortured
1 parent 82fb413 commit ae037bc

File tree

1 file changed

+108
-42
lines changed

1 file changed

+108
-42
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 108 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,50 +1712,18 @@ impl<'a> Parser<'a> {
17121712
// Parse any number of segments and bound sets. A segment is an
17131713
// identifier followed by an optional lifetime and a set of types.
17141714
// A bound set is a set of type parameter bounds.
1715-
let mut segments = Vec::new();
1716-
loop {
1717-
// First, parse an identifier.
1718-
let identifier = self.parse_ident();
1719-
1720-
// Parse the '::' before type parameters if it's required. If
1721-
// it is required and wasn't present, then we're done.
1722-
if mode == LifetimeAndTypesWithColons &&
1723-
!self.eat(&token::ModSep) {
1724-
segments.push(ast::PathSegment {
1725-
identifier: identifier,
1726-
lifetimes: Vec::new(),
1727-
types: OwnedSlice::empty(),
1728-
});
1729-
break
1715+
let segments = match mode {
1716+
LifetimeAndTypesWithoutColons |
1717+
LifetimeAndTypesAndBounds => {
1718+
self.parse_path_segments_without_colons()
17301719
}
1731-
1732-
// Parse the `<` before the lifetime and types, if applicable.
1733-
let (any_lifetime_or_types, lifetimes, types) = {
1734-
if mode != NoTypesAllowed && self.eat_lt(false) {
1735-
let (lifetimes, types) =
1736-
self.parse_generic_values_after_lt();
1737-
(true, lifetimes, OwnedSlice::from_vec(types))
1738-
} else {
1739-
(false, Vec::new(), OwnedSlice::empty())
1740-
}
1741-
};
1742-
1743-
// Assemble and push the result.
1744-
segments.push(ast::PathSegment {
1745-
identifier: identifier,
1746-
lifetimes: lifetimes,
1747-
types: types,
1748-
});
1749-
1750-
// We're done if we don't see a '::', unless the mode required
1751-
// a double colon to get here in the first place.
1752-
if !(mode == LifetimeAndTypesWithColons &&
1753-
!any_lifetime_or_types) {
1754-
if !self.eat(&token::ModSep) {
1755-
break
1756-
}
1720+
LifetimeAndTypesWithColons => {
1721+
self.parse_path_segments_with_colons()
17571722
}
1758-
}
1723+
NoTypesAllowed => {
1724+
self.parse_path_segments_without_types()
1725+
}
1726+
};
17591727

17601728
// Next, parse a plus and bounded type parameters, if
17611729
// applicable. We need to remember whether the separate was
@@ -1798,6 +1766,104 @@ impl<'a> Parser<'a> {
17981766
}
17991767
}
18001768

1769+
/// Examples:
1770+
/// - `a::b<T,U>::c<V,W>`
1771+
/// - `a::b<T,U>::c(V) -> W`
1772+
/// - `a::b<T,U>::c(V)`
1773+
pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
1774+
let mut segments = Vec::new();
1775+
loop {
1776+
// First, parse an identifier.
1777+
let identifier = self.parse_ident();
1778+
1779+
// Parse types, optionally.
1780+
let (lifetimes, types) = if self.eat_lt(false) {
1781+
self.parse_generic_values_after_lt()
1782+
} else if false && self.eat(&token::LParen) {
1783+
let mut types = self.parse_seq_to_end(
1784+
&token::RParen,
1785+
seq_sep_trailing_allowed(token::Comma),
1786+
|p| p.parse_ty(true));
1787+
1788+
if self.eat(&token::RArrow) {
1789+
types.push(self.parse_ty(true))
1790+
}
1791+
1792+
(Vec::new(), types)
1793+
} else {
1794+
(Vec::new(), Vec::new())
1795+
};
1796+
1797+
// Assemble and push the result.
1798+
segments.push(ast::PathSegment { identifier: identifier,
1799+
lifetimes: lifetimes,
1800+
types: OwnedSlice::from_vec(types), });
1801+
1802+
// Continue only if we see a `::`
1803+
if !self.eat(&token::ModSep) {
1804+
return segments;
1805+
}
1806+
}
1807+
}
1808+
1809+
/// Examples:
1810+
/// - `a::b::<T,U>::c`
1811+
pub fn parse_path_segments_with_colons(&mut self) -> Vec<ast::PathSegment> {
1812+
let mut segments = Vec::new();
1813+
loop {
1814+
// First, parse an identifier.
1815+
let identifier = self.parse_ident();
1816+
1817+
// If we do not see a `::`, stop.
1818+
if !self.eat(&token::ModSep) {
1819+
segments.push(ast::PathSegment { identifier: identifier,
1820+
lifetimes: Vec::new(),
1821+
types: OwnedSlice::empty() });
1822+
return segments;
1823+
}
1824+
1825+
// Check for a type segment.
1826+
if self.eat_lt(false) {
1827+
// Consumed `a::b::<`, go look for types
1828+
let (lifetimes, types) = self.parse_generic_values_after_lt();
1829+
segments.push(ast::PathSegment { identifier: identifier,
1830+
lifetimes: lifetimes,
1831+
types: OwnedSlice::from_vec(types) });
1832+
1833+
// Consumed `a::b::<T,U>`, check for `::` before proceeding
1834+
if !self.eat(&token::ModSep) {
1835+
return segments;
1836+
}
1837+
} else {
1838+
// Consumed `a::`, go look for `b`
1839+
segments.push(ast::PathSegment { identifier: identifier,
1840+
lifetimes: Vec::new(),
1841+
types: OwnedSlice::empty() });
1842+
}
1843+
}
1844+
}
1845+
1846+
1847+
/// Examples:
1848+
/// - `a::b::c`
1849+
pub fn parse_path_segments_without_types(&mut self) -> Vec<ast::PathSegment> {
1850+
let mut segments = Vec::new();
1851+
loop {
1852+
// First, parse an identifier.
1853+
let identifier = self.parse_ident();
1854+
1855+
// Assemble and push the result.
1856+
segments.push(ast::PathSegment { identifier: identifier,
1857+
lifetimes: Vec::new(),
1858+
types: OwnedSlice::empty(), });
1859+
1860+
// If we do not see a `::`, stop.
1861+
if !self.eat(&token::ModSep) {
1862+
return segments;
1863+
}
1864+
}
1865+
}
1866+
18011867
/// parses 0 or 1 lifetime
18021868
pub fn parse_opt_lifetime(&mut self) -> Option<ast::Lifetime> {
18031869
match self.token {

0 commit comments

Comments
 (0)