1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
use std::fmt; use std::hash::{Hash, Hasher}; use proc_macro2::{self, Literal, TokenNode, Term}; use {Span, TokenTree}; #[derive(Clone)] pub struct Lit { pub value: LitKind, pub span: Span, } #[derive(Clone)] pub enum LitKind { Bool(bool), Other(Literal), } impl Lit { pub fn into_token_tree(self) -> TokenTree { let kind = match self.value { LitKind::Bool(true) => TokenNode::Term(Term::intern("true")), LitKind::Bool(false) => TokenNode::Term(Term::intern("false")), LitKind::Other(l) => TokenNode::Literal(l), }; TokenTree(proc_macro2::TokenTree { span: self.span.0, kind: kind, }) } } impl fmt::Display for Lit { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.value, f) } } impl fmt::Debug for Lit { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.value, f) } } impl PartialEq for Lit { fn eq(&self, other: &Lit) -> bool { self.value == other.value } } impl Eq for Lit {} impl Hash for Lit { fn hash<H: Hasher>(&self, hasher: &mut H) { self.value.hash(hasher) } } impl fmt::Display for LitKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { LitKind::Bool(b) => b.fmt(f), LitKind::Other(ref l) => l.fmt(f), } } } impl fmt::Debug for LitKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { LitKind::Bool(b) => b.fmt(f), LitKind::Other(ref l) => fmt::Display::fmt(l, f), } } } impl PartialEq for LitKind { fn eq(&self, other: &LitKind) -> bool { match (self, other) { (&LitKind::Bool(b1), &LitKind::Bool(b2)) => b1 == b2, (&LitKind::Other(ref l1), &LitKind::Other(ref l2)) => { l1.to_string() == l2.to_string() } _ => false, } } } impl Eq for LitKind {} impl Hash for LitKind { fn hash<H: Hasher>(&self, hasher: &mut H) { match *self { LitKind::Bool(b) => (0u8, b).hash(hasher), LitKind::Other(ref l) => (1u8, l.to_string()).hash(hasher), } } } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use synom::{Synom, PResult, Cursor, parse_error}; impl Synom for Lit { fn parse(input: Cursor) -> PResult<Self> { match input.literal() { Some((rest, span, lit)) => { Ok((rest, Lit { span: Span(span), value: LitKind::Other(lit) })) } _ => match input.word() { Some((rest, span, sym)) => { let kind = if sym.as_str() == "true" { LitKind::Bool(true) } else if sym.as_str() == "false" { LitKind::Bool(false) } else { return parse_error(); }; Ok((rest, Lit { span: Span(span), value: kind })) } _ => parse_error(), } } } } } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Lit { fn to_tokens(&self, tokens: &mut Tokens) { self.clone().into_token_tree().to_tokens(tokens) } } }