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
use crate::{kw, Spanned};
use proc_macro2::Span;
use std::fmt;
use syn::{
    parse::{Lookahead1, Parse, ParseStream},
    LitBool, Result,
};

mod number;
pub use number::{LitDenominated, LitNumber, SubDenomination};

mod str;
pub use self::str::{HexStr, LitHexStr, LitStr, LitUnicodeStr, UnicodeStr};

/// A Solidity literal such as a string or integer or boolean.
#[derive(Clone)]
pub enum Lit {
    /// A boolean literal: `true` or `false`.
    Bool(LitBool),

    /// A hex string literal: `hex"1234"`.
    Hex(LitHexStr),

    /// An integer or fixed-point number literal: `1` or `1.0`.
    Number(LitNumber),

    /// A string literal.
    Str(LitStr),

    /// A unicode string literal.
    Unicode(LitUnicodeStr),
}

impl fmt::Debug for Lit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Lit::")?;
        match self {
            Self::Bool(lit) => lit.fmt(f),
            Self::Hex(lit) => lit.fmt(f),
            Self::Number(lit) => lit.fmt(f),
            Self::Str(lit) => lit.fmt(f),
            Self::Unicode(lit) => lit.fmt(f),
        }
    }
}

impl Parse for Lit {
    fn parse(input: ParseStream<'_>) -> Result<Self> {
        let lookahead = input.lookahead1();
        if lookahead.peek(syn::LitStr) {
            input.parse().map(Self::Str)
        } else if LitNumber::peek(&lookahead) {
            input.parse().map(Self::Number)
        } else if lookahead.peek(LitBool) {
            input.parse().map(Self::Bool)
        } else if lookahead.peek(kw::unicode) {
            input.parse().map(Self::Unicode)
        } else if lookahead.peek(kw::hex) {
            input.parse().map(Self::Hex)
        } else {
            Err(lookahead.error())
        }
    }
}

impl Spanned for Lit {
    fn span(&self) -> Span {
        match self {
            Self::Bool(lit) => lit.span(),
            Self::Hex(lit) => lit.span(),
            Self::Number(lit) => lit.span(),
            Self::Str(lit) => lit.span(),
            Self::Unicode(lit) => lit.span(),
        }
    }

    fn set_span(&mut self, span: Span) {
        match self {
            Self::Bool(lit) => lit.set_span(span),
            Self::Hex(lit) => lit.set_span(span),
            Self::Number(lit) => lit.set_span(span),
            Self::Str(lit) => lit.set_span(span),
            Self::Unicode(lit) => lit.set_span(span),
        }
    }
}

impl Lit {
    pub fn peek(lookahead: &Lookahead1<'_>) -> bool {
        lookahead.peek(syn::Lit) || lookahead.peek(kw::unicode) || lookahead.peek(kw::hex)
    }
}