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
use std::fmt;

use wast::parser::{Cursor, Parse, Parser, Peek, Result};

use crate::{AsAtoms, Atom};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Integer {
    pub(crate) sign: Option<Sign>,
    pub(crate) src:  String,
    pub(crate) val:  Option<String>,
    pub(crate) hex:  Option<bool>,
}

impl Integer {
    pub fn new(src: String) -> Self {
        Self {
            sign: None,
            src,
            val: None,
            hex: None,
        }
    }

    /// Returns the sign token for this integer.
    pub fn sign(&self) -> Option<Sign> {
        self.sign
    }

    /// Returns the original source text for this integer.
    pub fn src(&self) -> &str {
        &self.src
    }

    /// Returns the value string that can be parsed for this integer, as well as
    /// the base that it should be parsed in
    pub fn val(&self) -> (Option<&String>, Option<u32>) {
        let hex = if let Some(h) = self.hex {
            Some(if h { 16 } else { 10 })
        } else {
            None
        };

        (self.val.as_ref(), hex)
    }
}

impl AsAtoms for Integer {
    fn as_atoms(&self) -> Vec<Atom> {
        vec![Atom::new(self.src.to_owned())]
    }
}

impl fmt::Display for Integer {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.src)
    }
}

impl Parse<'_> for Integer {
    fn parse(parser: Parser<'_>) -> Result<Self> {
        parser.step(|cursor| match cursor.integer() {
            Some((s, cur)) => {
                let src = s.src().to_owned();
                let mut sign = None;
                let (val_ref, base) = s.val();
                let val = Some(val_ref.to_owned());
                let hex = Some(if base == 16 { true } else { false });

                if let Some(si) = s.sign() {
                    match si {
                        wast::lexer::SignToken::Plus => sign = Some(Sign::Pos),
                        wast::lexer::SignToken::Minus => sign = Some(Sign::Neg),
                    }
                }

                Ok((
                    Self {
                        sign,
                        src,
                        val,
                        hex,
                    },
                    cur,
                ))
            },
            None => Err(parser.error("could not parse integer")),
        })
    }
}

impl Peek for Integer {
    fn peek(cursor: Cursor<'_>) -> bool {
        cursor.integer().is_some()
    }

    fn display() -> &'static str {
        "integer"
    }
}

impl From<i32> for Integer {
    fn from(i: i32) -> Self {
        Self::new(i.to_string())
    }
}

#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash)]
pub enum Sign {
    Pos,
    Neg,
}