gccrs: Add Parser for Rust front-end pt.1

This is a Pratt-style parser for Rust that implements all of the AST. The
rust-parser-impl.h is the implementation of the parser as a template,
allowing it to be given ManagedTokenSource and avoid virtual calls. The
downside is it takes time to compile when used.

see: https://en.wikipedia.org/wiki/Operator-precedence_parser#Pratt_parsing

This patch contains the first half of the templated parser, so as to not
lose patches in the mailing list archives.

	gcc/rust/
	* parse/rust-cfg-parser.cc: New.
	* parse/rust-cfg-parser.h: New.
	* parse/rust-parse-impl.h: New.
	* parse/rust-parse.cc: New.
	* parse/rust-parse.h: New.

Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>

Signed-off-by: Joel Phillips <simplytheother@gmail.com>
This commit is contained in:
Joel Phillips 2022-10-21 13:39:04 +02:00 committed by Arthur Cohen
parent 18f6990f84
commit 35e4f3b4af
5 changed files with 8143 additions and 0 deletions

View file

@ -0,0 +1,127 @@
/* This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "rust-cfg-parser.h"
#include "rust-lex.h"
#include "rust-parse.h"
#include "rust-session-manager.h"
#include "selftest.h"
namespace Rust {
bool
parse_cfg_option (std::string &input, std::string &key, std::string &value)
{
key.clear ();
value.clear ();
auto lexer = Lexer (input);
auto parser = Parser<Lexer> (lexer);
auto token = parser.peek_current_token ();
if (token->get_id () != IDENTIFIER)
{
return false;
}
key = token->get_str ();
rust_assert (parser.skip_token (IDENTIFIER));
token = parser.peek_current_token ();
switch (token->get_id ())
{
case END_OF_FILE:
// we're done parsing, we had a valid key, return happily
return true;
case EQUAL:
// We have an equal sign: Skip the token and parse an identifier
{
rust_assert (parser.skip_token (EQUAL));
auto value_expr = parser.parse_literal_expr ();
// We had an equal sign but no value, error out
if (!value_expr)
return false;
if (value_expr->get_lit_type () != AST::Literal::LitType::STRING)
return false;
value = value_expr->get_literal ().as_string ();
return true;
}
default:
return false;
}
}
} // namespace Rust
#if CHECKING_P
namespace selftest {
void
rust_cfg_parser_test (void)
{
std::string key;
std::string value;
auto input = std::string ("key_no_value");
ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
ASSERT_EQ (key, "key_no_value");
ASSERT_TRUE (value.empty ());
input = std::string ("k=\"v\"");
ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
ASSERT_EQ (key, "k");
ASSERT_EQ (value, "v");
// values should be between double quotes
input = std::string ("k=v");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
// No value is an error if there is an equal sign
input = std::string ("k=");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
// No key is an error
input = std::string ("=");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
input = std::string ("=value");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
// values that are not string literals are an error
input = std::string ("key=b\"a\"");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
input = std::string ("key='v'");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
input = std::string ("key=155");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
input = std::string ("key=3.14");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
// kebab case is not valid for an identifier
input = std::string ("key-no-value");
ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
}
} // namespace selftest
#endif // CHECKING_P

View file

@ -0,0 +1,52 @@
/* This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef RUST_CFG_PARSER_H
#define RUST_CFG_PARSER_H
#include "rust-system.h"
namespace Rust {
/**
* Parse a `key` or `key="value"` pair given to the `-frust-cfg` compiler
* option.
*
* The format is as follows:
*
* -frust-cfg=<input>
*
* cfg_input: identifier | identifier '=' '"' identifier '"'
*
* @param input User input given to the -frust-cfg option
* @param key String in which to store the parsed `key`.
* @param value String in which to store the parsed `value` if it exists
*
* @return false if the given input was invalid, true otherwise
*/
bool
parse_cfg_option (std::string &input, std::string &key, std::string &value);
} // namespace Rust
#if CHECKING_P
namespace selftest {
extern void
rust_cfg_parser_test (void);
} // namespace selftest
#endif // CHECKING_P
#endif // RUST_CFG_PARSER_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,328 @@
/* This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "rust-parse.h"
#include "rust-linemap.h"
#include "rust-diagnostics.h"
namespace Rust {
std::string
extract_module_path (const AST::AttrVec &inner_attrs,
const AST::AttrVec &outer_attrs, const std::string &name)
{
AST::Attribute path_attr = AST::Attribute::create_empty ();
for (const auto &attr : inner_attrs)
{
if (attr.get_path ().as_string () == "path")
{
path_attr = attr;
break;
}
}
// Here, we found a path attribute, but it has no associated string. This is
// invalid
if (!path_attr.is_empty () && !path_attr.has_attr_input ())
{
rust_error_at (
path_attr.get_locus (),
// Split the format string so that -Wformat-diag does not complain...
"path attributes must contain a filename: '%s'", "#![path = \"file\"]");
return name;
}
for (const auto &attr : outer_attrs)
{
if (attr.get_path ().as_string () == "path")
{
path_attr = attr;
break;
}
}
// We didn't find a path attribute. This is not an error, there simply isn't
// one present
if (path_attr.is_empty ())
return name;
// Here, we found a path attribute, but it has no associated string. This is
// invalid
if (!path_attr.has_attr_input ())
{
rust_error_at (
path_attr.get_locus (),
// Split the format string so that -Wformat-diag does not complain...
"path attributes must contain a filename: '%s'", "#[path = \"file\"]");
return name;
}
auto path_value = path_attr.get_attr_input ().as_string ();
// At this point, the 'path' is of the following format: '= "<file.rs>"'
// We need to remove the equal sign and only keep the actual filename.
// In order to do this, we can simply go through the string until we find
// a character that is not an equal sign or whitespace
auto filename_begin = path_value.find_first_not_of ("=\t ");
auto path = path_value.substr (filename_begin);
// On windows, the path might mix '/' and '\' separators. Replace the
// UNIX-like separators by MSDOS separators to make sure the path will resolve
// properly.
//
// Source: rustc compiler
// (https://github.com/rust-lang/rust/blob/9863bf51a52b8e61bcad312f81b5193d53099f9f/compiler/rustc_expand/src/module.rs#L174)
#if defined(HAVE_DOS_BASED_FILE_SYSTEM)
path.replace ('/', '\\');
#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
return path;
}
template <typename T>
static bool
contains (std::vector<T> &vec, T elm)
{
return std::find (vec.begin (), vec.end (), elm) != vec.end ();
}
/**
* Avoid UB by calling .front() and .back() on empty containers...
*/
template <typename T>
static const T *
get_back_ptr (const std::vector<std::unique_ptr<T>> &values)
{
if (values.empty ())
return nullptr;
return values.back ().get ();
}
template <typename T>
static const T *
get_front_ptr (const std::vector<std::unique_ptr<T>> &values)
{
if (values.empty ())
return nullptr;
return values.front ().get ();
}
static bool
peculiar_fragment_match_compatible_fragment (
const AST::MacroFragSpec &last_spec, const AST::MacroFragSpec &spec,
Location match_locus)
{
static std::unordered_map<AST::MacroFragSpec::Kind,
std::vector<AST::MacroFragSpec::Kind>>
fragment_follow_set
= {{AST::MacroFragSpec::PATH, {AST::MacroFragSpec::BLOCK}},
{AST::MacroFragSpec::TY, {AST::MacroFragSpec::BLOCK}},
{AST::MacroFragSpec::VIS,
{AST::MacroFragSpec::IDENT, AST::MacroFragSpec::TY,
AST::MacroFragSpec::PATH}}};
auto is_valid
= contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ());
if (!is_valid)
rust_error_at (
match_locus,
"fragment specifier %<%s%> is not allowed after %<%s%> fragments",
spec.as_string ().c_str (), last_spec.as_string ().c_str ());
return is_valid;
}
static bool
peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
const AST::MacroMatch &match)
{
static std::unordered_map<AST::MacroFragSpec::Kind, std::vector<TokenId>>
follow_set
= {{AST::MacroFragSpec::EXPR, {MATCH_ARROW, COMMA, SEMICOLON}},
{AST::MacroFragSpec::STMT, {MATCH_ARROW, COMMA, SEMICOLON}},
{AST::MacroFragSpec::PAT, {MATCH_ARROW, COMMA, EQUAL, PIPE, IF, IN}},
{AST::MacroFragSpec::PATH,
{MATCH_ARROW, COMMA, EQUAL, PIPE, SEMICOLON, COLON, RIGHT_ANGLE,
RIGHT_SHIFT, LEFT_SQUARE, LEFT_CURLY, AS, WHERE}},
{AST::MacroFragSpec::TY,
{MATCH_ARROW, COMMA, EQUAL, PIPE, SEMICOLON, COLON, RIGHT_ANGLE,
RIGHT_SHIFT, LEFT_SQUARE, LEFT_CURLY, AS, WHERE}},
{AST::MacroFragSpec::VIS,
{
COMMA,
IDENTIFIER /* FIXME: Other than `priv` */,
LEFT_PAREN,
LEFT_SQUARE,
EXCLAM,
ASTERISK,
AMP,
LOGICAL_AND,
QUESTION_MARK,
LIFETIME,
LEFT_ANGLE,
LEFT_SHIFT,
SUPER,
SELF,
SELF_ALIAS,
EXTERN_TOK,
CRATE,
UNDERSCORE,
FOR,
IMPL,
FN_TOK,
UNSAFE,
TYPEOF,
DYN
// FIXME: Add Non kw identifiers
// FIXME: Add $crate as valid
}}};
Location error_locus = match.get_match_locus ();
std::string kind_str = "fragment";
auto &allowed_toks = follow_set[last_match.get_frag_spec ().get_kind ()];
// There are two behaviors to handle here: If the follow-up match is a token,
// we want to check if it is allowed.
// If it is a fragment, repetition or matcher then we know that it will be
// an error.
// For repetitions and matchers we want to extract a proper location to report
// the error.
switch (match.get_macro_match_type ())
{
case AST::MacroMatch::Tok: {
auto tok = static_cast<const AST::Token *> (&match);
if (contains (allowed_toks, tok->get_id ()))
return true;
kind_str = "token `"
+ std::string (get_token_description (tok->get_id ())) + "`";
error_locus = tok->get_match_locus ();
break;
}
break;
case AST::MacroMatch::Repetition: {
auto repetition
= static_cast<const AST::MacroMatchRepetition *> (&match);
auto &matches = repetition->get_matches ();
auto first_frag = get_front_ptr (matches);
if (first_frag)
return peculiar_fragment_match_compatible (last_match, *first_frag);
break;
}
case AST::MacroMatch::Matcher: {
auto matcher = static_cast<const AST::MacroMatcher *> (&match);
auto first_token = matcher->get_delim_type ();
TokenId delim_id;
switch (first_token)
{
case AST::PARENS:
delim_id = LEFT_PAREN;
break;
case AST::SQUARE:
delim_id = LEFT_SQUARE;
break;
case AST::CURLY:
delim_id = LEFT_CURLY;
break;
default:
gcc_unreachable ();
break;
}
if (contains (allowed_toks, delim_id))
return true;
kind_str = "token `" + std::string (get_token_description (delim_id))
+ "` at start of matcher";
error_locus = matcher->get_match_locus ();
break;
}
case AST::MacroMatch::Fragment: {
auto last_spec = last_match.get_frag_spec ();
auto fragment = static_cast<const AST::MacroMatchFragment *> (&match);
if (last_spec.has_follow_set_fragment_restrictions ())
return peculiar_fragment_match_compatible_fragment (
last_spec, fragment->get_frag_spec (), match.get_match_locus ());
}
break;
}
rust_error_at (error_locus, "%s is not allowed after %<%s%> fragment",
kind_str.c_str (),
last_match.get_frag_spec ().as_string ().c_str ());
auto allowed_toks_str
= "`" + std::string (get_token_description (allowed_toks[0])) + "`";
for (size_t i = 1; i < allowed_toks.size (); i++)
allowed_toks_str
+= ", `" + std::string (get_token_description (allowed_toks[i])) + "`";
rust_inform (error_locus, "allowed tokens are %s", allowed_toks_str.c_str ());
return false;
}
bool
is_match_compatible (const AST::MacroMatch &last_match,
const AST::MacroMatch &match)
{
const AST::MacroMatch *new_last = nullptr;
// We want to "extract" the concerning matches. In cases such as matchers and
// repetitions, we actually store multiple matchers, but are only concerned
// about the follow-set ambiguities of certain elements.
// There are some cases where we can short-circuit the algorithm: There will
// never be restrictions on token literals, or on certain fragments which do
// not have a set of follow-restrictions.
switch (last_match.get_macro_match_type ())
{
// This is our main stop condition: When we are finally looking at the
// last match (or its actual last component), and it is a fragment, it
// may contain some follow up restrictions.
case AST::MacroMatch::Fragment: {
auto fragment
= static_cast<const AST::MacroMatchFragment *> (&last_match);
if (fragment->get_frag_spec ().has_follow_set_restrictions ())
return peculiar_fragment_match_compatible (*fragment, match);
else
return true;
}
case AST::MacroMatch::Repetition: {
// A repetition on the left hand side means we want to make sure the
// last match of the repetition is compatible with the new match
auto repetition
= static_cast<const AST::MacroMatchRepetition *> (&last_match);
new_last = get_back_ptr (repetition->get_matches ());
// If there are no matches in the matcher, then it can be followed by
// anything
if (!new_last)
return true;
break;
}
case AST::MacroMatch::Matcher:
case AST::MacroMatch::Tok:
return true;
}
rust_assert (new_last);
// We check recursively until we find a terminating condition
// FIXME: Does expansion depth/limit matter here?
return is_match_compatible (*new_last, match);
}
} // namespace Rust

732
gcc/rust/parse/rust-parse.h Normal file
View file

@ -0,0 +1,732 @@
/* This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef RUST_PARSE_H
#define RUST_PARSE_H
#include "rust-lex.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
namespace Rust {
/* HACK: used to resolve the expression-or-statement problem at the end of a
* block by allowing either to be returned (technically). Tagged union would
* probably take up the same amount of space. */
struct ExprOrStmt
{
std::unique_ptr<AST::Expr> expr;
std::unique_ptr<AST::Stmt> stmt;
/* I was going to resist the urge to make this a real class and make it POD,
* but construction in steps is too difficult. So it'll just also have a
* constructor. */
// expression constructor
ExprOrStmt (std::unique_ptr<AST::Expr> expr) : expr (std::move (expr)) {}
// statement constructor
ExprOrStmt (std::unique_ptr<AST::Stmt> stmt) : stmt (std::move (stmt)) {}
// macro constructor
ExprOrStmt (std::unique_ptr<AST::MacroInvocation> macro)
: expr (std::move (macro))
{}
// Returns whether this object is in an error state.
bool is_error () const
{
return (expr == nullptr && stmt == nullptr)
|| (expr != nullptr && stmt != nullptr);
}
// Returns an error state object.
static ExprOrStmt create_error () { return ExprOrStmt (nullptr, nullptr); }
~ExprOrStmt () = default;
/* no copy constructors/assignment as simple object like this shouldn't
* require it */
// move constructors
ExprOrStmt (ExprOrStmt &&other) = default;
ExprOrStmt &operator= (ExprOrStmt &&other) = default;
private:
// private constructor only used for creating error state expr or stmt objects
ExprOrStmt (AST::Expr *expr, AST::Stmt *stmt) : expr (expr), stmt (stmt) {}
// make this work: have a disambiguation specifically for known statements
// (i.e. ';' and 'let'). then, have a special "parse expr or stmt" function
// that returns this type. inside it, it parses an expression, and then
// determines whether to return expr or stmt via whether the next token is a
// semicolon. should be able to disambiguate inside that function between
// stmts with blocks and without blocks.
};
/* Restrictions on parsing used to signal that certain ambiguous grammar
* features should be parsed in a certain way. */
struct ParseRestrictions
{
bool can_be_struct_expr = true;
/* Whether the expression was entered from a unary expression - prevents stuff
* like struct exprs being parsed from a dereference. */
bool entered_from_unary = false;
bool expr_can_be_null = false;
bool expr_can_be_stmt = false;
bool consume_semi = true;
};
// Parser implementation for gccrs.
// TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
template <typename ManagedTokenSource> class Parser
{
public:
/**
* Consume a token, reporting an error if it isn't the next token
*
* @param t ID of the token to consume
*
* @return true if the token was next, false if it wasn't found
*/
bool skip_token (TokenId t);
/**
* Same as `skip_token` but allows for failure without necessarily reporting
* an error
*
* @param t ID of the token to consume
*
* @return true if the token was next, false if it wasn't found
*/
bool maybe_skip_token (TokenId t);
std::unique_ptr<AST::Expr>
parse_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::LiteralExpr> parse_literal_expr (AST::AttrVec outer_attrs
= AST::AttrVec ());
std::unique_ptr<AST::BlockExpr>
parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::Item> parse_item (bool called_from_statement);
std::unique_ptr<AST::Pattern> parse_pattern ();
/**
* Parse a statement
*
* Statement : ';'
* | Item
* | LetStatement
* | ExpressionStatement
* | MacroInvocationSemi
*/
std::unique_ptr<AST::Stmt> parse_stmt (ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::Type> parse_type (bool save_errors = true);
std::unique_ptr<AST::ExternalItem> parse_external_item ();
std::unique_ptr<AST::TraitItem> parse_trait_item ();
std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
AST::PathInExpression parse_path_in_expression ();
std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params ();
AST::Visibility parse_visibility ();
std::unique_ptr<AST::IdentifierPattern> parse_identifier_pattern ();
std::unique_ptr<AST::TokenTree> parse_token_tree ();
AST::Attribute parse_attribute_body ();
AST::AttrVec parse_inner_attributes ();
private:
void skip_after_semicolon ();
void skip_after_end ();
void skip_after_end_block ();
void skip_after_next_block ();
void skip_after_end_attribute ();
const_TokenPtr expect_token (TokenId t);
void unexpected_token (const_TokenPtr t);
bool skip_generics_right_angle ();
void parse_statement_seq (bool (Parser::*done) ());
// AST-related stuff - maybe move or something?
AST::Attribute parse_inner_attribute ();
AST::AttrVec parse_outer_attributes ();
AST::Attribute parse_outer_attribute ();
std::unique_ptr<AST::AttrInput> parse_attr_input ();
AST::Attribute parse_doc_comment ();
// Path-related
AST::SimplePath parse_simple_path ();
AST::SimplePathSegment parse_simple_path_segment ();
AST::TypePath parse_type_path ();
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
AST::PathIdentSegment parse_path_ident_segment ();
AST::GenericArg parse_generic_arg ();
AST::GenericArgs parse_path_generic_args ();
AST::GenericArgsBinding parse_generic_args_binding ();
AST::TypePathFunction parse_type_path_function (Location locus);
AST::PathExprSegment parse_path_expr_segment ();
AST::QualifiedPathInExpression
// When given a pratt_parsed_loc, use it as the location of the
// first token parsed in the expression (the parsing of that first
// token should be skipped).
parse_qualified_path_in_expression (Location pratt_parsed_loc
= Linemap::unknown_location ());
AST::QualifiedPathType
parse_qualified_path_type (Location pratt_parsed_loc
= Linemap::unknown_location ());
AST::QualifiedPathInType parse_qualified_path_in_type ();
// Token tree or macro related
AST::DelimTokenTree parse_delim_token_tree ();
std::unique_ptr<AST::MacroRulesDefinition>
parse_macro_rules_def (AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroInvocation>
parse_macro_invocation_semi (AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroInvocation>
parse_macro_invocation (AST::AttrVec outer_attrs);
AST::MacroRule parse_macro_rule ();
AST::MacroMatcher parse_macro_matcher ();
std::unique_ptr<AST::MacroMatch> parse_macro_match ();
std::unique_ptr<AST::MacroMatchFragment> parse_macro_match_fragment ();
std::unique_ptr<AST::MacroMatchRepetition> parse_macro_match_repetition ();
// Top-level item-related
std::unique_ptr<AST::VisItem> parse_vis_item (AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroItem> parse_macro_item (AST::AttrVec outer_attrs);
// VisItem subclass-related
std::unique_ptr<AST::Module> parse_module (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExternCrate>
parse_extern_crate (AST::Visibility vis, AST::AttrVec outer_attrs);
std::unique_ptr<AST::UseDeclaration>
parse_use_decl (AST::Visibility vis, AST::AttrVec outer_attrs);
std::unique_ptr<AST::UseTree> parse_use_tree ();
std::unique_ptr<AST::Function> parse_function (AST::Visibility vis,
AST::AttrVec outer_attrs);
AST::FunctionQualifiers parse_function_qualifiers ();
std::vector<std::unique_ptr<AST::GenericParam> >
parse_generic_params_in_angles ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::GenericParam> >
parse_generic_params (EndTokenPred is_end_token);
template <typename EndTokenPred>
std::unique_ptr<AST::GenericParam>
parse_generic_param (EndTokenPred is_end_token);
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::LifetimeParam> >
parse_lifetime_params (EndTokenPred is_end_token);
std::vector<AST::LifetimeParam> parse_lifetime_params_objs ();
template <typename EndTokenPred>
std::vector<AST::LifetimeParam>
parse_lifetime_params_objs (EndTokenPred is_end_token);
template <typename ParseFunction, typename EndTokenPred>
auto parse_non_ptr_sequence (
ParseFunction parsing_function, EndTokenPred is_end_token,
std::string error_msg = "failed to parse generic param in generic params")
-> std::vector<decltype (parsing_function ())>;
AST::LifetimeParam parse_lifetime_param ();
std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParam> >
parse_type_params (EndTokenPred is_end_token);
std::unique_ptr<AST::TypeParam> parse_type_param ();
template <typename EndTokenPred>
std::vector<AST::FunctionParam>
parse_function_params (EndTokenPred is_end_token);
AST::FunctionParam parse_function_param ();
std::unique_ptr<AST::Type> parse_function_return_type ();
AST::WhereClause parse_where_clause ();
std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item ();
std::unique_ptr<AST::LifetimeWhereClauseItem>
parse_lifetime_where_clause_item ();
std::unique_ptr<AST::TypeBoundWhereClauseItem>
parse_type_bound_where_clause_item ();
std::vector<AST::LifetimeParam> parse_for_lifetimes ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParamBound> >
parse_type_param_bounds (EndTokenPred is_end_token);
std::vector<std::unique_ptr<AST::TypeParamBound> > parse_type_param_bounds ();
std::unique_ptr<AST::TypeParamBound> parse_type_param_bound ();
std::unique_ptr<AST::TraitBound> parse_trait_bound ();
std::vector<AST::Lifetime> parse_lifetime_bounds ();
template <typename EndTokenPred>
std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token);
AST::Lifetime parse_lifetime ();
std::unique_ptr<AST::TypeAlias> parse_type_alias (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::Struct> parse_struct (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::vector<AST::StructField> parse_struct_fields ();
template <typename EndTokenPred>
std::vector<AST::StructField> parse_struct_fields (EndTokenPred is_end_token);
AST::StructField parse_struct_field ();
std::vector<AST::TupleField> parse_tuple_fields ();
AST::TupleField parse_tuple_field ();
std::unique_ptr<AST::Enum> parse_enum (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::vector<std::unique_ptr<AST::EnumItem> > parse_enum_items ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::EnumItem> >
parse_enum_items (EndTokenPred is_end_token);
std::unique_ptr<AST::EnumItem> parse_enum_item ();
std::unique_ptr<AST::Union> parse_union (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::ConstantItem>
parse_const_item (AST::Visibility vis, AST::AttrVec outer_attrs);
std::unique_ptr<AST::StaticItem> parse_static_item (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::Trait> parse_trait (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitItemType>
parse_trait_type (AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitItemConst>
parse_trait_const (AST::AttrVec outer_attrs);
AST::SelfParam parse_self_param ();
std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::InherentImplItem>
parse_inherent_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitImplItem>
parse_trait_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExternBlock>
parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
AST::NamedFunctionParam parse_named_function_param (AST::AttrVec outer_attrs
= AST::AttrVec ());
AST::Method parse_method ();
// Expression-related (Pratt parsed)
std::unique_ptr<AST::Expr>
parse_expr (int right_binding_power,
AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
left_denotation (const_TokenPtr t, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_arithmetic_or_logical_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs, AST::ArithmeticOrLogicalExpr::ExprType expr_type,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_binary_plus_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_binary_minus_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_binary_mult_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_binary_div_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_binary_mod_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_bitwise_and_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_bitwise_or_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_bitwise_xor_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_left_shift_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArithmeticOrLogicalExpr>
parse_right_shift_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr>
parse_comparison_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
AST::ComparisonExpr::ExprType expr_type,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr>
parse_binary_equal_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr> parse_binary_not_equal_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_than_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr> parse_binary_less_than_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_equal_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ComparisonExpr> parse_binary_less_equal_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::LazyBooleanExpr>
parse_lazy_or_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::LazyBooleanExpr>
parse_lazy_and_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::TypeCastExpr>
parse_type_cast_expr (const_TokenPtr tok,
std::unique_ptr<AST::Expr> expr_to_cast,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::AssignmentExpr>
parse_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr> parse_compound_assignment_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs, AST::CompoundAssignmentExpr::ExprType expr_type,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_plus_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_minus_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_mult_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_div_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_mod_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_and_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_or_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr>
parse_xor_assig_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr> parse_left_shift_assig_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CompoundAssignmentExpr> parse_right_shift_assig_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::AwaitExpr>
parse_await_expr (const_TokenPtr tok,
std::unique_ptr<AST::Expr> expr_to_await,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::MethodCallExpr> parse_method_call_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> receiver_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::CallExpr> parse_function_call_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> function_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::RangeExpr> parse_led_range_exclusive_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::RangeExpr>
parse_nud_range_exclusive_expr (const_TokenPtr tok, AST::AttrVec outer_attrs);
std::unique_ptr<AST::RangeFromToInclExpr> parse_range_inclusive_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> left,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::RangeToInclExpr>
parse_range_to_inclusive_expr (const_TokenPtr tok, AST::AttrVec outer_attrs);
std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> tuple_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::FieldAccessExpr> parse_field_access_expr (
const_TokenPtr tok, std::unique_ptr<AST::Expr> struct_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::ArrayIndexExpr>
parse_index_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> array_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::MacroInvocation> parse_macro_invocation_partial (
AST::PathInExpression path, AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::StructExprStruct>
parse_struct_expr_struct_partial (AST::PathInExpression path,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::CallExpr>
parse_struct_expr_tuple_partial (AST::PathInExpression path,
AST::AttrVec outer_attrs);
AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok);
std::unique_ptr<AST::ClosureExpr>
parse_closure_expr_pratt (const_TokenPtr tok,
AST::AttrVec outer_attrs = AST::AttrVec ());
std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr_float (
const_TokenPtr tok, std::unique_ptr<AST::Expr> tuple_expr,
AST::AttrVec outer_attrs,
ParseRestrictions restrictions = ParseRestrictions ());
// Expression-related (non-Pratt parsed)
std::unique_ptr<AST::ExprWithBlock>
parse_expr_with_block (AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExprWithoutBlock>
parse_expr_without_block (AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions
= ParseRestrictions ());
// When given a pratt_parsed_loc, use it as the location of the
// first token parsed in the expression (the parsing of that first
// token should be skipped).
std::unique_ptr<AST::IfExpr>
parse_if_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::IfLetExpr>
parse_if_let_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::LoopExpr>
parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
AST::LoopLabel label = AST::LoopLabel::error (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::WhileLoopExpr>
parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
AST::LoopLabel label = AST::LoopLabel::error (),
Location pratt_parsed_loc
= Linemap::unknown_location ());
std::unique_ptr<AST::WhileLetLoopExpr>
parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
AST::LoopLabel label = AST::LoopLabel::error ());
std::unique_ptr<AST::ForLoopExpr>
parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
AST::LoopLabel label = AST::LoopLabel::error ());
std::unique_ptr<AST::MatchExpr>
parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
AST::MatchArm parse_match_arm ();
std::vector<std::unique_ptr<AST::Pattern> >
parse_match_arm_patterns (TokenId end_token_id);
std::unique_ptr<AST::BaseLoopExpr>
parse_labelled_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
AST::LoopLabel parse_loop_label ();
std::unique_ptr<AST::AsyncBlockExpr>
parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs
= AST::AttrVec ());
std::unique_ptr<AST::ClosureExpr> parse_closure_expr (AST::AttrVec outer_attrs
= AST::AttrVec ());
AST::ClosureParam parse_closure_param ();
// When given a pratt_parsed_loc, use it as the location of the
// first token parsed in the expression (the parsing of that first
// token should be skipped).
std::unique_ptr<AST::ReturnExpr>
parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::BreakExpr>
parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::ContinueExpr>
parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc
= Linemap::unknown_location ());
std::unique_ptr<AST::UnsafeBlockExpr>
parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc
= Linemap::unknown_location ());
std::unique_ptr<AST::ArrayExpr>
parse_array_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc = Linemap::unknown_location ());
std::unique_ptr<AST::ExprWithoutBlock>
parse_grouped_or_tuple_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
Location pratt_parsed_loc
= Linemap::unknown_location ());
std::unique_ptr<AST::StructExprField> parse_struct_expr_field ();
bool will_be_expr_with_block ();
// Type-related
std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds ();
std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type ();
std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type ();
std::unique_ptr<AST::ReferenceType> parse_reference_type ();
std::unique_ptr<AST::BareFunctionType>
parse_bare_function_type (std::vector<AST::LifetimeParam> for_lifetimes);
std::unique_ptr<AST::Type> parse_paren_prefixed_type ();
std::unique_ptr<AST::TypeNoBounds> parse_paren_prefixed_type_no_bounds ();
std::unique_ptr<AST::Type> parse_for_prefixed_type ();
AST::MaybeNamedParam parse_maybe_named_param (AST::AttrVec outer_attrs);
// Statement-related
/**
*Parse a let-statement
* LetStatement :
* OuterAttribute*
* 'let' PatternNoTopAlt ( ':' Type )? ('=' Expression )? ';'
*
* @param allow_no_semi Allow parsing a let-statement without expecting a
* semicolon to follow it
*/
std::unique_ptr<AST::LetStmt> parse_let_stmt (AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ExprStmt> parse_expr_stmt (AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
std::unique_ptr<AST::ExprStmtWithBlock>
parse_expr_stmt_with_block (AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExprStmtWithoutBlock>
parse_expr_stmt_without_block (AST::AttrVec outer_attrs,
ParseRestrictions restrictions
= ParseRestrictions ());
ExprOrStmt parse_stmt_or_expr_without_block ();
ExprOrStmt parse_stmt_or_expr_with_block (AST::AttrVec outer_attrs);
ExprOrStmt parse_macro_invocation_maybe_semi (AST::AttrVec outer_attrs);
ExprOrStmt parse_path_based_stmt_or_expr (AST::AttrVec outer_attrs);
// Pattern-related
std::unique_ptr<AST::Pattern> parse_literal_or_range_pattern ();
std::unique_ptr<AST::RangePatternBound> parse_range_pattern_bound ();
std::unique_ptr<AST::ReferencePattern> parse_reference_pattern ();
std::unique_ptr<AST::Pattern> parse_grouped_or_tuple_pattern ();
std::unique_ptr<AST::SlicePattern> parse_slice_pattern ();
std::unique_ptr<AST::Pattern> parse_ident_leading_pattern ();
std::unique_ptr<AST::TupleStructItems> parse_tuple_struct_items ();
AST::StructPatternElements parse_struct_pattern_elems ();
std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field ();
std::unique_ptr<AST::StructPatternField>
parse_struct_pattern_field_partial (AST::AttrVec outer_attrs);
int left_binding_power (const_TokenPtr token);
bool done_end ();
bool done_end_or_else ();
bool done_end_of_file ();
void add_error (Error error) { error_table.push_back (std::move (error)); }
public:
// Construct parser with specified "managed" token source.
Parser (ManagedTokenSource &tokenSource) : lexer (tokenSource) {}
// Parse items without parsing an entire crate. This function is the main
// parsing loop of AST::Crate::parse_crate().
std::vector<std::unique_ptr<AST::Item> > parse_items ();
// Main entry point for parser.
std::unique_ptr<AST::Crate> parse_crate ();
// Dumps all lexer output.
void debug_dump_lex_output (std::ostream &out);
void debug_dump_ast_output (AST::Crate &crate, std::ostream &out);
// Returns whether any parsing errors have occurred.
bool has_errors () const { return !error_table.empty (); }
// Remove all parsing errors from the table
void clear_errors () { error_table.clear (); }
// Get a reference to the list of errors encountered
std::vector<Error> &get_errors () { return error_table; }
const ManagedTokenSource &get_token_source () const { return lexer; }
const_TokenPtr peek_current_token () { return lexer.peek_token (0); }
private:
// The token source (usually lexer) associated with the parser.
ManagedTokenSource &lexer;
// The error list.
std::vector<Error> error_table;
// The names of inline modules while parsing.
std::vector<std::string> inline_module_stack;
class InlineModuleStackScope
{
private:
Parser &parser;
public:
InlineModuleStackScope (Parser &parser, std::string name) : parser (parser)
{
parser.inline_module_stack.emplace_back (std::move (name));
}
~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); }
};
};
std::string
extract_module_path (const AST::AttrVec &inner_attrs,
const AST::AttrVec &outer_attrs, const std::string &name);
/**
* Check if a MacroMatch is allowed to follow the last parsed MacroMatch.
*
* @param last_match Last matcher parsed before the current match
* @param match Current matcher to check
*
* @return true if the follow-up is valid, false otherwise
*/
bool
is_match_compatible (const AST::MacroMatch &last_match,
const AST::MacroMatch &current_match);
} // namespace Rust
// as now template, include implementations of all methods
#include "rust-parse-impl.h"
#endif // RUST_PARSE_H