mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
gccrs: Implement declarative macro 2.0 parser
gcc/rust/ChangeLog: * ast/rust-ast-full-decls.h (class MacroItem): Remove forward declaration. * ast/rust-ast-full-test.cc (MacroRulesDefinition): Rework MacroRulesDefinition class * ast/rust-ast.h (class MacroItem): Remove abstract class. * ast/rust-item.h (class MacroItem): Remove forward declaration. * ast/rust-macro.h (class MacroItem): Likewise. (class MacroRulesDefinition): Add MacroKind enum. (class MacroInvocation): Fix inheritance. * lex/rust-token.h: Token "macro" is now used. * parse/rust-parse-impl.h (Parser::parse_item): Add handling for MACRO. (Parser::parse_vis_item): Call into parse_decl_macro_def. (Parser::parse_macro_item): Delete function. (Parser::parse_macro_rules_def): Return MBE macros only. (Parser::parse_decl_macro_def): New function. (Parser::parse_stmt): Handle MACRO token. (Parser::parse_stmt_or_expr_without_block): Call into parse_macro_rules_def. * parse/rust-parse.h: Declare new function. gcc/testsuite/ChangeLog: * rust/compile/decl_macro1.rs: New test. * rust/compile/decl_macro2.rs: New test. * rust/compile/decl_macro3.rs: New test. * rust/compile/decl_macro4.rs: New test. * rust/compile/decl_macro5.rs: New test. * rust/compile/decl_macro6.rs: New test. * rust/compile/decl_macro7.rs: New test. * rust/execute/torture/decl_macro1.rs: New test. * rust/execute/torture/decl_macro2.rs: New test. * rust/execute/torture/decl_macro3.rs: New test. * rust/execute/torture/decl_macro4.rs: New test. Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
This commit is contained in:
committed by
Arthur Cohen
parent
ef792b9658
commit
e1394230b3
@@ -51,7 +51,6 @@ class Lifetime;
|
||||
class GenericParam;
|
||||
class LifetimeParam;
|
||||
class ConstGenericParam;
|
||||
class MacroItem;
|
||||
class TraitItem;
|
||||
class InherentImplItem;
|
||||
class TraitImplItem;
|
||||
|
||||
@@ -1284,6 +1284,7 @@ MacroRulesDefinition::as_string () const
|
||||
// get outer attrs
|
||||
str += append_attributes (outer_attrs, OUTER);
|
||||
|
||||
// TODO: deal with macro_2_0
|
||||
str += "macro_rules!";
|
||||
|
||||
str += rule_name;
|
||||
|
||||
@@ -1350,11 +1350,6 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
// A macro item AST node - abstract base class
|
||||
class MacroItem : public Item
|
||||
{
|
||||
};
|
||||
|
||||
// Item used in trait declarations - abstract base class
|
||||
class TraitItem
|
||||
{
|
||||
|
||||
@@ -4391,8 +4391,6 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
// Replaced with forward decls - defined in "rust-macro.h"
|
||||
class MacroItem;
|
||||
class MacroRulesDefinition;
|
||||
} // namespace AST
|
||||
} // namespace Rust
|
||||
|
||||
@@ -23,13 +23,11 @@
|
||||
#include "rust-ast.h"
|
||||
#include "rust-ast-fragment.h"
|
||||
#include "rust-location.h"
|
||||
#include "rust-item.h"
|
||||
#include "rust-make-unique.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace AST {
|
||||
|
||||
// Decls as definitions moved to rust-ast.h
|
||||
class MacroItem;
|
||||
|
||||
class MacroFragSpec
|
||||
{
|
||||
public:
|
||||
@@ -446,8 +444,18 @@ public:
|
||||
};
|
||||
|
||||
// A macro rules definition item AST node
|
||||
class MacroRulesDefinition : public MacroItem
|
||||
class MacroRulesDefinition : public VisItem
|
||||
{
|
||||
public:
|
||||
enum MacroKind
|
||||
{
|
||||
// Macro by Example (legacy macro rules)
|
||||
MBE,
|
||||
// Declarative macros 2.0
|
||||
DeclMacro,
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<Attribute> outer_attrs;
|
||||
Identifier rule_name;
|
||||
// MacroRulesDef rules_def;
|
||||
@@ -460,6 +468,7 @@ class MacroRulesDefinition : public MacroItem
|
||||
std::function<Fragment (Location, MacroInvocData &)> associated_transcriber;
|
||||
// Since we can't compare std::functions, we need to use an extra boolean
|
||||
bool is_builtin_rule;
|
||||
MacroKind kind;
|
||||
|
||||
/**
|
||||
* Default function to use as an associated transcriber. This function should
|
||||
@@ -479,27 +488,51 @@ class MacroRulesDefinition : public MacroItem
|
||||
* I am not aware of the implications of this decision. The rustc spec does
|
||||
* mention that using the same parser for macro definitions and invocations
|
||||
* is "extremely self-referential and non-intuitive". */
|
||||
|
||||
public:
|
||||
std::string as_string () const override;
|
||||
|
||||
MacroRulesDefinition (Identifier rule_name, DelimType delim_type,
|
||||
std::vector<MacroRule> rules,
|
||||
std::vector<Attribute> outer_attrs, Location locus)
|
||||
: outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
|
||||
std::vector<Attribute> outer_attrs, Location locus,
|
||||
MacroKind kind, Visibility vis)
|
||||
: VisItem (std::move (vis), outer_attrs),
|
||||
outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
|
||||
delim_type (delim_type), rules (std::move (rules)), locus (locus),
|
||||
associated_transcriber (dummy_builtin), is_builtin_rule (false)
|
||||
associated_transcriber (dummy_builtin), is_builtin_rule (false),
|
||||
kind (kind)
|
||||
{}
|
||||
|
||||
MacroRulesDefinition (
|
||||
Identifier builtin_name, DelimType delim_type,
|
||||
std::function<Fragment (Location, MacroInvocData &)> associated_transcriber)
|
||||
: outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
|
||||
std::function<Fragment (Location, MacroInvocData &)> associated_transcriber,
|
||||
MacroKind kind, Visibility vis)
|
||||
: VisItem (std::move (vis), std::vector<Attribute> ()),
|
||||
outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
|
||||
delim_type (delim_type), rules (std::vector<MacroRule> ()),
|
||||
locus (Location ()), associated_transcriber (associated_transcriber),
|
||||
is_builtin_rule (true)
|
||||
is_builtin_rule (true), kind (kind)
|
||||
{}
|
||||
|
||||
public:
|
||||
std::string as_string () const override;
|
||||
|
||||
static std::unique_ptr<MacroRulesDefinition>
|
||||
mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
|
||||
std::vector<Attribute> outer_attrs, Location locus)
|
||||
{
|
||||
return Rust::make_unique<MacroRulesDefinition> (
|
||||
MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
|
||||
AST::MacroRulesDefinition::MacroKind::MBE,
|
||||
AST::Visibility::create_error ()));
|
||||
}
|
||||
|
||||
static std::unique_ptr<MacroRulesDefinition>
|
||||
decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
|
||||
std::vector<Attribute> outer_attrs, Location locus,
|
||||
Visibility vis)
|
||||
{
|
||||
return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
|
||||
rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
|
||||
AST::MacroRulesDefinition::MacroKind::DeclMacro, vis));
|
||||
}
|
||||
|
||||
void accept_vis (ASTVisitor &vis) override;
|
||||
|
||||
// Invalid if rule name is empty, so base stripping on that.
|
||||
@@ -549,7 +582,7 @@ protected:
|
||||
* compile time */
|
||||
class MacroInvocation : public TypeNoBounds,
|
||||
public Pattern,
|
||||
public MacroItem,
|
||||
public Item,
|
||||
public TraitItem,
|
||||
public TraitImplItem,
|
||||
public InherentImplItem,
|
||||
|
||||
@@ -171,7 +171,7 @@ enum PrimitiveCoreType
|
||||
RS_TOKEN_KEYWORD (IN, "in") \
|
||||
RS_TOKEN_KEYWORD (LET, "let") \
|
||||
RS_TOKEN_KEYWORD (LOOP, "loop") \
|
||||
RS_TOKEN_KEYWORD (MACRO, "macro") /* unused */ \
|
||||
RS_TOKEN_KEYWORD (MACRO, "macro") \
|
||||
RS_TOKEN_KEYWORD (MATCH_TOK, "match") \
|
||||
RS_TOKEN_KEYWORD (MOD, "mod") \
|
||||
RS_TOKEN_KEYWORD (MOVE, "move") \
|
||||
|
||||
@@ -1032,11 +1032,6 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
|
||||
|
||||
// parse outer attributes for item
|
||||
AST::AttrVec outer_attrs = parse_outer_attributes ();
|
||||
|
||||
// TODO: decide how to deal with VisItem vs MacroItem dichotomy
|
||||
/* best current solution: catch all keywords that would imply a VisItem in a
|
||||
* switch and have MacroItem as a last resort */
|
||||
|
||||
const_TokenPtr t = lexer.peek_token ();
|
||||
|
||||
switch (t->get_id ())
|
||||
@@ -1064,6 +1059,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
|
||||
case STATIC_TOK:
|
||||
case TRAIT:
|
||||
case IMPL:
|
||||
case MACRO:
|
||||
/* TODO: implement union keyword but not really because of
|
||||
* context-dependence crappy hack way to parse a union written below to
|
||||
* separate it from the good code. */
|
||||
@@ -1078,7 +1074,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
|
||||
case CRATE:
|
||||
case DOLLAR_SIGN:
|
||||
// almost certainly macro invocation semi
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_invocation_semi (std::move (outer_attrs));
|
||||
break;
|
||||
// crappy hack to do union "keyword"
|
||||
case IDENTIFIER:
|
||||
@@ -1092,19 +1088,18 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
|
||||
else if (t->get_str () == "macro_rules")
|
||||
{
|
||||
// macro_rules! macro item
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_rules_def (std::move (outer_attrs));
|
||||
}
|
||||
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
|
||||
|| lexer.peek_token (1)->get_id () == EXCLAM)
|
||||
{
|
||||
/* path (probably) or macro invocation, so probably a macro invocation
|
||||
* semi */
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_invocation_semi (std::move (outer_attrs));
|
||||
}
|
||||
gcc_fallthrough ();
|
||||
default:
|
||||
// otherwise unrecognised
|
||||
// return parse_macro_item(std::move(outer_attrs));
|
||||
add_error (Error (t->get_locus (),
|
||||
"unrecognised token %qs for start of %s",
|
||||
t->get_token_description (),
|
||||
@@ -1335,6 +1330,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
|
||||
lexer.skip_token (1); // TODO: is this right thing to do?
|
||||
return nullptr;
|
||||
}
|
||||
case MACRO:
|
||||
return parse_decl_macro_def (std::move (vis), std::move (outer_attrs));
|
||||
default:
|
||||
// otherwise vis item clearly doesn't exist, which is not an error
|
||||
// has a catch-all post-switch return to allow other breaks to occur
|
||||
@@ -1343,42 +1340,6 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition).
|
||||
template <typename ManagedTokenSource>
|
||||
std::unique_ptr<AST::MacroItem>
|
||||
Parser<ManagedTokenSource>::parse_macro_item (AST::AttrVec outer_attrs)
|
||||
{
|
||||
const_TokenPtr t = lexer.peek_token ();
|
||||
|
||||
/* dodgy way of detecting macro due to weird context-dependence thing.
|
||||
* probably can be improved */
|
||||
// TODO: ensure that string compare works properly
|
||||
if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules")
|
||||
{
|
||||
return parse_macro_rules_def (std::move (outer_attrs));
|
||||
}
|
||||
else
|
||||
{
|
||||
// DEBUG: TODO: remove
|
||||
rust_debug (
|
||||
"DEBUG - parse_macro_item called and token is not macro_rules");
|
||||
if (t->get_id () == IDENTIFIER)
|
||||
{
|
||||
rust_debug ("just add to last error: token is not macro_rules and is "
|
||||
"instead '%s'",
|
||||
t->get_str ().c_str ());
|
||||
}
|
||||
else
|
||||
{
|
||||
rust_debug ("just add to last error: token is not macro_rules and is "
|
||||
"not an identifier either - it is '%s'",
|
||||
t->get_token_description ());
|
||||
}
|
||||
|
||||
return parse_macro_invocation_semi (std::move (outer_attrs));
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a macro rules definition syntax extension whatever thing.
|
||||
template <typename ManagedTokenSource>
|
||||
std::unique_ptr<AST::MacroRulesDefinition>
|
||||
@@ -1512,16 +1473,16 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
|
||||
{
|
||||
// as this is the end, allow recovery (probably) - may change
|
||||
return std::unique_ptr<AST::MacroRulesDefinition> (
|
||||
new AST::MacroRulesDefinition (
|
||||
AST::MacroRulesDefinition::mbe (
|
||||
std::move (rule_name), delim_type, std::move (macro_rules),
|
||||
std::move (outer_attrs), macro_locus));
|
||||
}
|
||||
}
|
||||
|
||||
return std::unique_ptr<AST::MacroRulesDefinition> (
|
||||
new AST::MacroRulesDefinition (std::move (rule_name), delim_type,
|
||||
std::move (macro_rules),
|
||||
std::move (outer_attrs), macro_locus));
|
||||
AST::MacroRulesDefinition::mbe (std::move (rule_name), delim_type,
|
||||
std::move (macro_rules),
|
||||
std::move (outer_attrs), macro_locus));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1541,6 +1502,165 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a declarative macro 2.0 definition.
|
||||
template <typename ManagedTokenSource>
|
||||
std::unique_ptr<AST::MacroRulesDefinition>
|
||||
Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis,
|
||||
AST::AttrVec outer_attrs)
|
||||
{
|
||||
// ensure that first token is identifier saying "macro"
|
||||
const_TokenPtr t = lexer.peek_token ();
|
||||
if (t->get_id () != MACRO)
|
||||
{
|
||||
Error error (
|
||||
t->get_locus (),
|
||||
"declarative macro definition does not start with %<macro%>");
|
||||
add_error (std::move (error));
|
||||
|
||||
// skip after somewhere?
|
||||
return nullptr;
|
||||
}
|
||||
lexer.skip_token ();
|
||||
Location macro_locus = t->get_locus ();
|
||||
|
||||
// parse macro name
|
||||
const_TokenPtr ident_tok = expect_token (IDENTIFIER);
|
||||
if (ident_tok == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
Identifier rule_name = ident_tok->get_str ();
|
||||
|
||||
t = lexer.peek_token ();
|
||||
if (t->get_id () == LEFT_PAREN)
|
||||
{
|
||||
// single definiton of macro rule
|
||||
// e.g. `macro foo($e:expr) {}`
|
||||
|
||||
// parse macro matcher
|
||||
Location locus = lexer.peek_token ()->get_locus ();
|
||||
AST::MacroMatcher matcher = parse_macro_matcher ();
|
||||
if (matcher.is_error ())
|
||||
return nullptr;
|
||||
|
||||
// check delimiter of macro matcher
|
||||
if (matcher.get_delim_type () != AST::DelimType::PARENS)
|
||||
{
|
||||
Error error (locus, "only parenthesis can be used for a macro "
|
||||
"matcher in declarative macro definition");
|
||||
add_error (std::move (error));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Location transcriber_loc = lexer.peek_token ()->get_locus ();
|
||||
AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree ();
|
||||
AST::MacroTranscriber transcriber (delim_tok_tree, transcriber_loc);
|
||||
|
||||
if (transcriber.get_token_tree ().get_delim_type ()
|
||||
!= AST::DelimType::CURLY)
|
||||
{
|
||||
Error error (transcriber_loc,
|
||||
"only braces can be used for a macro transcriber "
|
||||
"in declarative macro definition");
|
||||
add_error (std::move (error));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AST::MacroRule macro_rule
|
||||
= AST::MacroRule (std::move (matcher), std::move (transcriber), locus);
|
||||
std::vector<AST::MacroRule> macro_rules;
|
||||
macro_rules.push_back (macro_rule);
|
||||
|
||||
return std::unique_ptr<AST::MacroRulesDefinition> (
|
||||
AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
|
||||
macro_rules,
|
||||
std::move (outer_attrs),
|
||||
macro_locus, vis));
|
||||
}
|
||||
else if (t->get_id () == LEFT_CURLY)
|
||||
{
|
||||
// multiple definitions of macro rule separated by comma
|
||||
// e.g. `macro foo { () => {}, ($e:expr) => {}, }`
|
||||
|
||||
// parse left curly
|
||||
const_TokenPtr left_curly = expect_token (LEFT_CURLY);
|
||||
if (left_curly == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// parse actual macro rules
|
||||
std::vector<AST::MacroRule> macro_rules;
|
||||
|
||||
// must be at least one macro rule, so parse it
|
||||
AST::MacroRule initial_rule = parse_macro_rule ();
|
||||
if (initial_rule.is_error ())
|
||||
{
|
||||
Error error (
|
||||
lexer.peek_token ()->get_locus (),
|
||||
"required first macro rule in declarative macro definition "
|
||||
"could not be parsed");
|
||||
add_error (std::move (error));
|
||||
|
||||
// skip after somewhere?
|
||||
return nullptr;
|
||||
}
|
||||
macro_rules.push_back (std::move (initial_rule));
|
||||
|
||||
t = lexer.peek_token ();
|
||||
// parse macro rules
|
||||
while (t->get_id () == COMMA)
|
||||
{
|
||||
// skip comma
|
||||
lexer.skip_token ();
|
||||
|
||||
// don't parse if end of macro rules
|
||||
if (token_id_matches_delims (lexer.peek_token ()->get_id (),
|
||||
AST::CURLY))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// try to parse next rule
|
||||
AST::MacroRule rule = parse_macro_rule ();
|
||||
if (rule.is_error ())
|
||||
{
|
||||
Error error (
|
||||
lexer.peek_token ()->get_locus (),
|
||||
"failed to parse macro rule in declarative macro definition");
|
||||
add_error (std::move (error));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
macro_rules.push_back (std::move (rule));
|
||||
|
||||
t = lexer.peek_token ();
|
||||
}
|
||||
|
||||
// parse right curly
|
||||
const_TokenPtr right_curly = expect_token (RIGHT_CURLY);
|
||||
if (right_curly == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::unique_ptr<AST::MacroRulesDefinition> (
|
||||
AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
|
||||
std::move (macro_rules),
|
||||
std::move (outer_attrs),
|
||||
macro_locus, vis));
|
||||
}
|
||||
else
|
||||
{
|
||||
add_error (Error (t->get_locus (),
|
||||
"unexpected token %qs - expecting delimiters "
|
||||
"(for a declarative macro definiton)",
|
||||
t->get_token_description ()));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a semi-coloned (except for full block) macro invocation item.
|
||||
template <typename ManagedTokenSource>
|
||||
std::unique_ptr<AST::MacroInvocation>
|
||||
@@ -6004,6 +6124,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
|
||||
case STATIC_TOK:
|
||||
case TRAIT:
|
||||
case IMPL:
|
||||
case MACRO:
|
||||
/* TODO: implement union keyword but not really because of
|
||||
* context-dependence crappy hack way to parse a union written below to
|
||||
* separate it from the good code. */
|
||||
@@ -6019,7 +6140,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
|
||||
case CRATE:
|
||||
case DOLLAR_SIGN:
|
||||
// almost certainly macro invocation semi
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_invocation_semi (std::move (outer_attrs));
|
||||
break;
|
||||
// crappy hack to do union "keyword"
|
||||
case IDENTIFIER:
|
||||
@@ -6032,7 +6153,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
|
||||
else if (t->get_str () == "macro_rules")
|
||||
{
|
||||
// macro_rules! macro item
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_rules_def (std::move (outer_attrs));
|
||||
}
|
||||
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
|
||||
|| lexer.peek_token (1)->get_id () == EXCLAM)
|
||||
@@ -6040,7 +6161,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
|
||||
// FIXME: ensure doesn't take any expressions by mistake
|
||||
/* path (probably) or macro invocation, so probably a macro
|
||||
* invocation semi */
|
||||
return parse_macro_item (std::move (outer_attrs));
|
||||
return parse_macro_invocation_semi (std::move (outer_attrs));
|
||||
}
|
||||
gcc_fallthrough ();
|
||||
// TODO: find out how to disable gcc "implicit fallthrough" warning
|
||||
@@ -11711,8 +11832,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
|
||||
else if (t->get_str () == "macro_rules")
|
||||
{
|
||||
// macro_rules! macro item
|
||||
std::unique_ptr<AST::MacroItem> item (
|
||||
parse_macro_item (std::move (outer_attrs)));
|
||||
std::unique_ptr<AST::Item> item (
|
||||
parse_macro_rules_def (std::move (outer_attrs)));
|
||||
return ExprOrStmt (std::move (item));
|
||||
}
|
||||
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
|
||||
|
||||
@@ -197,6 +197,8 @@ private:
|
||||
AST::DelimTokenTree parse_delim_token_tree ();
|
||||
std::unique_ptr<AST::MacroRulesDefinition>
|
||||
parse_macro_rules_def (AST::AttrVec outer_attrs);
|
||||
std::unique_ptr<AST::MacroRulesDefinition>
|
||||
parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
|
||||
std::unique_ptr<AST::MacroInvocation>
|
||||
parse_macro_invocation_semi (AST::AttrVec outer_attrs);
|
||||
std::unique_ptr<AST::MacroInvocation>
|
||||
@@ -209,7 +211,6 @@ private:
|
||||
|
||||
// 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,
|
||||
|
||||
2
gcc/testsuite/rust/compile/decl_macro1.rs
Normal file
2
gcc/testsuite/rust/compile/decl_macro1.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
#![feature(decl_macro)]
|
||||
macro m() {}
|
||||
2
gcc/testsuite/rust/compile/decl_macro2.rs
Normal file
2
gcc/testsuite/rust/compile/decl_macro2.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
#![feature(decl_macro)]
|
||||
pub macro m($e: expr) { $e + $e }
|
||||
4
gcc/testsuite/rust/compile/decl_macro3.rs
Normal file
4
gcc/testsuite/rust/compile/decl_macro3.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#![feature(decl_macro)]
|
||||
macro foo {
|
||||
() => {}
|
||||
}
|
||||
5
gcc/testsuite/rust/compile/decl_macro4.rs
Normal file
5
gcc/testsuite/rust/compile/decl_macro4.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
#![feature(decl_macro)]
|
||||
macro foo {
|
||||
() => { 0 },
|
||||
($n: expr) => { $n + 1 },
|
||||
}
|
||||
5
gcc/testsuite/rust/compile/decl_macro5.rs
Normal file
5
gcc/testsuite/rust/compile/decl_macro5.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
#![feature(decl_macro)]
|
||||
macro foo {
|
||||
() => [],
|
||||
($h: expr, $(t: expr),*) => ($h),
|
||||
}
|
||||
5
gcc/testsuite/rust/compile/decl_macro6.rs
Normal file
5
gcc/testsuite/rust/compile/decl_macro6.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
#![feature(decl_macro)]
|
||||
macro m {}
|
||||
// { dg-error "unexpected token .\}. - expecting delimiters .for a macro matcher." "" { target *-*-* } .-1 }
|
||||
// { dg-error "required first macro rule in declarative macro definition could not be parsed" "" { target *-*-* } .-2 }
|
||||
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
|
||||
4
gcc/testsuite/rust/compile/decl_macro7.rs
Normal file
4
gcc/testsuite/rust/compile/decl_macro7.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#![feature(decl_macro)]
|
||||
pub macro hello() [ "Hello" ]
|
||||
// { dg-error "only braces can be used for a macro transcriber in declarative macro definition" "" { target *-*-* } .-1 }
|
||||
// { dg-error "failed to parse item in crate" }
|
||||
8
gcc/testsuite/rust/execute/torture/decl_macro1.rs
Normal file
8
gcc/testsuite/rust/execute/torture/decl_macro1.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
#![feature(decl_macro)]
|
||||
macro one() {
|
||||
1
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
one!() - 1
|
||||
}
|
||||
8
gcc/testsuite/rust/execute/torture/decl_macro2.rs
Normal file
8
gcc/testsuite/rust/execute/torture/decl_macro2.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
#![feature(decl_macro)]
|
||||
macro one {
|
||||
() => { 1 }
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
one!() - 1
|
||||
}
|
||||
15
gcc/testsuite/rust/execute/torture/decl_macro3.rs
Normal file
15
gcc/testsuite/rust/execute/torture/decl_macro3.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
#![feature(decl_macro)]
|
||||
macro add {
|
||||
($e:expr) => {
|
||||
$e
|
||||
},
|
||||
($h:expr, $($t:expr),*) => {
|
||||
$h + add!($($t),*)
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let a = add!(1, 2, 3);
|
||||
|
||||
a - 6
|
||||
}
|
||||
15
gcc/testsuite/rust/execute/torture/decl_macro4.rs
Normal file
15
gcc/testsuite/rust/execute/torture/decl_macro4.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
#![feature(decl_macro)]
|
||||
pub macro add {
|
||||
($e:expr) => {
|
||||
$e
|
||||
},
|
||||
($h:expr, $($t:expr),*) => {
|
||||
$h + add!($($t),*)
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let a = add!(1, 2, 3);
|
||||
|
||||
a - 6
|
||||
}
|
||||
Reference in New Issue
Block a user