Skip to content

Commit 0c71d65

Browse files
committed
gccrs: refactor function qualifier parsing
gcc/rust/ChangeLog * parse/rust-parse-impl.hxx: Refactor qualifier parsing * parse/rust-parse.h: (parse_function_qualifiers) Likewise
1 parent a4602f3 commit 0c71d65

File tree

2 files changed

+159
-93
lines changed

2 files changed

+159
-93
lines changed

gcc/rust/parse/rust-parse-impl.hxx

Lines changed: 146 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,101 +1638,154 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
16381638
}
16391639

16401640
return std::unique_ptr<AST::Function> (new AST::Function (
1641-
std::move (function_name), std::move (*qualifiers.value ()),
1641+
std::move (function_name), std::move (qualifiers.value ()),
16421642
std::move (generic_params), std::move (function_params),
16431643
std::move (return_type), std::move (where_clause), std::move (body),
16441644
std::move (vis), std::move (outer_attrs), locus, is_external));
16451645
}
16461646

16471647
// Parses function or method qualifiers (i.e. const, unsafe, and extern).
16481648
template <typename ManagedTokenSource>
1649-
tl::expected<std::unique_ptr<AST::FunctionQualifiers>, Parse::Error::Node>
1649+
tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
16501650
Parser<ManagedTokenSource>::parse_function_qualifiers ()
1651+
{
1652+
location_t locus = lexer.peek_token ()->get_locus ();
1653+
1654+
auto parsed = parse_function_qualifiers_raw (locus);
1655+
if (!parsed)
1656+
return tl::unexpected<Parse::Error::Node> (parsed.error ());
1657+
1658+
return function_qualifiers_from_keywords (locus, std::move (parsed->first),
1659+
std::move (parsed->second));
1660+
}
1661+
1662+
// Take the list of parsed function qualifiers and convert it to
1663+
// the corrresponding flags to pass to the AST item constructor.
1664+
//
1665+
// This assumes ``keywords`` contains only those tokens that
1666+
// map to qualifiers.
1667+
template <typename ManagedTokenSource>
1668+
tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
1669+
Parser<ManagedTokenSource>::function_qualifiers_from_keywords (
1670+
location_t locus, const std::vector<TokenId> keywords, std::string abi)
16511671
{
16521672
Default default_status = Default::No;
16531673
Async async_status = Async::No;
16541674
Const const_status = Const::No;
16551675
Unsafety unsafe_status = Unsafety::Normal;
16561676
bool has_extern = false;
1657-
std::string abi;
16581677

1659-
// collect all qualifiers before checking the order to allow for a better
1660-
// error message
1661-
std::vector<TokenId> found_order;
1678+
for (auto qualifier : keywords)
1679+
{
1680+
switch (qualifier)
1681+
{
1682+
case IDENTIFIER:
1683+
// only "default" is valid in this context
1684+
default_status = Default::Yes;
1685+
continue;
1686+
case CONST:
1687+
const_status = Const::Yes;
1688+
continue;
1689+
case ASYNC:
1690+
async_status = Async::Yes;
1691+
continue;
1692+
case UNSAFE:
1693+
unsafe_status = Unsafety::Unsafe;
1694+
continue;
1695+
case EXTERN_KW:
1696+
has_extern = true;
1697+
continue;
1698+
default:
1699+
// non-qualifier token in input
1700+
rust_unreachable ();
1701+
}
1702+
}
16621703

1663-
const_TokenPtr t;
1664-
location_t locus = lexer.peek_token ()->get_locus ();
1704+
return AST::FunctionQualifiers (locus, default_status, async_status,
1705+
const_status, unsafe_status, has_extern,
1706+
std::move (abi));
1707+
}
1708+
1709+
// this consumes as many function qualifier tokens while ensuring
1710+
// uniqueness.
1711+
template <typename ManagedTokenSource>
1712+
tl::expected<std::pair<std::vector<TokenId>, std::string>, Parse::Error::Node>
1713+
Parser<ManagedTokenSource>::parse_function_qualifiers_raw (location_t locus)
1714+
{
1715+
std::vector<TokenId> found_order;
1716+
std::string abi;
16651717

16661718
// this will terminate on duplicates or the first non-qualifier token
16671719
while (true)
16681720
{
1669-
const TokenId token_id = lexer.peek_token ()->get_id ();
1670-
1671-
if (std::find (found_order.cbegin (), found_order.cend (), token_id)
1672-
!= found_order.cend ())
1673-
{
1674-
// qualifiers mustn't appear twice
1675-
Error error (lexer.peek_token ()->get_locus (),
1676-
"encountered duplicate function qualifier %qs",
1677-
lexer.peek_token ()->get_token_description ());
1678-
add_error (std::move (error));
1679-
1680-
return tl::unexpected<Parse::Error::Node> (
1681-
Parse::Error::Node::MALFORMED);
1682-
}
1721+
auto token = lexer.peek_token ();
1722+
const TokenId token_id = token->get_id ();
1723+
location_t locus = lexer.peek_token ()->get_locus ();
16831724

16841725
switch (token_id)
16851726
{
16861727
case IDENTIFIER:
1687-
if (lexer.peek_token ()->get_str () != Values::WeakKeywords::DEFAULT)
1728+
if (token->get_str () != Values::WeakKeywords::DEFAULT)
16881729
{
1689-
// only "default" is valid in this context
1730+
// only "default" is valid in this context, so this must
1731+
// be a non-qualifier keyword
16901732
goto done;
16911733
}
1692-
default_status = Default::Yes;
1693-
break;
1734+
// fallthrough
16941735
case CONST:
1695-
const_status = Const::Yes;
1696-
break;
16971736
case ASYNC:
1698-
async_status = Async::Yes;
1699-
break;
17001737
case UNSAFE:
1701-
unsafe_status = Unsafety::Unsafe;
1738+
found_order.push_back (token_id);
1739+
lexer.skip_token ();
17021740
break;
17031741
case EXTERN_KW:
17041742
{
1705-
has_extern = true;
1706-
// detect optional abi name
1743+
found_order.push_back (token_id);
17071744
lexer.skip_token ();
1745+
1746+
// detect optional abi name
17081747
const_TokenPtr next_tok = lexer.peek_token ();
17091748
if (next_tok->get_id () == STRING_LITERAL)
17101749
{
17111750
abi = next_tok->get_str ();
1751+
lexer.skip_token ();
17121752
}
17131753
}
17141754
break;
17151755
default:
1756+
// non-qualifier keyword
17161757
goto done;
17171758
}
1718-
found_order.push_back (token_id);
1719-
lexer.skip_token ();
1759+
1760+
if (std::count (found_order.cbegin (), found_order.cend (), token_id) > 1)
1761+
{
1762+
// qualifiers mustn't appear twice
1763+
Error error (locus, "encountered duplicate function qualifier %qs",
1764+
token->get_token_description ());
1765+
add_error (std::move (error));
1766+
1767+
return tl::unexpected<Parse::Error::Node> (
1768+
Parse::Error::Node::MALFORMED);
1769+
}
17201770
}
17211771
done:
17221772

1723-
if (!ensure_function_qualifier_order (locus, std::move (found_order)))
1773+
if (!ensure_function_qualifier_order (locus, found_order))
17241774
return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
17251775

1726-
return std::unique_ptr<AST::FunctionQualifiers> (
1727-
new AST::FunctionQualifiers (locus, default_status, async_status,
1728-
const_status, unsafe_status, has_extern,
1729-
std::move (abi)));
1776+
return make_pair (found_order, abi);
17301777
}
17311778

1779+
// Validate the order of the list of function qualifiers; this assumes that
1780+
// ``found_order`` consists only of function qualifier tokens.
1781+
//
1782+
// If the order is illegal, the generated error message gives both the wrong
1783+
// order as found in the source and the correct order according to Rust syntax
1784+
// rules.
17321785
template <typename ManagedTokenSource>
17331786
bool
17341787
Parser<ManagedTokenSource>::ensure_function_qualifier_order (
1735-
location_t locus, std::vector<TokenId> found_order)
1788+
location_t locus, const std::vector<TokenId> &found_order)
17361789
{
17371790
// Check in order of default, const, async, unsafe, extern
17381791
auto token_priority = [] (const TokenId id) {
@@ -1759,62 +1812,65 @@ Parser<ManagedTokenSource>::ensure_function_qualifier_order (
17591812
const size_t priority = token_priority (token_id);
17601813
if (priority <= last_priority)
17611814
{
1762-
auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {
1763-
std::ostringstream ss;
1815+
emit_function_qualifier_order_error_msg (locus, found_order);
1816+
return false;
1817+
}
17641818

1765-
for (auto id : token_ids)
1766-
{
1767-
if (ss.tellp () != 0)
1768-
ss << ' ';
1819+
last_priority = priority;
1820+
}
17691821

1770-
if (id == IDENTIFIER)
1771-
ss << Values::WeakKeywords::DEFAULT;
1772-
else
1773-
ss << token_id_keyword_string (id);
1774-
}
1822+
return true;
1823+
}
17751824

1776-
return ss.str ();
1777-
};
1825+
template <typename ManagedTokenSource>
1826+
void
1827+
Parser<ManagedTokenSource>::emit_function_qualifier_order_error_msg (
1828+
location_t locus, const std::vector<TokenId> &found_order)
1829+
{
1830+
std::vector<TokenId> expected_order
1831+
= {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};
17781832

1779-
std::vector<TokenId> expected_order
1780-
= {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};
1833+
// we only keep the qualifiers actually used in the offending code
1834+
std::vector<TokenId>::iterator token_id = expected_order.begin ();
1835+
while (token_id != expected_order.end ())
1836+
{
1837+
if (std::find (found_order.cbegin (), found_order.cend (), *token_id)
1838+
== found_order.cend ())
1839+
{
1840+
token_id = expected_order.erase (token_id);
1841+
}
1842+
else
1843+
{
1844+
++token_id;
1845+
}
1846+
}
17811847

1782-
// we only keep the qualifiers actually used in the offending code
1783-
std::vector<TokenId>::const_iterator token_id
1784-
= expected_order.cbegin ();
1785-
while (token_id != expected_order.cend ())
1786-
{
1787-
if (std::find (found_order.cbegin (), found_order.cend (),
1788-
*token_id)
1789-
== found_order.cend ())
1790-
{
1791-
token_id = expected_order.erase (token_id);
1792-
}
1793-
else
1794-
{
1795-
++token_id;
1796-
}
1797-
}
1848+
auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {
1849+
std::ostringstream ss;
17981850

1799-
const std::string found_qualifiers = qualifiers_to_str (found_order);
1800-
const std::string expected_qualifiers
1801-
= qualifiers_to_str (expected_order);
1851+
for (auto id : token_ids)
1852+
{
1853+
if (ss.tellp () != 0)
1854+
ss << ' ';
18021855

1803-
location_t error_locus
1804-
= make_location (locus, locus, lexer.peek_token ()->get_locus ());
1805-
Error error (
1806-
error_locus,
1807-
"invalid order of function qualifiers; found %qs, expected %qs",
1808-
found_qualifiers.c_str (), expected_qualifiers.c_str ());
1809-
add_error (std::move (error));
1856+
if (id == IDENTIFIER)
1857+
ss << Values::WeakKeywords::DEFAULT;
1858+
else
1859+
ss << token_id_keyword_string (id);
1860+
}
18101861

1811-
return false;
1812-
}
1862+
return ss.str ();
1863+
};
18131864

1814-
last_priority = priority;
1815-
}
1865+
const std::string found_qualifiers = qualifiers_to_str (found_order);
1866+
const std::string expected_qualifiers = qualifiers_to_str (expected_order);
18161867

1817-
return true;
1868+
location_t error_locus
1869+
= make_location (locus, locus, lexer.peek_token ()->get_locus ());
1870+
Error error (error_locus,
1871+
"invalid order of function qualifiers; found %qs, expected %qs",
1872+
found_qualifiers.c_str (), expected_qualifiers.c_str ());
1873+
add_error (std::move (error));
18181874
}
18191875

18201876
// Parses generic (lifetime or type) params inside angle brackets (optional).
@@ -4479,7 +4535,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
44794535
}
44804536

44814537
return std::unique_ptr<AST::Function> (
4482-
new AST::Function (std::move (ident), std::move (*qualifiers.value ()),
4538+
new AST::Function (std::move (ident), std::move (qualifiers.value ()),
44834539
std::move (generic_params), std::move (function_params),
44844540
std::move (return_type), std::move (where_clause),
44854541
std::move (body), std::move (vis),
@@ -4709,7 +4765,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
47094765
}
47104766

47114767
return std::unique_ptr<AST::Function> (
4712-
new AST::Function (std::move (ident), std::move (*qualifiers.value ()),
4768+
new AST::Function (std::move (ident), std::move (qualifiers.value ()),
47134769
std::move (generic_params), std::move (function_params),
47144770
std::move (return_type), std::move (where_clause),
47154771
std::move (body), std::move (vis),
@@ -6407,7 +6463,7 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
64076463
}
64086464

64096465
return std::unique_ptr<AST::BareFunctionType> (new AST::BareFunctionType (
6410-
std::move (for_lifetimes), std::move (*qualifiers.value ()),
6466+
std::move (for_lifetimes), std::move (qualifiers.value ()),
64116467
std::move (params), is_variadic, std::move (variadic_attrs),
64126468
std::move (return_type), best_try_locus));
64136469
}

gcc/rust/parse/rust-parse.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,20 @@ template <typename ManagedTokenSource> class Parser
364364
std::unique_ptr<AST::Function> parse_function (AST::Visibility vis,
365365
AST::AttrVec outer_attrs,
366366
bool is_external = false);
367-
tl::expected<std::unique_ptr<AST::FunctionQualifiers>, Parse::Error::Node>
367+
tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
368368
parse_function_qualifiers ();
369-
bool ensure_function_qualifier_order (location_t locus,
370-
std::vector<TokenId> found_order);
369+
tl::expected<std::pair<std::vector<TokenId>, std::string>, Parse::Error::Node>
370+
parse_function_qualifiers_raw (location_t locus);
371+
bool
372+
ensure_function_qualifier_order (location_t locus,
373+
const std::vector<TokenId> &found_order);
374+
tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
375+
function_qualifiers_from_keywords (location_t locus,
376+
std::vector<TokenId> keywords,
377+
std::string abi);
378+
void emit_function_qualifier_order_error_msg (
379+
location_t locus, const std::vector<TokenId> &found_order);
380+
371381
std::vector<std::unique_ptr<AST::GenericParam>>
372382
parse_generic_params_in_angles ();
373383
template <typename EndTokenPred>

0 commit comments

Comments
 (0)