Skip to content

Commit 6e05dac

Browse files
authored
Merge pull request #74 from alexcrichton/lex-doc-comments
Lex doc comments as attributes
2 parents 99d9630 + 1eb96a0 commit 6e05dac

File tree

3 files changed

+113
-71
lines changed

3 files changed

+113
-71
lines changed

src/stable.rs

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -591,24 +591,55 @@ impl fmt::Display for Literal {
591591
}
592592
}
593593

594-
named!(token_stream -> ::TokenStream, map!(
595-
many0!(token_tree),
596-
|trees| ::TokenStream::_new(TokenStream { inner: trees })
597-
));
594+
fn token_stream(mut input: Cursor) -> PResult<::TokenStream> {
595+
let mut trees = Vec::new();
596+
loop {
597+
let input_no_ws = skip_whitespace(input);
598+
if input_no_ws.rest.len() == 0 {
599+
break
600+
}
601+
if let Ok((a, tokens)) = doc_comment(input_no_ws) {
602+
input = a;
603+
trees.extend(tokens);
604+
continue
605+
}
606+
607+
let (a, tt) = match token_tree(input_no_ws) {
608+
Ok(p) => p,
609+
Err(_) => break,
610+
};
611+
trees.push(tt);
612+
input = a;
613+
}
614+
Ok((input, ::TokenStream::_new(TokenStream { inner: trees })))
615+
}
598616

599617
#[cfg(not(procmacro2_semver_exempt))]
600-
fn token_tree(input: Cursor) -> PResult<TokenTree> {
601-
token_kind(input)
618+
fn spanned<'a, T>(
619+
input: Cursor<'a>,
620+
f: fn(Cursor<'a>) -> PResult<'a, T>,
621+
) -> PResult<'a, (T, ::Span)> {
622+
let (a, b) = f(skip_whitespace(input))?;
623+
Ok((a, ((b, ::Span::_new(Span { })))))
602624
}
603625

604626
#[cfg(procmacro2_semver_exempt)]
605-
fn token_tree(input: Cursor) -> PResult<TokenTree> {
627+
fn spanned<'a, T>(
628+
input: Cursor<'a>,
629+
f: fn(Cursor<'a>) -> PResult<'a, T>,
630+
) -> PResult<'a, (T, ::Span)> {
606631
let input = skip_whitespace(input);
607632
let lo = input.off;
608-
let (input, mut token) = token_kind(input)?;
609-
let hi = input.off;
610-
token.set_span(::Span::_new(Span { lo: lo, hi: hi }));
611-
Ok((input, token))
633+
let (a, b) = f(input)?;
634+
let hi = a.off;
635+
let span = ::Span::_new(Span { lo: lo, hi: hi });
636+
Ok((a, (b, span)))
637+
}
638+
639+
fn token_tree(input: Cursor) -> PResult<TokenTree> {
640+
let (rest, (mut tt, span)) = spanned(input, token_kind)?;
641+
tt.set_span(span);
642+
Ok((rest, tt))
612643
}
613644

614645
named!(token_kind -> TokenTree, alt!(
@@ -721,8 +752,6 @@ named!(literal_nocapture -> (), alt!(
721752
float
722753
|
723754
int
724-
|
725-
doc_comment
726755
));
727756

728757
named!(string -> (), alt!(
@@ -1146,31 +1175,53 @@ fn op_char(input: Cursor) -> PResult<char> {
11461175
}
11471176
}
11481177

1149-
named!(doc_comment -> (), alt!(
1178+
fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> {
1179+
let mut trees = Vec::new();
1180+
let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?;
1181+
trees.push(TokenTree::Op(Op::new('#', Spacing::Alone)));
1182+
if inner {
1183+
trees.push(Op::new('!', Spacing::Alone).into());
1184+
}
1185+
let mut stream = vec![
1186+
TokenTree::Term(::Term::new("doc", span)),
1187+
TokenTree::Op(Op::new('=', Spacing::Alone)),
1188+
TokenTree::Literal(::Literal::string(comment)),
1189+
];
1190+
for tt in stream.iter_mut() {
1191+
tt.set_span(span);
1192+
}
1193+
trees.push(Group::new(Delimiter::Bracket, stream.into_iter().collect()).into());
1194+
for tt in trees.iter_mut() {
1195+
tt.set_span(span);
1196+
}
1197+
Ok((rest, trees))
1198+
}
1199+
1200+
named!(doc_comment_contents -> (&str, bool), alt!(
11501201
do_parse!(
11511202
punct!("//!") >>
1152-
take_until_newline_or_eof!() >>
1153-
(())
1203+
s: take_until_newline_or_eof!() >>
1204+
((s, true))
11541205
)
11551206
|
11561207
do_parse!(
11571208
option!(whitespace) >>
11581209
peek!(tag!("/*!")) >>
1159-
block_comment >>
1160-
(())
1210+
s: block_comment >>
1211+
((s, true))
11611212
)
11621213
|
11631214
do_parse!(
11641215
punct!("///") >>
11651216
not!(tag!("/")) >>
1166-
take_until_newline_or_eof!() >>
1167-
(())
1217+
s: take_until_newline_or_eof!() >>
1218+
((s, false))
11681219
)
11691220
|
11701221
do_parse!(
11711222
option!(whitespace) >>
11721223
peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
1173-
block_comment >>
1174-
(())
1224+
s: block_comment >>
1225+
((s, false))
11751226
)
11761227
));

src/strnom.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ macro_rules! take_until_newline_or_eof {
268268
} else {
269269
match $i.find('\n') {
270270
Some(i) => Ok(($i.advance(i), &$i.rest[..i])),
271-
None => Ok(($i.advance($i.len()), "")),
271+
None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])),
272272
}
273273
}
274274
}};
@@ -389,37 +389,3 @@ macro_rules! map {
389389
map!($i, call!($f), $g)
390390
};
391391
}
392-
393-
macro_rules! many0 {
394-
($i:expr, $f:expr) => {{
395-
let ret;
396-
let mut res = ::std::vec::Vec::new();
397-
let mut input = $i;
398-
399-
loop {
400-
if input.is_empty() {
401-
ret = Ok((input, res));
402-
break;
403-
}
404-
405-
match $f(input) {
406-
Err(LexError) => {
407-
ret = Ok((input, res));
408-
break;
409-
}
410-
Ok((i, o)) => {
411-
// loop trip must always consume (otherwise infinite loops)
412-
if i.len() == input.len() {
413-
ret = Err(LexError);
414-
break;
415-
}
416-
417-
res.push(o);
418-
input = i;
419-
}
420-
}
421-
}
422-
423-
ret
424-
}};
425-
}

tests/test.rs

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ fn roundtrip() {
2929
roundtrip("a");
3030
roundtrip("<<");
3131
roundtrip("<<=");
32-
roundtrip(
33-
"
34-
/// a
35-
wut
36-
",
37-
);
3832
roundtrip(
3933
"
4034
1
@@ -115,12 +109,16 @@ testing 123
115109
testing 234
116110
}",
117111
&[
118-
(1, 0, 1, 30),
119-
(2, 0, 2, 7),
120-
(2, 8, 2, 11),
121-
(3, 0, 5, 1),
122-
(4, 2, 4, 9),
123-
(4, 10, 4, 13),
112+
(1, 0, 1, 30), // #
113+
(1, 0, 1, 30), // [ ... ]
114+
(1, 0, 1, 30), // doc
115+
(1, 0, 1, 30), // =
116+
(1, 0, 1, 30), // "This is..."
117+
(2, 0, 2, 7), // testing
118+
(2, 8, 2, 11), // 123
119+
(3, 0, 5, 1), // { ... }
120+
(4, 2, 4, 9), // testing
121+
(4, 10, 4, 13), // 234
124122
],
125123
);
126124
}
@@ -192,11 +190,38 @@ fn tricky_doc_comment() {
192190

193191
let stream = "/// doc".parse::<proc_macro2::TokenStream>().unwrap();
194192
let tokens = stream.into_iter().collect::<Vec<_>>();
195-
assert!(tokens.len() == 1, "not length 1 -- {:?}", tokens);
193+
assert!(tokens.len() == 2, "not length 2 -- {:?}", tokens);
196194
match tokens[0] {
197-
proc_macro2::TokenTree::Literal(_) => {}
195+
proc_macro2::TokenTree::Op(ref tt) => assert_eq!(tt.op(), '#'),
198196
_ => panic!("wrong token {:?}", tokens[0]),
199197
}
198+
let mut tokens = match tokens[1] {
199+
proc_macro2::TokenTree::Group(ref tt) => {
200+
assert_eq!(tt.delimiter(), proc_macro2::Delimiter::Bracket);
201+
tt.stream().into_iter()
202+
}
203+
_ => panic!("wrong token {:?}", tokens[0]),
204+
};
205+
206+
match tokens.next().unwrap() {
207+
proc_macro2::TokenTree::Term(ref tt) => assert_eq!(tt.as_str(), "doc"),
208+
t => panic!("wrong token {:?}", t),
209+
}
210+
match tokens.next().unwrap() {
211+
proc_macro2::TokenTree::Op(ref tt) => assert_eq!(tt.op(), '='),
212+
t => panic!("wrong token {:?}", t),
213+
}
214+
match tokens.next().unwrap() {
215+
proc_macro2::TokenTree::Literal(ref tt) => {
216+
assert_eq!(tt.to_string(), "\" doc\"");
217+
}
218+
t => panic!("wrong token {:?}", t),
219+
}
220+
assert!(tokens.next().is_none());
221+
222+
let stream = "//! doc".parse::<proc_macro2::TokenStream>().unwrap();
223+
let tokens = stream.into_iter().collect::<Vec<_>>();
224+
assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens);
200225
}
201226

202227
#[test]

0 commit comments

Comments
 (0)