Skip to content

Commit ba6980a

Browse files
authored
Support tuples and arrays in path parser (#17)
1 parent 680794d commit ba6980a

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "myn"
33
description = "Minimalist Rust syntax parsing for procedural macros"
4-
version = "0.2.1"
4+
version = "0.2.2"
55
authors = ["Jay Oster <[email protected]>"]
66
repository = "https://github.com/parasyte/myn"
77
edition = "2021"

src/ty.rs

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ impl TokenIterExt for TokenIter {
6666

6767
while let Some(tree) = self.peek() {
6868
match tree {
69-
TokenTree::Punct(punct) if punct.as_char() == ',' && nesting == 0 => break,
69+
TokenTree::Punct(punct)
70+
if [',', ';'].contains(&punct.as_char()) && nesting == 0 =>
71+
{
72+
break
73+
}
7074
TokenTree::Punct(punct) => {
7175
let ch = punct.as_char();
7276

@@ -84,7 +88,43 @@ impl TokenIterExt for TokenIter {
8488
span.get_or_insert_with(|| ident.span());
8589
path.push_str(&ident.to_string());
8690
}
87-
_ => return Err(spanned_error("Unexpected token", self.next().as_span())),
91+
TokenTree::Group(group) => {
92+
span.get_or_insert(group.span());
93+
let mut stream = group.stream().into_token_iter();
94+
95+
match group.delimiter() {
96+
Delimiter::Parenthesis => {
97+
// Tuples are comma-separated paths.
98+
path.push('(');
99+
while stream.peek().is_some() {
100+
let (inner, _span) = stream.parse_path()?;
101+
path.push_str(&inner);
102+
if stream.peek().is_some() {
103+
stream.expect_punct(',')?;
104+
path.push_str(", ");
105+
}
106+
}
107+
if path.ends_with(' ') {
108+
path.pop();
109+
}
110+
path.push(')');
111+
}
112+
Delimiter::Bracket => {
113+
// Arrays are in `[path; size]` form.
114+
path.push('[');
115+
let (inner, _span) = stream.parse_path()?;
116+
path.push_str(&inner);
117+
stream.expect_punct(';')?;
118+
path.push_str("; ");
119+
path.push_str(&stream.try_lit()?.to_string());
120+
path.push(']');
121+
}
122+
_ => return Err(spanned_error("Unexpected token", group.span())),
123+
}
124+
}
125+
TokenTree::Literal(_) => {
126+
return Err(spanned_error("Unexpected token", self.next().as_span()))
127+
}
88128
}
89129

90130
self.next();
@@ -192,6 +232,44 @@ mod tests {
192232
use super::*;
193233
use std::str::FromStr;
194234

235+
#[test]
236+
fn test_tokeniter_parse_path() {
237+
let mut input = TokenStream::from_str("foo::bar").unwrap().into_token_iter();
238+
assert_eq!(input.parse_path().unwrap().0, "foo::bar");
239+
assert!(input.next().is_none());
240+
241+
let mut input = TokenStream::from_str("foo::bar<baz>")
242+
.unwrap()
243+
.into_token_iter();
244+
assert_eq!(input.parse_path().unwrap().0, "foo::bar<baz>");
245+
assert!(input.next().is_none());
246+
247+
let mut input = TokenStream::from_str("foo::bar<()>")
248+
.unwrap()
249+
.into_token_iter();
250+
assert_eq!(input.parse_path().unwrap().0, "foo::bar<()>");
251+
assert!(input.next().is_none());
252+
253+
let mut input = TokenStream::from_str("foo::bar<(foo, bar::baz<T>)>")
254+
.unwrap()
255+
.into_token_iter();
256+
assert_eq!(
257+
input.parse_path().unwrap().0,
258+
"foo::bar<(foo, bar::baz<T>)>"
259+
);
260+
assert!(input.next().is_none());
261+
262+
let mut input = TokenStream::from_str("foo<(bar, [i32; 4])>")
263+
.unwrap()
264+
.into_token_iter();
265+
assert_eq!(input.parse_path().unwrap().0, "foo<(bar, [i32; 4])>");
266+
assert!(input.next().is_none());
267+
268+
let mut input = TokenStream::from_str("(u8, )").unwrap().into_token_iter();
269+
assert_eq!(input.parse_path().unwrap().0, "(u8,)");
270+
assert!(input.next().is_none());
271+
}
272+
195273
#[test]
196274
fn test_tokeniter_expect_group() {
197275
let mut input = TokenStream::from_str("{ foo }").unwrap().into_token_iter();

0 commit comments

Comments
 (0)