blob: 339797ea3263f7e8ac1e6df69f53d3d3907cebdf [file] [log] [blame]
Alex Crichton44bffbc2017-05-19 17:51:59 -07001extern crate unicode_xid;
2
Alex Crichton76a5cc82017-05-23 07:01:44 -07003use std::ascii;
Alex Crichton44bffbc2017-05-19 17:51:59 -07004use std::borrow::Borrow;
5use std::cell::RefCell;
6use std::collections::HashMap;
7use std::fmt;
8use std::iter;
9use std::ops;
10use std::rc::Rc;
11use std::str::FromStr;
12use std::vec;
13
14use proc_macro;
15use self::unicode_xid::UnicodeXID;
16use synom::space::{skip_whitespace, block_comment, whitespace};
17use synom::{IResult};
18
19use {TokenTree, TokenKind, Delimiter, OpKind};
20
21#[derive(Clone)]
22pub struct TokenStream {
23 inner: Vec<TokenTree>,
24}
25
26#[derive(Debug)]
27pub struct LexError;
28
29impl TokenStream {
30 pub fn empty() -> TokenStream {
31 TokenStream { inner: Vec::new() }
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.inner.len() == 0
36 }
37}
38
39impl FromStr for TokenStream {
40 type Err = LexError;
41
42 fn from_str(src: &str) -> Result<TokenStream, LexError> {
43 match token_stream(src) {
44 IResult::Done(input, output) => {
45 if skip_whitespace(input).len() != 0 {
46 Err(LexError)
47 } else {
48 Ok(output)
49 }
50 }
51 IResult::Error => Err(LexError),
52 }
53 }
54}
55
56impl fmt::Display for TokenStream {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 let mut joint = false;
59 for (i, tt) in self.inner.iter().enumerate() {
60 if i != 0 && !joint {
61 write!(f, " ")?;
62 }
63 joint = false;
64 match tt.kind {
65 TokenKind::Sequence(delim, ref stream) => {
66 let (start, end) = match delim {
67 Delimiter::Parenthesis => ("(", ")"),
68 Delimiter::Brace => ("{", "}"),
69 Delimiter::Bracket => ("[", "]"),
70 Delimiter::None => ("", ""),
71 };
Alex Crichton852d53d2017-05-19 19:25:08 -070072 if stream.0.inner.len() == 0 {
73 write!(f, "{} {}", start, end)?
74 } else {
75 write!(f, "{} {} {}", start, stream, end)?
76 }
Alex Crichton44bffbc2017-05-19 17:51:59 -070077 }
Alex Crichton9c2fb0a2017-05-26 08:49:31 -070078 TokenKind::Word(ref sym) => write!(f, "{}", sym.as_str())?,
Alex Crichton44bffbc2017-05-19 17:51:59 -070079 TokenKind::Op(ch, ref op) => {
80 write!(f, "{}", ch)?;
81 match *op {
82 OpKind::Alone => {}
83 OpKind::Joint => joint = true,
84 }
85 }
86 TokenKind::Literal(ref literal) => {
87 write!(f, "{}", literal)?;
88 // handle comments
89 if (literal.0).0.starts_with("/") {
90 write!(f, "\n")?;
91 }
92 }
93 }
94 }
95
96 Ok(())
97 }
98}
99
100impl From<proc_macro::TokenStream> for TokenStream {
101 fn from(inner: proc_macro::TokenStream) -> TokenStream {
102 inner.to_string().parse().expect("compiler token stream parse failed")
103 }
104}
105
106impl From<TokenStream> for proc_macro::TokenStream {
107 fn from(inner: TokenStream) -> proc_macro::TokenStream {
108 inner.to_string().parse().expect("failed to parse to compiler tokens")
109 }
110}
111
112
113impl From<TokenTree> for TokenStream {
114 fn from(tree: TokenTree) -> TokenStream {
115 TokenStream { inner: vec![tree] }
116 }
117}
118
119impl iter::FromIterator<TokenStream> for TokenStream {
120 fn from_iter<I: IntoIterator<Item=TokenStream>>(streams: I) -> Self {
121 let mut v = Vec::new();
122
123 for stream in streams.into_iter() {
124 v.extend(stream.inner);
125 }
126
127 TokenStream { inner: v }
128 }
129}
130
131pub type TokenIter = vec::IntoIter<TokenTree>;
132
133impl IntoIterator for TokenStream {
134 type Item = TokenTree;
135 type IntoIter = TokenIter;
136
137 fn into_iter(self) -> TokenIter {
138 self.inner.into_iter()
139 }
140}
141
142#[derive(Clone, Copy, Default)]
143pub struct Span;
144
145impl Span {
146 pub fn call_site() -> Span {
147 Span
148 }
149}
150
151#[derive(Copy, Clone)]
152pub struct Symbol(usize);
153
154thread_local!(static SYMBOLS: RefCell<Interner> = RefCell::new(Interner::new()));
155
156impl<'a> From<&'a str> for Symbol {
157 fn from(string: &'a str) -> Symbol {
158 Symbol(SYMBOLS.with(|s| s.borrow_mut().intern(string)))
159 }
160}
161
162impl ops::Deref for Symbol {
163 type Target = str;
164
165 fn deref(&self) -> &str {
166 SYMBOLS.with(|interner| {
167 let interner = interner.borrow();
168 let s = interner.get(self.0);
169 unsafe {
170 &*(s as *const str)
171 }
172 })
173 }
174}
175
176struct Interner {
177 string_to_index: HashMap<MyRc, usize>,
178 index_to_string: Vec<Rc<String>>,
179}
180
181#[derive(Hash, Eq, PartialEq)]
182struct MyRc(Rc<String>);
183
184impl Borrow<str> for MyRc {
185 fn borrow(&self) -> &str {
186 &self.0
187 }
188}
189
190impl Interner {
191 fn new() -> Interner {
192 Interner {
193 string_to_index: HashMap::new(),
194 index_to_string: Vec::new(),
195 }
196 }
197
198 fn intern(&mut self, s: &str) -> usize {
199 if let Some(&idx) = self.string_to_index.get(s) {
200 return idx
201 }
202 let s = Rc::new(s.to_string());
203 self.index_to_string.push(s.clone());
204 self.string_to_index.insert(MyRc(s), self.index_to_string.len() - 1);
205 self.index_to_string.len() - 1
206 }
207
208 fn get(&self, idx: usize) -> &str {
209 &self.index_to_string[idx]
210 }
211}
212
213#[derive(Clone)]
214pub struct Literal(String);
215
Alex Crichton852d53d2017-05-19 19:25:08 -0700216impl Literal {
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700217 pub fn byte_char(byte: u8) -> Literal {
Alex Crichton76a5cc82017-05-23 07:01:44 -0700218 match byte {
219 0 => Literal(format!("b'\\0'")),
220 b'\"' => Literal(format!("b'\"'")),
221 n => {
222 let mut escaped = "b'".to_string();
223 escaped.extend(ascii::escape_default(n).map(|c| c as char));
224 escaped.push('\'');
225 Literal(escaped)
226 }
227 }
228 }
229
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700230 pub fn byte_string(bytes: &[u8]) -> Literal {
Alex Crichton852d53d2017-05-19 19:25:08 -0700231 let mut escaped = "b\"".to_string();
232 for b in bytes {
233 match *b {
234 b'\0' => escaped.push_str(r"\0"),
235 b'\t' => escaped.push_str(r"\t"),
236 b'\n' => escaped.push_str(r"\n"),
237 b'\r' => escaped.push_str(r"\r"),
238 b'"' => escaped.push_str("\\\""),
239 b'\\' => escaped.push_str("\\\\"),
240 b'\x20' ... b'\x7E' => escaped.push(*b as char),
241 _ => escaped.push_str(&format!("\\x{:02X}", b)),
242 }
243 }
244 escaped.push('"');
245 Literal(escaped)
246 }
Alex Crichton76a5cc82017-05-23 07:01:44 -0700247
248 pub fn doccomment(s: &str) -> Literal {
249 Literal(s.to_string())
250 }
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700251
252 pub fn float(s: &str) -> Literal {
253 Literal(s.to_string())
254 }
255
256 pub fn integer(s: &str) -> Literal {
257 Literal(s.to_string())
258 }
Alex Crichton31316622017-05-26 12:54:47 -0700259
260 pub fn raw_string(s: &str, pounds: usize) -> Literal {
261 let mut ret = format!("r");
262 ret.extend((0..pounds).map(|_| "#"));
263 ret.push('"');
264 ret.push_str(s);
265 ret.push('"');
266 ret.extend((0..pounds).map(|_| "#"));
267 Literal(ret)
268 }
269
270 pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
271 let mut ret = format!("rb");
272 ret.extend((0..pounds).map(|_| "#"));
273 ret.push('"');
274 ret.push_str(s);
275 ret.push('"');
276 ret.extend((0..pounds).map(|_| "#"));
277 Literal(ret)
278 }
Alex Crichton852d53d2017-05-19 19:25:08 -0700279}
280
Alex Crichton44bffbc2017-05-19 17:51:59 -0700281impl fmt::Display for Literal {
282 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283 self.0.fmt(f)
284 }
285}
286
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700287macro_rules! ints {
Alex Crichton44bffbc2017-05-19 17:51:59 -0700288 ($($t:ty,)*) => {$(
289 impl From<$t> for Literal {
290 fn from(t: $t) -> Literal {
Alex Crichton852d53d2017-05-19 19:25:08 -0700291 Literal(format!(concat!("{}", stringify!($t)), t))
Alex Crichton44bffbc2017-05-19 17:51:59 -0700292 }
293 }
294 )*}
295}
296
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700297ints! {
Alex Crichton852d53d2017-05-19 19:25:08 -0700298 u8, u16, u32, u64, usize,
299 i8, i16, i32, i64, isize,
Alex Crichton9c2fb0a2017-05-26 08:49:31 -0700300}
301
302macro_rules! floats {
303 ($($t:ty,)*) => {$(
304 impl From<$t> for Literal {
305 fn from(t: $t) -> Literal {
306 assert!(!t.is_nan());
307 assert!(!t.is_infinite());
308 Literal(format!(concat!("{}", stringify!($t)), t))
309 }
310 }
311 )*}
312}
313
314floats! {
Alex Crichton852d53d2017-05-19 19:25:08 -0700315 f32, f64,
316}
317
Alex Crichton44bffbc2017-05-19 17:51:59 -0700318impl<'a> From<&'a str> for Literal {
319 fn from(t: &'a str) -> Literal {
320 let mut s = t.chars().flat_map(|c| c.escape_default()).collect::<String>();
321 s.push('"');
322 s.insert(0, '"');
323 Literal(s)
324 }
325}
326
327impl From<char> for Literal {
328 fn from(t: char) -> Literal {
329 Literal(format!("'{}'", t.escape_default()))
330 }
331}
332
333named!(token_stream -> TokenStream,
334 map!(token_trees, |s: Vec<TokenTree>| TokenStream { inner: s }));
335
336named!(token_trees -> Vec<TokenTree>, many0!(token_tree));
337
338named!(token_tree -> TokenTree,
339 map!(token_kind, |s: TokenKind| {
340 TokenTree {
341 span: ::Span(Span),
342 kind: s,
343 }
344 }));
345
346named!(token_kind -> TokenKind, alt!(
347 map!(delimited, |(d, s): (Delimiter, TokenStream)| {
348 TokenKind::Sequence(d, ::TokenStream(s))
349 })
350 |
Michael Layzellbad58012017-05-24 20:42:52 -0400351 map!(literal, |l| TokenKind::Literal(::Literal(l))) // must be before symbol
Alex Crichton44bffbc2017-05-19 17:51:59 -0700352 |
Michael Layzellbad58012017-05-24 20:42:52 -0400353 map!(symbol, |w| TokenKind::Word(::Symbol(w)))
Alex Crichton44bffbc2017-05-19 17:51:59 -0700354 |
355 map!(op, |(op, kind): (char, OpKind)| {
356 TokenKind::Op(op, kind)
357 })
358));
359
360named!(delimited -> (Delimiter, TokenStream), alt!(
361 delimited!(
362 punct!("("),
363 token_stream,
364 punct!(")")
365 ) => { |ts| (Delimiter::Parenthesis, ts) }
366 |
367 delimited!(
368 punct!("["),
369 token_stream,
370 punct!("]")
371 ) => { |ts| (Delimiter::Bracket, ts) }
372 |
373 delimited!(
374 punct!("{"),
375 token_stream,
376 punct!("}")
377 ) => { |ts| (Delimiter::Brace, ts) }
378));
379
380named!(symbol -> Symbol, alt!(
381 lifetime
382 |
383 map!(word, Symbol::from)
384));
385
386named!(lifetime -> Symbol, preceded!(
387 punct!("'"),
388 alt!(
389 // TODO: can we get rid of this allocation?
390 map!(word, |id| Symbol::from(&format!("'{}", id)[..]))
391 |
392 map!(keyword!("static"), |_| Symbol::from("'static"))
393 )
394));
395
396fn word(mut input: &str) -> IResult<&str, &str> {
397 input = skip_whitespace(input);
398
399 let mut chars = input.char_indices();
400 match chars.next() {
401 Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
402 _ => return IResult::Error,
403 }
404
405 for (i, ch) in chars {
406 if !UnicodeXID::is_xid_continue(ch) {
407 return IResult::Done(&input[i..], &input[..i])
408 }
409 }
410
411 IResult::Done("", input)
412}
413
414fn literal(input: &str) -> IResult<&str, Literal> {
415 let input_no_ws = skip_whitespace(input);
416
417 match literal_nocapture(input_no_ws) {
418 IResult::Done(a, ()) => {
419 let start = input.len() - input_no_ws.len();
420 let len = input_no_ws.len() - a.len();
421 let end = start + len;
Alex Crichton44bffbc2017-05-19 17:51:59 -0700422 IResult::Done(a, Literal(input[start..end].to_string()))
423 }
424 IResult::Error => IResult::Error,
425 }
426}
427
428named!(literal_nocapture -> (), alt!(
429 string
430 |
431 byte_string
432 |
433 byte
434 |
435 character
436 |
437 float
438 |
439 int
440 |
441 boolean
442 |
443 doc_comment
444));
445
446named!(string -> (), alt!(
447 quoted_string
448 |
449 preceded!(
450 punct!("r"),
451 raw_string
452 ) => { |_| () }
453));
454
455named!(quoted_string -> (), delimited!(
456 punct!("\""),
457 cooked_string,
458 tag!("\"")
459));
460
461fn cooked_string(input: &str) -> IResult<&str, ()> {
462 let mut chars = input.char_indices().peekable();
463 while let Some((byte_offset, ch)) = chars.next() {
464 match ch {
465 '"' => {
466 return IResult::Done(&input[byte_offset..], ());
467 }
468 '\r' => {
469 if let Some((_, '\n')) = chars.next() {
470 // ...
471 } else {
472 break;
473 }
474 }
475 '\\' => {
476 match chars.next() {
477 Some((_, 'x')) => {
478 if !backslash_x_char(&mut chars) {
479 break
480 }
481 }
482 Some((_, 'n')) |
483 Some((_, 'r')) |
484 Some((_, 't')) |
485 Some((_, '\\')) |
486 Some((_, '\'')) |
487 Some((_, '"')) |
488 Some((_, '0')) => {}
489 Some((_, 'u')) => {
490 if !backslash_u(&mut chars) {
491 break
492 }
493 }
494 Some((_, '\n')) | Some((_, '\r')) => {
495 while let Some(&(_, ch)) = chars.peek() {
496 if ch.is_whitespace() {
497 chars.next();
498 } else {
499 break;
500 }
501 }
502 }
503 _ => break,
504 }
505 }
506 _ch => {}
507 }
508 }
509 IResult::Error
510}
511
512named!(byte_string -> (), alt!(
513 delimited!(
514 punct!("b\""),
515 cooked_byte_string,
516 tag!("\"")
517 ) => { |_| () }
518 |
519 preceded!(
520 punct!("br"),
521 raw_string
522 ) => { |_| () }
523));
524
525fn cooked_byte_string(mut input: &str) -> IResult<&str, ()> {
526 let mut bytes = input.bytes().enumerate();
527 'outer: while let Some((offset, b)) = bytes.next() {
528 match b {
529 b'"' => {
530 return IResult::Done(&input[offset..], ());
531 }
532 b'\r' => {
533 if let Some((_, b'\n')) = bytes.next() {
534 // ...
535 } else {
536 break;
537 }
538 }
539 b'\\' => {
540 match bytes.next() {
541 Some((_, b'x')) => {
542 if !backslash_x_byte(&mut bytes) {
543 break
544 }
545 }
546 Some((_, b'n')) |
547 Some((_, b'r')) |
548 Some((_, b't')) |
549 Some((_, b'\\')) |
550 Some((_, b'0')) |
551 Some((_, b'\'')) |
552 Some((_, b'"')) => {}
553 Some((newline, b'\n')) |
554 Some((newline, b'\r')) => {
555 let rest = &input[newline + 1..];
556 for (offset, ch) in rest.char_indices() {
557 if !ch.is_whitespace() {
558 input = &rest[offset..];
559 bytes = input.bytes().enumerate();
560 continue 'outer;
561 }
562 }
563 break;
564 }
565 _ => break,
566 }
567 }
568 b if b < 0x80 => {}
569 _ => break,
570 }
571 }
572 IResult::Error
573}
574
575fn raw_string(input: &str) -> IResult<&str, ()> {
576 let mut chars = input.char_indices();
577 let mut n = 0;
578 while let Some((byte_offset, ch)) = chars.next() {
579 match ch {
580 '"' => {
581 n = byte_offset;
582 break;
583 }
584 '#' => {}
585 _ => return IResult::Error,
586 }
587 }
588 for (byte_offset, ch) in chars {
589 match ch {
590 '"' if input[byte_offset + 1..].starts_with(&input[..n]) => {
591 let rest = &input[byte_offset + 1 + n..];
592 return IResult::Done(rest, ())
593 }
594 '\r' => {}
595 _ => {}
596 }
597 }
598 IResult::Error
599}
600
601named!(byte -> (), do_parse!(
602 punct!("b") >>
603 tag!("'") >>
604 cooked_byte >>
605 tag!("'") >>
606 (())
607));
608
609fn cooked_byte(input: &str) -> IResult<&str, ()> {
610 let mut bytes = input.bytes().enumerate();
611 let ok = match bytes.next().map(|(_, b)| b) {
612 Some(b'\\') => {
613 match bytes.next().map(|(_, b)| b) {
614 Some(b'x') => backslash_x_byte(&mut bytes),
615 Some(b'n') |
616 Some(b'r') |
617 Some(b't') |
618 Some(b'\\') |
619 Some(b'0') |
620 Some(b'\'') |
621 Some(b'"') => true,
622 _ => false,
623 }
624 }
625 b => b.is_some(),
626 };
627 if ok {
628 match bytes.next() {
629 Some((offset, _)) => IResult::Done(&input[offset..], ()),
630 None => IResult::Done("", ()),
631 }
632 } else {
633 IResult::Error
634 }
635}
636
637named!(character -> (), do_parse!(
638 punct!("'") >>
639 cooked_char >>
640 tag!("'") >>
641 (())
642));
643
644fn cooked_char(input: &str) -> IResult<&str, ()> {
645 let mut chars = input.char_indices();
646 let ok = match chars.next().map(|(_, ch)| ch) {
647 Some('\\') => {
648 match chars.next().map(|(_, ch)| ch) {
649 Some('x') => backslash_x_char(&mut chars),
650 Some('u') => backslash_u(&mut chars),
651 Some('n') |
652 Some('r') |
653 Some('t') |
654 Some('\\') |
655 Some('0') |
656 Some('\'') |
657 Some('"') => true,
658 _ => false,
659 }
660 }
661 ch => ch.is_some(),
662 };
663 if ok {
664 IResult::Done(chars.as_str(), ())
665 } else {
666 IResult::Error
667 }
668}
669
670macro_rules! next_ch {
671 ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
672 match $chars.next() {
673 Some((_, ch)) => match ch {
674 $pat $(| $rest)* => ch,
675 _ => return false,
676 },
677 None => return false
678 }
679 };
680}
681
682fn backslash_x_char<I>(chars: &mut I) -> bool
683 where I: Iterator<Item = (usize, char)>
684{
685 next_ch!(chars @ '0'...'7');
686 next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
687 true
688}
689
690fn backslash_x_byte<I>(chars: &mut I) -> bool
691 where I: Iterator<Item = (usize, u8)>
692{
693 next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
694 next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
695 true
696}
697
698fn backslash_u<I>(chars: &mut I) -> bool
699 where I: Iterator<Item = (usize, char)>
700{
701 next_ch!(chars @ '{');
702 next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
703 let b = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
704 if b == '}' {
705 return true
706 }
707 let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
708 if c == '}' {
709 return true
710 }
711 let d = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
712 if d == '}' {
713 return true
714 }
715 let e = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
716 if e == '}' {
717 return true
718 }
719 let f = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
720 if f == '}' {
721 return true
722 }
723 next_ch!(chars @ '}');
724 true
725}
726
727named!(float -> (), do_parse!(
728 float_string >>
729 alt!(
730 tag!("f32") => { |_| () }
731 |
732 tag!("f64") => { |_| () }
733 |
734 epsilon!()
735 ) >>
736 (())
737));
738
739fn float_string(input: &str) -> IResult<&str, ()> {
740 let mut chars = input.chars().peekable();
741 match chars.next() {
742 Some(ch) if ch >= '0' && ch <= '9' => {}
743 _ => return IResult::Error,
744 }
745
746 let mut len = 1;
747 let mut has_dot = false;
748 let mut has_exp = false;
749 while let Some(&ch) = chars.peek() {
750 match ch {
751 '0'...'9' | '_' => {
752 chars.next();
753 len += 1;
754 }
755 '.' => {
756 if has_dot {
757 break;
758 }
759 chars.next();
760 if chars.peek()
761 .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
762 .unwrap_or(false) {
763 return IResult::Error;
764 }
765 len += 1;
766 has_dot = true;
767 }
768 'e' | 'E' => {
769 chars.next();
770 len += 1;
771 has_exp = true;
772 break;
773 }
774 _ => break,
775 }
776 }
777
778 let rest = &input[len..];
779 if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
780 return IResult::Error;
781 }
782
783 if has_exp {
784 let mut has_exp_value = false;
785 while let Some(&ch) = chars.peek() {
786 match ch {
787 '+' | '-' => {
788 if has_exp_value {
789 break;
790 }
791 chars.next();
792 len += 1;
793 }
794 '0'...'9' => {
795 chars.next();
796 len += 1;
797 has_exp_value = true;
798 }
799 '_' => {
800 chars.next();
801 len += 1;
802 }
803 _ => break,
804 }
805 }
806 if !has_exp_value {
807 return IResult::Error;
808 }
809 }
810
811 IResult::Done(&input[len..], ())
812}
813
814named!(int -> (), do_parse!(
815 digits >>
816 alt!(
817 tag!("isize") => { |_| () }
818 |
819 tag!("i8") => { |_| () }
820 |
821 tag!("i16") => { |_| () }
822 |
823 tag!("i32") => { |_| () }
824 |
825 tag!("i64") => { |_| () }
826 |
827 tag!("usize") => { |_| () }
828 |
829 tag!("u8") => { |_| () }
830 |
831 tag!("u16") => { |_| () }
832 |
833 tag!("u32") => { |_| () }
834 |
835 tag!("u64") => { |_| () }
836 |
837 epsilon!()
838 ) >>
839 (())
840));
841
842fn digits(mut input: &str) -> IResult<&str, ()> {
843 let base = if input.starts_with("0x") {
844 input = &input[2..];
845 16
846 } else if input.starts_with("0o") {
847 input = &input[2..];
848 8
849 } else if input.starts_with("0b") {
850 input = &input[2..];
851 2
852 } else {
853 10
854 };
855
856 let mut value = 0u64;
857 let mut len = 0;
858 let mut empty = true;
859 for b in input.bytes() {
860 let digit = match b {
861 b'0'...b'9' => (b - b'0') as u64,
862 b'a'...b'f' => 10 + (b - b'a') as u64,
863 b'A'...b'F' => 10 + (b - b'A') as u64,
864 b'_' => {
865 if empty && base == 10 {
866 return IResult::Error;
867 }
868 len += 1;
869 continue;
870 }
871 _ => break,
872 };
873 if digit >= base {
874 return IResult::Error;
875 }
876 value = match value.checked_mul(base) {
877 Some(value) => value,
878 None => return IResult::Error,
879 };
880 value = match value.checked_add(digit) {
881 Some(value) => value,
882 None => return IResult::Error,
883 };
884 len += 1;
885 empty = false;
886 }
887 if empty {
888 IResult::Error
889 } else {
890 IResult::Done(&input[len..], ())
891 }
892}
893
894named!(boolean -> (), alt!(
895 keyword!("true") => { |_| () }
896 |
897 keyword!("false") => { |_| () }
898));
899
900macro_rules! punct1 {
901 ($i:expr, $punct:expr) => {
902 punct1($i, $punct)
903 }
904}
905
906fn punct1<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, char> {
907 let input = skip_whitespace(input);
908 if input.starts_with(token) {
909 IResult::Done(&input[1..], token.chars().next().unwrap())
910 } else {
911 IResult::Error
912 }
913}
914
915named!(op -> (char, OpKind), alt!(
916 keyword!("_") => { |_| ('_', OpKind::Alone) }
917 |
918 punct1!("&&") => { |_| ('&', OpKind::Joint) }
919 |
920 punct1!("||") => { |_| ('|', OpKind::Joint) }
921 |
922 punct1!("->") => { |_| ('-', OpKind::Joint) }
923 |
924 punct1!("<-") => { |_| ('<', OpKind::Joint) }
925 |
926 punct1!("=>") => { |_| ('=', OpKind::Joint) }
927 |
928 punct1!("...") => { |_| ('.', OpKind::Joint) }
929 |
930 punct1!("..") => { |_| ('.', OpKind::Joint) }
931 |
932 punct!(".") => { |_| ('.', OpKind::Alone) }
933 |
Alex Crichton852d53d2017-05-19 19:25:08 -0700934 punct!(",") => { |_| (',', OpKind::Alone) }
935 |
Alex Crichton44bffbc2017-05-19 17:51:59 -0700936 bin_op_eq
937 |
938 bin_op
939 |
940 punct1!("<=") => { |_| ('<', OpKind::Joint) }
941 |
942 punct1!("==") => { |_| ('=', OpKind::Joint) }
943 |
944 punct1!("!=") => { |_| ('!', OpKind::Joint) }
945 |
946 punct1!(">=") => { |_| ('>', OpKind::Joint) }
947 |
948 punct1!("::") => { |_| (':', OpKind::Joint) }
949 |
950 punct!("=") => { |_| ('=', OpKind::Alone) }
951 |
952 punct!("<") => { |_| ('<', OpKind::Alone) }
953 |
954 punct!(">") => { |_| ('>', OpKind::Alone) }
955 |
956 punct!("!") => { |_| ('!', OpKind::Alone) }
957 |
958 punct!("~") => { |_| ('~', OpKind::Alone) }
959 |
960 punct!("@") => { |_| ('@', OpKind::Alone) }
961 |
962 punct!(",") => { |_| (',', OpKind::Alone) }
963 |
964 punct!(";") => { |_| (';', OpKind::Alone) }
965 |
966 punct!(":") => { |_| (':', OpKind::Alone) }
967 |
968 punct!("#") => { |_| ('#', OpKind::Alone) }
969 |
970 punct!("$") => { |_| ('$', OpKind::Alone) }
971 |
972 punct!("?") => { |_| ('?', OpKind::Alone) }
973));
974
975named!(bin_op -> (char, OpKind), alt!(
976 punct!("+") => { |_| ('+', OpKind::Alone) }
977 |
978 punct!("-") => { |_| ('-', OpKind::Alone) }
979 |
980 punct!("*") => { |_| ('*', OpKind::Alone) }
981 |
982 punct!("/") => { |_| ('/', OpKind::Alone) }
983 |
984 punct!("%") => { |_| ('%', OpKind::Alone) }
985 |
986 punct!("^") => { |_| ('^', OpKind::Alone) }
987 |
988 punct!("&") => { |_| ('&', OpKind::Alone) }
989 |
990 punct!("|") => { |_| ('|', OpKind::Alone) }
991 |
992 punct1!("<<") => { |_| ('<', OpKind::Joint) }
993 |
994 punct1!(">>") => { |_| ('>', OpKind::Joint) }
995));
996
997named!(bin_op_eq -> (char, OpKind), alt!(
998 punct1!("+=") => { |_| ('+', OpKind::Joint) }
999 |
1000 punct1!("-=") => { |_| ('-', OpKind::Joint) }
1001 |
1002 punct1!("*=") => { |_| ('*', OpKind::Joint) }
1003 |
1004 punct1!("/=") => { |_| ('/', OpKind::Joint) }
1005 |
1006 punct1!("%=") => { |_| ('%', OpKind::Joint) }
1007 |
1008 punct1!("^=") => { |_| ('^', OpKind::Joint) }
1009 |
1010 punct1!("&=") => { |_| ('&', OpKind::Joint) }
1011 |
1012 punct1!("|=") => { |_| ('|', OpKind::Joint) }
1013 |
1014 punct1!("<<=") => { |_| ('<', OpKind::Joint) }
1015 |
1016 punct1!(">>=") => { |_| ('>', OpKind::Joint) }
1017));
1018
1019named!(doc_comment -> (), alt!(
1020 do_parse!(
1021 punct!("//!") >>
1022 take_until!("\n") >>
1023 (())
1024 )
1025 |
1026 do_parse!(
1027 option!(whitespace) >>
1028 peek!(tag!("/*!")) >>
1029 block_comment >>
1030 (())
1031 )
1032 |
1033 do_parse!(
1034 punct!("///") >>
1035 not!(tag!("/")) >>
1036 take_until!("\n") >>
1037 (())
1038 )
1039 |
1040 do_parse!(
1041 option!(whitespace) >>
1042 peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
1043 block_comment >>
1044 (())
1045 )
1046));
1047
1048#[cfg(test)]
1049mod tests {
1050 use super::*;
1051
1052 #[test]
1053 fn symbols() {
1054 assert_eq!(&*Symbol::from("foo"), "foo");
1055 assert_eq!(&*Symbol::from("bar"), "bar");
1056 }
1057
1058 #[test]
1059 fn literals() {
1060 assert_eq!(Literal::from("foo").to_string(), "\"foo\"");
1061 assert_eq!(Literal::from("\"").to_string(), "\"\\\"\"");
1062 }
1063
1064 #[test]
1065 fn roundtrip() {
1066 fn roundtrip(p: &str) {
1067 println!("parse: {}", p);
1068 let s = p.parse::<TokenStream>().unwrap().to_string();
1069 println!("first: {}", s);
1070 let s2 = s.to_string().parse::<TokenStream>().unwrap().to_string();
1071 assert_eq!(s, s2);
1072 }
1073 roundtrip("a");
1074 roundtrip("<<");
1075 roundtrip("<<=");
1076 roundtrip("
1077 /// a
1078 wut
1079 ");
1080 roundtrip("
1081 1
1082 1.0
1083 1f32
1084 2f64
1085 1usize
1086 4isize
1087 4e10
1088 1_000
1089 1_0i32
1090 8u8
1091 9
1092 0
1093 ");
1094 }
1095}