Skip to content

Commit 4e35289

Browse files
committed
Restructure parsing of paths, which is quite tortured
1 parent e84e7a0 commit 4e35289

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
@@ -1706,50 +1706,18 @@ impl<'a> Parser<'a> {
17061706
// Parse any number of segments and bound sets. A segment is an
17071707
// identifier followed by an optional lifetime and a set of types.
17081708
// A bound set is a set of type parameter bounds.
1709-
let mut segments = Vec::new();
1710-
loop {
1711-
// First, parse an identifier.
1712-
let identifier = self.parse_ident();
1713-
1714-
// Parse the '::' before type parameters if it's required. If
1715-
// it is required and wasn't present, then we're done.
1716-
if mode == LifetimeAndTypesWithColons &&
1717-
!self.eat(&token::ModSep) {
1718-
segments.push(ast::PathSegment {
1719-
identifier: identifier,
1720-
lifetimes: Vec::new(),
1721-
types: OwnedSlice::empty(),
1722-
});
1723-
break
1709+
let segments = match mode {
1710+
LifetimeAndTypesWithoutColons |
1711+
LifetimeAndTypesAndBounds => {
1712+
self.parse_path_segments_without_colons()
17241713
}
1725-
1726-
// Parse the `<` before the lifetime and types, if applicable.
1727-
let (any_lifetime_or_types, lifetimes, types) = {
1728-
if mode != NoTypesAllowed && self.eat_lt(false) {
1729-
let (lifetimes, types) =
1730-
self.parse_generic_values_after_lt();
1731-
(true, lifetimes, OwnedSlice::from_vec(types))
1732-
} else {
1733-
(false, Vec::new(), OwnedSlice::empty())
1734-
}
1735-
};
1736-
1737-
// Assemble and push the result.
1738-
segments.push(ast::PathSegment {
1739-
identifier: identifier,
1740-
lifetimes: lifetimes,
1741-
types: types,
1742-
});
1743-
1744-
// We're done if we don't see a '::', unless the mode required
1745-
// a double colon to get here in the first place.
1746-
if !(mode == LifetimeAndTypesWithColons &&
1747-
!any_lifetime_or_types) {
1748-
if !self.eat(&token::ModSep) {
1749-
break
1750-
}
1714+
LifetimeAndTypesWithColons => {
1715+
self.parse_path_segments_with_colons()
17511716
}
1752-
}
1717+
NoTypesAllowed => {
1718+
self.parse_path_segments_without_types()
1719+
}
1720+
};
17531721

17541722
// Next, parse a plus and bounded type parameters, if
17551723
// applicable. We need to remember whether the separate was
@@ -1792,6 +1760,104 @@ impl<'a> Parser<'a> {
17921760
}
17931761
}
17941762

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

0 commit comments

Comments
 (0)