Merge #1161
1161: Add mbe 'item' matcher r=matklad a=edwin0cheng Add `item` matcher in `ra_mbe` , and added corresponding `item()` parser in `ra_syntax`. This PR also help PR #1148 for `Items` parsing. And hopefully fix #1149 ?! Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
403cd78bae
6 changed files with 70 additions and 0 deletions
|
@ -597,4 +597,48 @@ SOURCE_FILE@[0; 40)
|
||||||
assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}");
|
assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}");
|
||||||
assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
|
assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_single_item() {
|
||||||
|
let rules = create_rules(
|
||||||
|
r#"
|
||||||
|
macro_rules! foo {
|
||||||
|
($ i:item) => (
|
||||||
|
$ i
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_expansion(&rules, "foo! {mod c {}}", "mod c {}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all_items() {
|
||||||
|
let rules = create_rules(
|
||||||
|
r#"
|
||||||
|
macro_rules! foo {
|
||||||
|
($ ($ i:item)*) => ($ (
|
||||||
|
$ i
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_expansion(&rules, r#"
|
||||||
|
foo! {
|
||||||
|
extern crate a;
|
||||||
|
mod b;
|
||||||
|
mod c {}
|
||||||
|
use d;
|
||||||
|
const E: i32 = 0;
|
||||||
|
static F: i32 = 0;
|
||||||
|
impl G {}
|
||||||
|
struct H;
|
||||||
|
enum I { Foo }
|
||||||
|
trait J {}
|
||||||
|
fn h() {}
|
||||||
|
extern {}
|
||||||
|
type T = u8;
|
||||||
|
}
|
||||||
|
"#, r#"extern crate a ; mod b ; mod c {} use d ; const E : i32 = 0 ; static F : i32 = 0 ; impl G {} struct H ; enum I {Foo} trait J {} fn h () {} extern {} type T = u8 ;"#);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
|
||||||
let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone();
|
let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone();
|
||||||
res.inner.insert(text.clone(), Binding::Simple(pat.into()));
|
res.inner.insert(text.clone(), Binding::Simple(pat.into()));
|
||||||
}
|
}
|
||||||
|
"item" => {
|
||||||
|
let item =
|
||||||
|
input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone();
|
||||||
|
res.inner.insert(text.clone(), Binding::Simple(item.into()));
|
||||||
|
}
|
||||||
_ => return Err(ExpandError::UnexpectedToken),
|
_ => return Err(ExpandError::UnexpectedToken),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,6 +283,9 @@ mod tests {
|
||||||
|
|
||||||
assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
|
assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
|
||||||
assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
|
assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// Add an err test case for ($($i:ident)) => ($())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) {
|
fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) {
|
||||||
|
|
|
@ -46,6 +46,10 @@ impl<'a> Parser<'a> {
|
||||||
self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false))
|
self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_item(self) -> Option<tt::TokenTree> {
|
||||||
|
self.parse(ra_parser::parse_item)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse<F>(self, f: F) -> Option<tt::TokenTree>
|
fn parse<F>(self, f: F) -> Option<tt::TokenTree>
|
||||||
where
|
where
|
||||||
F: FnOnce(&dyn TokenSource, &mut dyn TreeSink),
|
F: FnOnce(&dyn TokenSource, &mut dyn TreeSink),
|
||||||
|
|
|
@ -104,6 +104,11 @@ impl<'a> TtCursor<'a> {
|
||||||
parser.parse_stmt()
|
parser.parse_stmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> {
|
||||||
|
let parser = Parser::new(&mut self.pos, self.subtree);
|
||||||
|
parser.parse_item()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> {
|
pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> {
|
||||||
if self.at_char(char) {
|
if self.at_char(char) {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
|
@ -69,6 +69,10 @@ pub(crate) fn stmt(p: &mut Parser, with_semi: bool) {
|
||||||
expressions::stmt(p, with_semi)
|
expressions::stmt(p, with_semi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn item(p: &mut Parser) {
|
||||||
|
items::item_or_macro(p, true, items::ItemFlavor::Mod)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn reparser(
|
pub(crate) fn reparser(
|
||||||
node: SyntaxKind,
|
node: SyntaxKind,
|
||||||
first_child: Option<SyntaxKind>,
|
first_child: Option<SyntaxKind>,
|
||||||
|
|
|
@ -93,6 +93,11 @@ pub fn parse_stmt(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink,
|
||||||
parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi));
|
parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse given tokens into the given sink as an item
|
||||||
|
pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
|
||||||
|
parse_from_tokens(token_source, tree_sink, grammar::item);
|
||||||
|
}
|
||||||
|
|
||||||
/// A parsing function for a specific braced-block.
|
/// A parsing function for a specific braced-block.
|
||||||
pub struct Reparser(fn(&mut parser::Parser));
|
pub struct Reparser(fn(&mut parser::Parser));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue