<commit_before>//! Mouse and key events.

use std::io::{Error, ErrorKind};
use std::ascii::AsciiExt;
use std::str;

/// An event reported by the terminal.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Event {
    /// A key press.
    Key(Key),
    /// A mouse button press, release or wheel use at specific coordinates.
    Mouse(MouseEvent),
    /// An event that cannot currently be evaluated.
    Unsupported(Vec<u8>),
}

/// A mouse related event.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MouseEvent {
    /// A mouse button was pressed.
    ///
    /// The coordinates are one-based.
    Press(MouseButton, u16, u16),
    /// A mouse button was released.
    ///
    /// The coordinates are one-based.
    Release(u16, u16),
    /// A mouse button is held over the given coordinates.
    ///
    /// The coordinates are one-based.
    Hold(u16, u16),
}

/// A mouse button.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MouseButton {
    /// The left mouse button.
    Left,
    /// The right mouse button.
    Right,
    /// The middle mouse button.
    Middle,
    /// Mouse wheel is going up.
    ///
    /// This event is typically only used with Mouse::Press.
    WheelUp,
    /// Mouse wheel is going down.
    ///
    /// This event is typically only used with Mouse::Press.
    WheelDown,
}

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    ///
    /// Only function keys 1 through 12 are supported.
    F(u8),
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Null byte.
    Null,
    /// Esc key.
    Esc,

    #[doc(hidden)]
    __IsNotComplete,
}

/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
pub fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event, Error>
    where I: Iterator<Item = Result<u8, Error>>
{
    let error = Error::new(ErrorKind::Other, "Could not parse an event");
    match item {
        b'\x1B' => {
            // This is an escape character, leading a control sequence.
            Ok(match iter.next() {
                Some(Ok(b'O')) => {
                    match iter.next() {
                        // F1-F4
                        Some(Ok(val @ b'P'...b'S')) => Event::Key(Key::F(1 + val - b'P')),
                        _ => return Err(error),
                    }
                }
                Some(Ok(b'[')) => {
                    // This is a CSI sequence.
                    parse_csi(iter).ok_or(error)?
                }
                Some(Ok(c)) => {
                    let ch = parse_utf8_char(c, iter);
                    Event::Key(Key::Alt(try!(ch)))
                }
                Some(Err(_)) | None => return Err(error),
            })
        }
        b'\n' | b'\r' => Ok(Event::Key(Key::Char('\n'))),
        b'\t' => Ok(Event::Key(Key::Char('\t'))),
        b'\x7F' => Ok(Event::Key(Key::Backspace)),
        c @ b'\x01'...b'\x1A' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
        c @ b'\x1C'...b'\x1F' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char))),
        b'\0' => Ok(Event::Key(Key::Null)),
        c => {
            Ok({
                let ch = parse_utf8_char(c, iter);
                Event::Key(Key::Char(try!(ch)))
            })
        }
    }
}

/// Parses a CSI sequence, just after reading ^[
///
/// Returns None if an unrecognized sequence is found.
fn parse_csi<I>(iter: &mut I) -> Option<Event>
    where I: Iterator<Item = Result<u8, Error>>
{
    Some(match iter.next() {
        Some(Ok(b'D')) => Event::Key(Key::Left),
        Some(Ok(b'C')) => Event::Key(Key::Right),
        Some(Ok(b'A')) => Event::Key(Key::Up),
        Some(Ok(b'B')) => Event::Key(Key::Down),
        Some(Ok(b'H')) => Event::Key(Key::Home),
        Some(Ok(b'F')) => Event::Key(Key::End),
        Some(Ok(b'M')) => {
            // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
            let mut next = || iter.next().unwrap().unwrap();

            let cb = next() as i8 - 32;
            // (1, 1) are the coords for upper left.
            let cx = next().saturating_sub(32) as u16;
            let cy = next().saturating_sub(32) as u16;
            Event::Mouse(match cb & 0b11 {
                0 => {
                    if cb & 0x40 != 0 {
                        MouseEvent::Press(MouseButton::WheelUp, cx, cy)
                    } else {
                        MouseEvent::Press(MouseButton::Left, cx, cy)
                    }
                }
                1 => {
                    if cb & 0x40 != 0 {
                        MouseEvent::Press(MouseButton::WheelDown, cx, cy)
                    } else {
                        MouseEvent::Press(MouseButton::Middle, cx, cy)
                    }
                }
                2 => MouseEvent::Press(MouseButton::Right, cx, cy),
                3 => MouseEvent::Release(cx, cy),
                _ => return None,
            })
        }
        Some(Ok(b'<')) => {
            // xterm mouse encoding:
            // ESC [ < Cb ; Cx ; Cy ; (M or m)
            let mut buf = Vec::new();
            let mut c = iter.next().unwrap().unwrap();
            while match c {
                b'm' | b'M' => false,
                _ => true,
            } {
                buf.push(c);
                c = iter.next().unwrap().unwrap();
            }
            let str_buf = String::from_utf8(buf).unwrap();
            let nums = &mut str_buf.split(';');

            let cb = nums.next().unwrap().parse::<u16>().unwrap();
            let cx = nums.next().unwrap().parse::<u16>().unwrap();
            let cy = nums.next().unwrap().parse::<u16>().unwrap();

            let event = match cb {
                0...2 | 64...65 => {
                    let button = match cb {
                        0 => MouseButton::Left,
                        1 => MouseButton::Middle,
                        2 => MouseButton::Right,
                        64 => MouseButton::WheelUp,
                        65 => MouseButton::WheelDown,
                        _ => unreachable!(),
                    };
                    match c {
                        b'M' => MouseEvent::Press(button, cx, cy),
                        b'm' => MouseEvent::Release(cx, cy),
                        _ => return None,
                    }
                }
                32 => MouseEvent::Hold(cx, cy),
                _ => return None,
            };

            Event::Mouse(event)
        }
        Some(Ok(c @ b'0'...b'9')) => {
            // Numbered escape code.
            let mut buf = Vec::new();
            buf.push(c);
            let mut c = iter.next().unwrap().unwrap();
            // The final byte of a CSI sequence can be in the range 64-126, so
            // let's keep reading anything else.
            while c < 64 || c > 126 {
                buf.push(c);
                c = iter.next().unwrap().unwrap();
            }

            match c {
                // rxvt mouse encoding:
                // ESC [ Cb ; Cx ; Cy ; M
                b'M' => {
                    let str_buf = String::from_utf8(buf).unwrap();

                    let nums: Vec<u16> = str_buf
                        .split(';')
                        .map(|n| n.parse().unwrap())
                        .collect();

                    let cb = nums[0];
                    let cx = nums[1];
                    let cy = nums[2];

                    let event = match cb {
                        32 => MouseEvent::Press(MouseButton::Left, cx, cy),
                        33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
                        34 => MouseEvent::Press(MouseButton::Right, cx, cy),
                        35 => MouseEvent::Release(cx, cy),
                        64 => MouseEvent::Hold(cx, cy),
                        96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
                        _ => return None,
                    };

                    Event::Mouse(event)
                }
                // Special key code.
                b'~' => {
                    let str_buf = String::from_utf8(buf).unwrap();

                    // This CSI sequence can be a list of semicolon-separated
                    // numbers.
                    let nums: Vec<u8> = str_buf
                        .split(';')
                        .map(|n| n.parse().unwrap())
                        .collect();

                    if nums.is_empty() {
                        return None;
                    }

                    // TODO: handle multiple values for key modififiers (ex: values
                    // [3, 2] means Shift+Delete)
                    if nums.len() > 1 {
                        return None;
                    }

                    match nums[0] {
                        1 | 7 => Event::Key(Key::Home),
                        2 => Event::Key(Key::Insert),
                        3 => Event::Key(Key::Delete),
                        4 | 8 => Event::Key(Key::End),
                        5 => Event::Key(Key::PageUp),
                        6 => Event::Key(Key::PageDown),
                        v @ 11...15 => Event::Key(Key::F(v - 10)),
                        v @ 17...21 => Event::Key(Key::F(v - 11)),
                        v @ 23...24 => Event::Key(Key::F(v - 12)),
                        _ => return None,
                    }
                }
                _ => return None,
            }
        }
        _ => return None,
    })

}

/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
    where I: Iterator<Item = Result<u8, Error>>
{
    let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
    if c.is_ascii() {
        Ok(c as char)
    } else {
        let bytes = &mut Vec::new();
        bytes.push(c);

        loop {
            bytes.push(iter.next().unwrap().unwrap());
            if let Ok(st) = str::from_utf8(bytes) {
                return Ok(st.chars().next().unwrap());
            }
            if bytes.len() >= 4 {
                return error;
            }
        }
    }
}

#[cfg(test)]
#[test]
fn test_parse_utf8() {
    let st = "abcéŷ¤£€ù%323";
    let ref mut bytes = st.bytes().map(|x| Ok(x));
    let chars = st.chars();
    for c in chars {
        let b = bytes.next().unwrap().unwrap();
        assert!(c == parse_utf8_char(b, bytes).unwrap());
    }
}
<commit_msg>add support for xterm mouse release code (#97)<commit_after>//! Mouse and key events.

use std::io::{Error, ErrorKind};
use std::ascii::AsciiExt;
use std::str;

/// An event reported by the terminal.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Event {
    /// A key press.
    Key(Key),
    /// A mouse button press, release or wheel use at specific coordinates.
    Mouse(MouseEvent),
    /// An event that cannot currently be evaluated.
    Unsupported(Vec<u8>),
}

/// A mouse related event.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MouseEvent {
    /// A mouse button was pressed.
    ///
    /// The coordinates are one-based.
    Press(MouseButton, u16, u16),
    /// A mouse button was released.
    ///
    /// The coordinates are one-based.
    Release(u16, u16),
    /// A mouse button is held over the given coordinates.
    ///
    /// The coordinates are one-based.
    Hold(u16, u16),
}

/// A mouse button.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MouseButton {
    /// The left mouse button.
    Left,
    /// The right mouse button.
    Right,
    /// The middle mouse button.
    Middle,
    /// Mouse wheel is going up.
    ///
    /// This event is typically only used with Mouse::Press.
    WheelUp,
    /// Mouse wheel is going down.
    ///
    /// This event is typically only used with Mouse::Press.
    WheelDown,
}

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    ///
    /// Only function keys 1 through 12 are supported.
    F(u8),
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Null byte.
    Null,
    /// Esc key.
    Esc,

    #[doc(hidden)]
    __IsNotComplete,
}

/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
pub fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event, Error>
    where I: Iterator<Item = Result<u8, Error>>
{
    let error = Error::new(ErrorKind::Other, "Could not parse an event");
    match item {
        b'\x1B' => {
            // This is an escape character, leading a control sequence.
            Ok(match iter.next() {
                Some(Ok(b'O')) => {
                    match iter.next() {
                        // F1-F4
                        Some(Ok(val @ b'P'...b'S')) => Event::Key(Key::F(1 + val - b'P')),
                        _ => return Err(error),
                    }
                }
                Some(Ok(b'[')) => {
                    // This is a CSI sequence.
                    parse_csi(iter).ok_or(error)?
                }
                Some(Ok(c)) => {
                    let ch = parse_utf8_char(c, iter);
                    Event::Key(Key::Alt(try!(ch)))
                }
                Some(Err(_)) | None => return Err(error),
            })
        }
        b'\n' | b'\r' => Ok(Event::Key(Key::Char('\n'))),
        b'\t' => Ok(Event::Key(Key::Char('\t'))),
        b'\x7F' => Ok(Event::Key(Key::Backspace)),
        c @ b'\x01'...b'\x1A' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
        c @ b'\x1C'...b'\x1F' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char))),
        b'\0' => Ok(Event::Key(Key::Null)),
        c => {
            Ok({
                let ch = parse_utf8_char(c, iter);
                Event::Key(Key::Char(try!(ch)))
            })
        }
    }
}

/// Parses a CSI sequence, just after reading ^[
///
/// Returns None if an unrecognized sequence is found.
fn parse_csi<I>(iter: &mut I) -> Option<Event>
    where I: Iterator<Item = Result<u8, Error>>
{
    Some(match iter.next() {
        Some(Ok(b'D')) => Event::Key(Key::Left),
        Some(Ok(b'C')) => Event::Key(Key::Right),
        Some(Ok(b'A')) => Event::Key(Key::Up),
        Some(Ok(b'B')) => Event::Key(Key::Down),
        Some(Ok(b'H')) => Event::Key(Key::Home),
        Some(Ok(b'F')) => Event::Key(Key::End),
        Some(Ok(b'M')) => {
            // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
            let mut next = || iter.next().unwrap().unwrap();

            let cb = next() as i8 - 32;
            // (1, 1) are the coords for upper left.
            let cx = next().saturating_sub(32) as u16;
            let cy = next().saturating_sub(32) as u16;
            Event::Mouse(match cb & 0b11 {
                0 => {
                    if cb & 0x40 != 0 {
                        MouseEvent::Press(MouseButton::WheelUp, cx, cy)
                    } else {
                        MouseEvent::Press(MouseButton::Left, cx, cy)
                    }
                }
                1 => {
                    if cb & 0x40 != 0 {
                        MouseEvent::Press(MouseButton::WheelDown, cx, cy)
                    } else {
                        MouseEvent::Press(MouseButton::Middle, cx, cy)
                    }
                }
                2 => MouseEvent::Press(MouseButton::Right, cx, cy),
                3 => MouseEvent::Release(cx, cy),
                _ => return None,
            })
        }
        Some(Ok(b'<')) => {
            // xterm mouse encoding:
            // ESC [ < Cb ; Cx ; Cy (;) (M or m)
            let mut buf = Vec::new();
            let mut c = iter.next().unwrap().unwrap();
            while match c {
                b'm' | b'M' => false,
                _ => true,
            } {
                buf.push(c);
                c = iter.next().unwrap().unwrap();
            }
            let str_buf = String::from_utf8(buf).unwrap();
            let nums = &mut str_buf.split(';');

            let cb = nums.next().unwrap().parse::<u16>().unwrap();
            let cx = nums.next().unwrap().parse::<u16>().unwrap();
            let cy = nums.next().unwrap().parse::<u16>().unwrap();

            let event = match cb {
                0...2 | 64...65 => {
                    let button = match cb {
                        0 => MouseButton::Left,
                        1 => MouseButton::Middle,
                        2 => MouseButton::Right,
                        64 => MouseButton::WheelUp,
                        65 => MouseButton::WheelDown,
                        _ => unreachable!(),
                    };
                    match c {
                        b'M' => MouseEvent::Press(button, cx, cy),
                        b'm' => MouseEvent::Release(cx, cy),
                        _ => return None,
                    }
                }
                32 => MouseEvent::Hold(cx, cy),
                3 => MouseEvent::Release(cx, cy),
                _ => return None,
            };

            Event::Mouse(event)
        }
        Some(Ok(c @ b'0'...b'9')) => {
            // Numbered escape code.
            let mut buf = Vec::new();
            buf.push(c);
            let mut c = iter.next().unwrap().unwrap();
            // The final byte of a CSI sequence can be in the range 64-126, so
            // let's keep reading anything else.
            while c < 64 || c > 126 {
                buf.push(c);
                c = iter.next().unwrap().unwrap();
            }

            match c {
                // rxvt mouse encoding:
                // ESC [ Cb ; Cx ; Cy ; M
                b'M' => {
                    let str_buf = String::from_utf8(buf).unwrap();

                    let nums: Vec<u16> = str_buf
                        .split(';')
                        .map(|n| n.parse().unwrap())
                        .collect();

                    let cb = nums[0];
                    let cx = nums[1];
                    let cy = nums[2];

                    let event = match cb {
                        32 => MouseEvent::Press(MouseButton::Left, cx, cy),
                        33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
                        34 => MouseEvent::Press(MouseButton::Right, cx, cy),
                        35 => MouseEvent::Release(cx, cy),
                        64 => MouseEvent::Hold(cx, cy),
                        96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
                        _ => return None,
                    };

                    Event::Mouse(event)
                }
                // Special key code.
                b'~' => {
                    let str_buf = String::from_utf8(buf).unwrap();

                    // This CSI sequence can be a list of semicolon-separated
                    // numbers.
                    let nums: Vec<u8> = str_buf
                        .split(';')
                        .map(|n| n.parse().unwrap())
                        .collect();

                    if nums.is_empty() {
                        return None;
                    }

                    // TODO: handle multiple values for key modififiers (ex: values
                    // [3, 2] means Shift+Delete)
                    if nums.len() > 1 {
                        return None;
                    }

                    match nums[0] {
                        1 | 7 => Event::Key(Key::Home),
                        2 => Event::Key(Key::Insert),
                        3 => Event::Key(Key::Delete),
                        4 | 8 => Event::Key(Key::End),
                        5 => Event::Key(Key::PageUp),
                        6 => Event::Key(Key::PageDown),
                        v @ 11...15 => Event::Key(Key::F(v - 10)),
                        v @ 17...21 => Event::Key(Key::F(v - 11)),
                        v @ 23...24 => Event::Key(Key::F(v - 12)),
                        _ => return None,
                    }
                }
                _ => return None,
            }
        }
        _ => return None,
    })

}

/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
    where I: Iterator<Item = Result<u8, Error>>
{
    let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
    if c.is_ascii() {
        Ok(c as char)
    } else {
        let bytes = &mut Vec::new();
        bytes.push(c);

        loop {
            bytes.push(iter.next().unwrap().unwrap());
            if let Ok(st) = str::from_utf8(bytes) {
                return Ok(st.chars().next().unwrap());
            }
            if bytes.len() >= 4 {
                return error;
            }
        }
    }
}

#[cfg(test)]
#[test]
fn test_parse_utf8() {
    let st = "abcéŷ¤£€ù%323";
    let ref mut bytes = st.bytes().map(|x| Ok(x));
    let chars = st.chars();
    for c in chars {
        let b = bytes.next().unwrap().unwrap();
        assert!(c == parse_utf8_char(b, bytes).unwrap());
    }
}
<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};
use core::f64::consts::pi;

use funs::triganomic::{cos, sin};
use mat::{Mat3, Mat4};
use num::kinds::{Float, Number};
use num::conv::cast;
use quat::Quat;
use vec::Vec3;

/**
 * The base trait for anglular units
 */
pub trait Angle<T>: Add<self,self>
                  , Sub<self,self>
                  , Mul<T,self>
                  , Div<T,self>
                  // , Div<self,T>
                  , Modulo<T,self>
                  // , Modulo<self,T>
                  , Neg<self>
                  , Eq, Ord {
    static pure fn full_turn() -> self;
    static pure fn half_turn() -> self;
    static pure fn quadrant()  -> self;
    static pure fn sextant()   -> self;
    static pure fn octant()    -> self;
    static pure fn zero()      -> self;

    pure fn to_radians(&self) -> Radians<T>;
    pure fn to_degrees(&self) -> Degrees<T>;
    pure fn wrap(&self) -> self;
    pure fn opposite(&self) -> self;
}

pub enum Radians<T> = T;

// FIXME: not sure why I need the Eq and Ord trait bounds, but Rust complains if I don't include them
pub impl<T:Copy Float> Radians<T>: Angle<T> {
    #[inline(always)] static pure fn full_turn()    -> Radians<T> { Radians(Float::two_pi())    }
    #[inline(always)] static pure fn half_turn()    -> Radians<T> { Radians(Float::pi())        }
    #[inline(always)] static pure fn quadrant()     -> Radians<T> { Radians(Float::frac_pi_2()) }
    #[inline(always)] static pure fn sextant()      -> Radians<T> { Radians(Float::frac_pi_3()) }
    #[inline(always)] static pure fn octant()       -> Radians<T> { Radians(Float::frac_pi_4()) }
    #[inline(always)] static pure fn zero()         -> Radians<T> { Radians(Number::zero())     }

    #[inline(always)] pure fn to_radians(&self) -> Radians<T> { *self }
    #[inline(always)] pure fn to_degrees(&self) -> Degrees<T> { Degrees(**self * cast(180.0 / pi)) }

    #[inline(always)]
    pure fn wrap(&self) -> Radians<T> {
        let theta = (*self) % cast(2.0 * pi);

        // keep in the domain of 0 to 1 rad
        if theta >= Angle::zero() {
            theta
        } else {
            theta + Angle::full_turn()
        }
    }

    #[inline(always)]
    pure fn opposite(&self) -> Radians<T> {
        (self + Angle::half_turn()).wrap()     // TODO: test!
    }
}

pub impl<T:Copy Float> Radians<T>: Add<Radians<T>, Radians<T>> {
    #[inline(always)]
    pure fn add(rhs: &Radians<T>) -> Radians<T> {
        Radians(*self + **rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Sub<Radians<T>, Radians<T>> {
    #[inline(always)]
    pure fn sub(&self, rhs: &Radians<T>) -> Radians<T> {
        Radians(**self - **rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Mul<T, Radians<T>> {
    #[inline(always)]
    pure fn mul(&self, rhs: &T) -> Radians<T> {
        Radians(**self * *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Div<T, Radians<T>> {
    #[inline(always)]
    pure fn div(&self, rhs: &T) -> Radians<T> {
        Radians(**self / *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Modulo<T, Radians<T>> {
    #[inline(always)]
    pure fn modulo(&self, rhs: &T) -> Radians<T> {
        Radians(**self % *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Neg<Radians<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Radians<T> {
        Radians(-**self)
    }
}

pub impl<T:Copy Float> Radians<T>: Eq {
    #[inline(always)] pure fn eq(&self, other: &Radians<T>) -> bool { **self == **other }
    #[inline(always)] pure fn ne(&self, other: &Radians<T>) -> bool { **self != **other }
}

pub impl<T:Copy Float> Radians<T>: Ord {
    #[inline(always)] pure fn lt(&self, other: &Radians<T>) -> bool { **self <  **other }
    #[inline(always)] pure fn le(&self, other: &Radians<T>) -> bool { **self <= **other }
    #[inline(always)] pure fn ge(&self, other: &Radians<T>) -> bool { **self >= **other }
    #[inline(always)] pure fn gt(&self, other: &Radians<T>) -> bool { **self >  **other }
}

pub impl<T> Radians<T>: ToStr {
    pure fn to_str() -> ~str { fmt!("%? rad", *self) }
}

pub enum Degrees<T> = T;

// FIXME: not sure why I need the Eq and Ord trait bounds, but Rust complains if I don't include them
pub impl<T:Copy Float> Degrees<T>: Angle<T> {
    #[inline(always)] static pure fn full_turn()    -> Degrees<T> { Degrees(cast(360.0)) }
    #[inline(always)] static pure fn half_turn()    -> Degrees<T> { Degrees(cast(180.0)) }
    #[inline(always)] static pure fn quadrant()     -> Degrees<T> { Degrees(cast(90.0))  }
    #[inline(always)] static pure fn sextant()      -> Degrees<T> { Degrees(cast(60.0))  }
    #[inline(always)] static pure fn octant()       -> Degrees<T> { Degrees(cast(45.0))  }
    #[inline(always)] static pure fn zero()         -> Degrees<T> { Degrees(cast(0.0))   }

    #[inline(always)] pure fn to_radians(&self) -> Radians<T> { Radians(**self * cast(pi / 180.0)) }
    #[inline(always)] pure fn to_degrees(&self) -> Degrees<T> { *self }

    #[inline(always)]
    pure fn wrap(&self) -> Degrees<T> {
        let theta = (*self) % cast(360);

        // keep in the domain of 0 to 360 degrees
        if theta >= Angle::zero() {
            theta
        } else {
            theta + Angle::full_turn()
        }
    }

    #[inline(always)]
    pure fn opposite(&self) -> Degrees<T> {
        (self + Angle::half_turn()).wrap()      // TODO: test!
    }
}

pub impl<T:Copy Float> Degrees<T>: Add<Degrees<T>, Degrees<T>> {
    #[inline(always)]
    pure fn add(rhs: &Degrees<T>) -> Degrees<T> {
        Degrees(*self + **rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Sub<Degrees<T>, Degrees<T>> {
    #[inline(always)]
    pure fn sub(&self, rhs: &Degrees<T>) -> Degrees<T> {
        Degrees(**self - **rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Mul<T, Degrees<T>> {
    #[inline(always)]
    pure fn mul(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self * *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Div<T, Degrees<T>> {
    #[inline(always)]
    pure fn div(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self / *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Modulo<T, Degrees<T>> {
    #[inline(always)]
    pure fn modulo(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self % *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Neg<Degrees<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Degrees<T> {
        Degrees(-**self)
    }
}

pub impl<T:Copy Float> Degrees<T>: Eq {
    #[inline(always)] pure fn eq(&self, other: &Degrees<T>) -> bool { **self == **other }
    #[inline(always)] pure fn ne(&self, other: &Degrees<T>) -> bool { **self != **other }
}

pub impl<T:Copy Float> Degrees<T>: Ord {
    #[inline(always)] pure fn lt(&self, other: &Degrees<T>) -> bool { **self <  **other }
    #[inline(always)] pure fn le(&self, other: &Degrees<T>) -> bool { **self <= **other }
    #[inline(always)] pure fn ge(&self, other: &Degrees<T>) -> bool { **self >= **other }
    #[inline(always)] pure fn gt(&self, other: &Degrees<T>) -> bool { **self >  **other }
}

pub impl<T> Degrees<T>: ToStr {
    pure fn to_str() -> ~str { fmt!("%?\xB0", *self) }
}

/**
 * An angular rotation around an arbitary axis
 */
pub struct Rotation<T> {
    theta: Radians<T>,
    axis: Vec3<T>,
}

pub impl<T:Copy Float> Rotation<T> {
    #[inline(always)]
    static pure fn new(theta: Radians<T>, axis: Vec3<T>) -> Rotation<T> {
        Rotation { theta: move theta, axis: move axis }
    }

    #[inline(always)]
    pure fn to_mat3() -> Mat3<T> {
        let c:  T = cos(&self.theta);
        let s:  T = sin(&self.theta);
        let _0: T = cast(0);
        let _1: T = cast(1);
        // let _0: T = Number::from(0);    // FIXME: causes ICE
        // let _1: T = Number::from(0);    // FIXME: causes ICE
        let t:  T = _1 - c;

        let x = self.axis.x;
        let y = self.axis.y;
        let z = self.axis.z;

        Mat3::new(t * x * x + c,       t * x * y + s * z,   t * x * z - s * y,
                  t * x * y - s * z,   t * y * y + c,       t * y * z + s * x,
                  t * x * z - s - y,   t * y * z - s * x,   t * z * z + c)
    }

    #[inline(always)]
    pure fn to_mat4() -> Mat4<T> {
        self.to_mat3().to_mat4()
    }

    #[inline(always)]
    pure fn to_quat() -> Quat<T> {
        let half = self.theta / Number::from(2);
        Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half)))
    }
}

pub struct Euler<T> {
    x: Radians<T>,   // pitch
    y: Radians<T>,   // yaw
    z: Radians<T>,   // roll
}<commit_msg>Add todo, remove fixme<commit_after>use core::cmp::{Eq, Ord};
use core::f64::consts::pi;

use funs::triganomic::{cos, sin};
use mat::{Mat3, Mat4};
use num::kinds::{Float, Number};
use num::conv::cast;
use quat::Quat;
use vec::Vec3;

/**
 * The base trait for anglular units
 */
pub trait Angle<T>: Add<self,self>,
                    Sub<self,self>
                    Mul<T,self>,
                    Div<T,self>,
                    // Div<self,T>,     // TODO: not sure how to implement this, or if it is even possible...
                    Modulo<T,self>,
                    // Modulo<self,T>,  // TODO: not sure how to implement this, or if it is even possible...
                    Neg<self>,
                    Eq, Ord {
    static pure fn full_turn() -> self;
    static pure fn half_turn() -> self;
    static pure fn quadrant()  -> self;
    static pure fn sextant()   -> self;
    static pure fn octant()    -> self;
    static pure fn zero()      -> self;

    pure fn to_radians(&self) -> Radians<T>;
    pure fn to_degrees(&self) -> Degrees<T>;
    pure fn wrap(&self) -> self;
    pure fn opposite(&self) -> self;
}

pub enum Radians<T> = T;

pub impl<T:Copy Float> Radians<T>: Angle<T> {
    #[inline(always)] static pure fn full_turn()    -> Radians<T> { Radians(Float::two_pi())    }
    #[inline(always)] static pure fn half_turn()    -> Radians<T> { Radians(Float::pi())        }
    #[inline(always)] static pure fn quadrant()     -> Radians<T> { Radians(Float::frac_pi_2()) }
    #[inline(always)] static pure fn sextant()      -> Radians<T> { Radians(Float::frac_pi_3()) }
    #[inline(always)] static pure fn octant()       -> Radians<T> { Radians(Float::frac_pi_4()) }
    #[inline(always)] static pure fn zero()         -> Radians<T> { Radians(Number::zero())     }

    #[inline(always)] pure fn to_radians(&self) -> Radians<T> { *self }
    #[inline(always)] pure fn to_degrees(&self) -> Degrees<T> { Degrees(**self * cast(180.0 / pi)) }

    #[inline(always)]
    pure fn wrap(&self) -> Radians<T> {
        let theta = (*self) % cast(2.0 * pi);

        // keep in the domain of 0 to 1 rad
        if theta >= Angle::zero() {
            theta
        } else {
            theta + Angle::full_turn()
        }
    }

    #[inline(always)]
    pure fn opposite(&self) -> Radians<T> {
        (self + Angle::half_turn()).wrap()     // TODO: test!
    }
}

pub impl<T:Copy Float> Radians<T>: Add<Radians<T>, Radians<T>> {
    #[inline(always)]
    pure fn add(rhs: &Radians<T>) -> Radians<T> {
        Radians(*self + **rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Sub<Radians<T>, Radians<T>> {
    #[inline(always)]
    pure fn sub(&self, rhs: &Radians<T>) -> Radians<T> {
        Radians(**self - **rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Mul<T, Radians<T>> {
    #[inline(always)]
    pure fn mul(&self, rhs: &T) -> Radians<T> {
        Radians(**self * *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Div<T, Radians<T>> {
    #[inline(always)]
    pure fn div(&self, rhs: &T) -> Radians<T> {
        Radians(**self / *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Modulo<T, Radians<T>> {
    #[inline(always)]
    pure fn modulo(&self, rhs: &T) -> Radians<T> {
        Radians(**self % *rhs)
    }
}

pub impl<T:Copy Float> Radians<T>: Neg<Radians<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Radians<T> {
        Radians(-**self)
    }
}

pub impl<T:Copy Float> Radians<T>: Eq {
    #[inline(always)] pure fn eq(&self, other: &Radians<T>) -> bool { **self == **other }
    #[inline(always)] pure fn ne(&self, other: &Radians<T>) -> bool { **self != **other }
}

pub impl<T:Copy Float> Radians<T>: Ord {
    #[inline(always)] pure fn lt(&self, other: &Radians<T>) -> bool { **self <  **other }
    #[inline(always)] pure fn le(&self, other: &Radians<T>) -> bool { **self <= **other }
    #[inline(always)] pure fn ge(&self, other: &Radians<T>) -> bool { **self >= **other }
    #[inline(always)] pure fn gt(&self, other: &Radians<T>) -> bool { **self >  **other }
}

pub impl<T> Radians<T>: ToStr {
    pure fn to_str() -> ~str { fmt!("%? rad", *self) }
}

pub enum Degrees<T> = T;

// FIXME: not sure why I need the Eq and Ord trait bounds, but Rust complains if I don't include them
pub impl<T:Copy Float> Degrees<T>: Angle<T> {
    #[inline(always)] static pure fn full_turn()    -> Degrees<T> { Degrees(cast(360.0)) }
    #[inline(always)] static pure fn half_turn()    -> Degrees<T> { Degrees(cast(180.0)) }
    #[inline(always)] static pure fn quadrant()     -> Degrees<T> { Degrees(cast(90.0))  }
    #[inline(always)] static pure fn sextant()      -> Degrees<T> { Degrees(cast(60.0))  }
    #[inline(always)] static pure fn octant()       -> Degrees<T> { Degrees(cast(45.0))  }
    #[inline(always)] static pure fn zero()         -> Degrees<T> { Degrees(cast(0.0))   }

    #[inline(always)] pure fn to_radians(&self) -> Radians<T> { Radians(**self * cast(pi / 180.0)) }
    #[inline(always)] pure fn to_degrees(&self) -> Degrees<T> { *self }

    #[inline(always)]
    pure fn wrap(&self) -> Degrees<T> {
        let theta = (*self) % cast(360);

        // keep in the domain of 0 to 360 degrees
        if theta >= Angle::zero() {
            theta
        } else {
            theta + Angle::full_turn()
        }
    }

    #[inline(always)]
    pure fn opposite(&self) -> Degrees<T> {
        (self + Angle::half_turn()).wrap()      // TODO: test!
    }
}

pub impl<T:Copy Float> Degrees<T>: Add<Degrees<T>, Degrees<T>> {
    #[inline(always)]
    pure fn add(rhs: &Degrees<T>) -> Degrees<T> {
        Degrees(*self + **rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Sub<Degrees<T>, Degrees<T>> {
    #[inline(always)]
    pure fn sub(&self, rhs: &Degrees<T>) -> Degrees<T> {
        Degrees(**self - **rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Mul<T, Degrees<T>> {
    #[inline(always)]
    pure fn mul(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self * *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Div<T, Degrees<T>> {
    #[inline(always)]
    pure fn div(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self / *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Modulo<T, Degrees<T>> {
    #[inline(always)]
    pure fn modulo(&self, rhs: &T) -> Degrees<T> {
        Degrees(**self % *rhs)
    }
}

pub impl<T:Copy Float> Degrees<T>: Neg<Degrees<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Degrees<T> {
        Degrees(-**self)
    }
}

pub impl<T:Copy Float> Degrees<T>: Eq {
    #[inline(always)] pure fn eq(&self, other: &Degrees<T>) -> bool { **self == **other }
    #[inline(always)] pure fn ne(&self, other: &Degrees<T>) -> bool { **self != **other }
}

pub impl<T:Copy Float> Degrees<T>: Ord {
    #[inline(always)] pure fn lt(&self, other: &Degrees<T>) -> bool { **self <  **other }
    #[inline(always)] pure fn le(&self, other: &Degrees<T>) -> bool { **self <= **other }
    #[inline(always)] pure fn ge(&self, other: &Degrees<T>) -> bool { **self >= **other }
    #[inline(always)] pure fn gt(&self, other: &Degrees<T>) -> bool { **self >  **other }
}

pub impl<T> Degrees<T>: ToStr {
    pure fn to_str() -> ~str { fmt!("%?\xB0", *self) }
}

/**
 * An angular rotation around an arbitary axis
 */
pub struct Rotation<T> {
    theta: Radians<T>,
    axis: Vec3<T>,
}

pub impl<T:Copy Float> Rotation<T> {
    #[inline(always)]
    static pure fn new(theta: Radians<T>, axis: Vec3<T>) -> Rotation<T> {
        Rotation { theta: move theta, axis: move axis }
    }

    #[inline(always)]
    pure fn to_mat3() -> Mat3<T> {
        let c:  T = cos(&self.theta);
        let s:  T = sin(&self.theta);
        let _0: T = cast(0);
        let _1: T = cast(1);
        // let _0: T = Number::from(0);    // FIXME: causes ICE
        // let _1: T = Number::from(0);    // FIXME: causes ICE
        let t:  T = _1 - c;

        let x = self.axis.x;
        let y = self.axis.y;
        let z = self.axis.z;

        Mat3::new(t * x * x + c,       t * x * y + s * z,   t * x * z - s * y,
                  t * x * y - s * z,   t * y * y + c,       t * y * z + s * x,
                  t * x * z - s - y,   t * y * z - s * x,   t * z * z + c)
    }

    #[inline(always)]
    pure fn to_mat4() -> Mat4<T> {
        self.to_mat3().to_mat4()
    }

    #[inline(always)]
    pure fn to_quat() -> Quat<T> {
        let half = self.theta / Number::from(2);
        Quat::from_sv(cos(&half), self.axis.mul_t(sin(&half)))
    }
}

pub struct Euler<T> {
    x: Radians<T>,   // pitch
    y: Radians<T>,   // yaw
    z: Radians<T>,   // roll
}<|endoftext|>


<commit_before>#![allow(dead_code)]

use regex::Regex;

#[repr(u32)]
#[derive(Clone)]
pub enum SubToken {
    Plus     = 0,
    Minus    = 1,
    Multiply = 2,
    Divide   = 3,

    Number   = 4,

    LParen   = 5,
    RParen   = 6,

    End      = 7,
}

#[derive(Clone)]
pub struct Token {
    kind: SubToken,
    value: Option<f64>
}

impl Token {
    pub fn new(kind: SubToken, value: Option<f64>) -> Self {
        Token{kind: kind, value: value}
    }
    pub fn set_kind(&mut self, kind: SubToken) {
        self.kind = kind;
    }
    pub fn set_value(&mut self, value: Option<f64>) {
        self.value = value;
    }
    pub fn get_kind(&self) -> SubToken {
        self.kind.clone()
    }
    pub fn get_value(&self) -> Option<f64> {
        self.value.clone()
    }
}

pub struct Lexer {
    input: String,
    return_previous_token: bool,
    previous_token: Option<Token>
}

impl Lexer {
    pub fn new(input: String) -> Self {
        Lexer{input: input, return_previous_token: false, previous_token: None}
    }
    pub fn get_next_token(&mut self) -> Token {
        if self.return_previous_token {
            self.return_previous_token = false;
            return self.previous_token.clone().unwrap();
        }
        let strip_input = strip_white_space(self.input.clone());
        lazy_static! {
            static ref PLUS_RE: Regex = Regex::new(r"\A\+").unwrap();
            static ref MINUS_RE: Regex = Regex::new(r"\A-").unwrap();
            static ref MULT_RE: Regex = Regex::new(r"\*").unwrap();
            static ref DIV_RE: Regex = Regex::new(r"\A/").unwrap();
            static ref NUM_RE: Regex = Regex::new(r"\A\d+(\.\d+)?").unwrap();
            static ref LPAREN_RE: Regex = Regex::new(r"\A\(").unwrap();
            static ref RPAREN_RE: Regex = Regex::new(r"\A\)").unwrap();
        }
        let token: Token;
        if PLUS_RE.is_match(&strip_input[..]) {
            PLUS_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::Plus, None);
        } else if MINUS_RE.is_match(&strip_input[..]) {
            MINUS_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::Minus, None);
        } else if MULT_RE.is_match(&strip_input[..]) {
            MULT_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::Multiply, None);
        } else if DIV_RE.is_match(&strip_input[..]) {
            DIV_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::Divide, None);
        } else if NUM_RE.is_match(&strip_input[..]) {
            use std::str::FromStr;
            let value: Option<f64> = f64::from_str(NUM_RE.captures(&strip_input[..]).unwrap().at(0).unwrap()).ok();
            NUM_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::Number, value);
        } else if LPAREN_RE.is_match(&strip_input[..]) {
            LPAREN_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::LParen, None);
        } else if RPAREN_RE.is_match(&strip_input[..]) {
            RPAREN_RE.replace(&strip_input[..], "");
            token = Token::new(SubToken::RParen, None);
        } else if strip_input.is_empty() {
            token = Token::new(SubToken::End, None);
        } else {
            let mut error: String = String::from("Unknown token: ");
            error.push_str(&strip_input[..]);
            panic!(error);
        }
        self.previous_token = Some(token.clone());
        token
    }
    pub fn revert(&mut self) {
        self.return_previous_token = true;
    }
}

fn strip_white_space(input: String) -> String {
    input.split_whitespace().collect::<Vec<&str>>().join("")
}
<commit_msg>Fixed input not updating<commit_after>#![allow(dead_code)]

use regex::Regex;

#[repr(u32)]
#[derive(Debug, Clone)]
pub enum SubToken {
    Plus     = 0,
    Minus    = 1,
    Multiply = 2,
    Divide   = 3,

    Number   = 4,

    LParen   = 5,
    RParen   = 6,

    End      = 7,
}

#[derive(Debug, Clone)]
pub struct Token {
    kind: SubToken,
    value: Option<f64>
}

impl Token {
    pub fn new(kind: SubToken, value: Option<f64>) -> Self {
        Token{kind: kind, value: value}
    }
    pub fn set_kind(&mut self, kind: SubToken) {
        self.kind = kind;
    }
    pub fn set_value(&mut self, value: Option<f64>) {
        self.value = value;
    }
    pub fn get_kind(&self) -> SubToken {
        self.kind.clone()
    }
    pub fn get_value(&self) -> Option<f64> {
        self.value.clone()
    }
}

#[derive(Debug)]
pub struct Lexer {
    input: String,
    return_previous_token: bool,
    previous_token: Option<Token>
}

impl Lexer {
    pub fn new(input: String) -> Self {
        Lexer{input: input, return_previous_token: false, previous_token: None}
    }
    pub fn get_next_token(&mut self) -> Token {
        if self.return_previous_token {
            self.return_previous_token = false;
            return self.previous_token.clone().unwrap();
        }
        let mut strip_input = strip_white_space(self.input.clone());
        lazy_static! {
            static ref PLUS_RE: Regex = Regex::new(r"\A\+").unwrap();
            static ref MINUS_RE: Regex = Regex::new(r"\A-").unwrap();
            static ref MULT_RE: Regex = Regex::new(r"\A\*").unwrap();
            static ref DIV_RE: Regex = Regex::new(r"\A/").unwrap();
            static ref NUM_RE: Regex = Regex::new(r"\A\d+(\.\d+)?").unwrap();
            static ref LPAREN_RE: Regex = Regex::new(r"\A\(").unwrap();
            static ref RPAREN_RE: Regex = Regex::new(r"\A\)").unwrap();
        }
        let token: Token;
        let temp = &(strip_input.clone())[..];
        if PLUS_RE.is_match(temp) {
            strip_input = PLUS_RE.replace(temp, "");
            token = Token::new(SubToken::Plus, None);
        } else if MINUS_RE.is_match(temp) {
            strip_input = MINUS_RE.replace(temp, "");
            token = Token::new(SubToken::Minus, None);
        } else if MULT_RE.is_match(temp) {
            strip_input = MULT_RE.replace(temp, "");
            token = Token::new(SubToken::Multiply, None);
        } else if DIV_RE.is_match(temp) {
            strip_input = DIV_RE.replace(temp, "");
            token = Token::new(SubToken::Divide, None);
        } else if NUM_RE.is_match(temp) {
            use std::str::FromStr;
            let value: Option<f64> = f64::from_str(NUM_RE.captures(temp).unwrap().at(0).unwrap()).ok();
            strip_input = NUM_RE.replace(temp, "");
            token = Token::new(SubToken::Number, value);
        } else if LPAREN_RE.is_match(temp) {
            strip_input = LPAREN_RE.replace(temp, "");
            token = Token::new(SubToken::LParen, None);
        } else if RPAREN_RE.is_match(temp) {
            strip_input = RPAREN_RE.replace(temp, "");
            token = Token::new(SubToken::RParen, None);
        } else if strip_input.is_empty() {
            token = Token::new(SubToken::End, None);
        } else {
            let mut error: String = String::from("Unknown token: ");
            error.push_str(temp);
            panic!(error);
        }
        self.input = strip_input;
        self.previous_token = Some(token.clone());
        token
    }
    pub fn revert(&mut self) {
        self.return_previous_token = true;
    }
}

fn strip_white_space(input: String) -> String {
    input.split_whitespace().collect::<Vec<&str>>().join("")
}
<|endoftext|>


<commit_before>use std::collections::LinkedList;
use collections::borrow::Borrow;

use token::Token;

use std::cell::Cell;
use std::rc::Rc;
use regex::Regex;
use context::Context;
use token::Posn;

pub trait ESCharExt {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
}

impl ESCharExt for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }
}

struct LineOrientedReader<I> {
    chars: I,
    curr_char: Option<char>,
    next_char: Option<char>,
    curr_posn: Posn
}

impl<I> LineOrientedReader<I> where I: Iterator<Item=char> {
    pub fn new(mut chars: I) -> LineOrientedReader<I> {
        let curr_char = chars.next();
        let next_char = if curr_char.is_some() { chars.next() } else { None };
        LineOrientedReader {
            chars: chars,
            curr_char: curr_char,
            next_char: next_char,
            curr_posn: Posn {
                offset: 0,
                line: 0,
                column: 0
            }
        }
    }

    pub fn curr_char(&mut self) -> Option<char> { self.curr_char }
    pub fn curr_posn(&mut self) -> Posn { self.curr_posn }
    pub fn next_char(&mut self) -> Option<char> { self.next_char }

    pub fn bump(&mut self) {
        let curr_char = self.next_char;
        let next_char = if curr_char.is_some() { self.chars.next() } else { None };

        self.curr_char = curr_char;
        self.next_char = next_char;

        if (curr_char == Some('\r') && next_char != Some('\n')) ||
           curr_char == Some('\n') ||
           curr_char == Some('\u{2028}') ||
           curr_char == Some('\u{2029}') {
            self.curr_posn.line += 1;
            self.curr_posn.column = 0;
        } else {
            self.curr_posn.column += 1;
        }

        self.curr_posn.offset += 1;
    }
}

struct TokenBuffer {
    tokens: LinkedList<Token>
}

impl TokenBuffer {
    fn new() -> TokenBuffer {
        TokenBuffer {
            tokens: LinkedList::new()
        }
    }

    fn is_empty(&mut self) -> bool {
        self.tokens.len() == 0
    }

    fn push_token(&mut self, token: Token) {
        assert!(self.tokens.len() == 0);
        self.tokens.push_back(token);
    }

    fn read_token(&mut self) -> Token {
        assert!(self.tokens.len() > 0);
        self.tokens.pop_front().unwrap()
    }

    fn peek_token(&mut self) -> &Token {
        assert!(self.tokens.len() > 0);
        self.tokens.front().unwrap()
    }

    fn unread_token(&mut self, token: Token) {
        assert!(self.tokens.len() >= 0);
        assert!(self.tokens.len() < 3);
        self.tokens.push_front(token);
    }
}

pub struct Lexer<I> {
    reader: LineOrientedReader<I>,
    cx: Rc<Cell<Context>>,
    lookahead: TokenBuffer
}

impl<I> Lexer<I> where I: Iterator<Item=char> {
    // constructor

    pub fn new(chars: I, cx: Rc<Cell<Context>>) -> Lexer<I> {
        Lexer {
            reader: LineOrientedReader::new(chars),
            cx: cx,
            lookahead: TokenBuffer::new()
        }
    }

    // public methods

    pub fn is_eof(&mut self) -> bool {
        match *self.peek_token() {
            Token::EOF => true,
            _ => false
        }
    }

    pub fn peek_token(&mut self) -> &Token {
        if self.lookahead.is_empty() {
            let token = self.read_next_token();
            self.lookahead.push_token(token);
        }
        self.lookahead.peek_token()
    }

    pub fn read_token(&mut self) -> Token {
        if self.lookahead.is_empty() {
            self.read_next_token()
        } else {
            self.lookahead.read_token()
        }
    }

    pub fn unread_token(&mut self, token: Token) {
        self.lookahead.unread_token(token);
    }

    // private methods

    fn skip_line_comment(&mut self) {
    }

    fn skip_block_comment(&mut self) {
    }

    fn div_or_regexp(&mut self) -> Token {
        if self.cx.borrow().get().operator {
            unimplemented!()
        } else {
            unimplemented!()
        }
    }

    fn read_next_token(&mut self) -> Token {
        self.skip_whitespace();
        loop {
            match self.reader.curr_char() {
                None => return Token::EOF,
                Some(ch) => {
                    if ch == '/' {
                        match self.reader.next_char() {
                            Some('/') => self.skip_line_comment(),
                            Some('*') => self.skip_block_comment(),
                            _ => return self.div_or_regexp()
                        }
                    }
                    unimplemented!()
                }
            }
        }
    }

    fn is_whitespace(&mut self) -> bool {
        match self.reader.curr_char() {
            Some(ch) => ch.is_es_whitespace(),
            None => false
        }
    }

    fn eat(&mut self) -> Option<char> {
        let ch = self.reader.curr_char();
        self.reader.bump();
        ch
    }

    fn skip_whitespace(&mut self) {
        while self.is_whitespace() {
            self.reader.bump();
        }
    }
}

impl<I> Iterator for Lexer<I> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.skip_whitespace();
        self.eat()
            .map(|ch| {
                match ch {
                    '1' => Token::DecimalInt(String::from_str("1")),
                    '+' => Token::Plus,
                    _ => Token::Error(ch)
                }
            })
    }
}
<commit_msg>starting to guess randomly now, still no src/lexer.rs:2:5: 2:29 error: unresolved import `std::collections::Borrow`. There is no `Borrow` in `std::collections` src/lexer.rs:2 use std::collections::Borrow;                    ^~~~~~~~~~~~~~~~~~~~~~~~<commit_after>use std::collections::LinkedList;
use std::collections::Borrow;

use token::Token;

use std::cell::Cell;
use std::rc::Rc;
use regex::Regex;
use context::Context;
use token::Posn;

pub trait ESCharExt {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
}

impl ESCharExt for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }
}

struct LineOrientedReader<I> {
    chars: I,
    curr_char: Option<char>,
    next_char: Option<char>,
    curr_posn: Posn
}

impl<I> LineOrientedReader<I> where I: Iterator<Item=char> {
    pub fn new(mut chars: I) -> LineOrientedReader<I> {
        let curr_char = chars.next();
        let next_char = if curr_char.is_some() { chars.next() } else { None };
        LineOrientedReader {
            chars: chars,
            curr_char: curr_char,
            next_char: next_char,
            curr_posn: Posn {
                offset: 0,
                line: 0,
                column: 0
            }
        }
    }

    pub fn curr_char(&mut self) -> Option<char> { self.curr_char }
    pub fn curr_posn(&mut self) -> Posn { self.curr_posn }
    pub fn next_char(&mut self) -> Option<char> { self.next_char }

    pub fn bump(&mut self) {
        let curr_char = self.next_char;
        let next_char = if curr_char.is_some() { self.chars.next() } else { None };

        self.curr_char = curr_char;
        self.next_char = next_char;

        if (curr_char == Some('\r') && next_char != Some('\n')) ||
           curr_char == Some('\n') ||
           curr_char == Some('\u{2028}') ||
           curr_char == Some('\u{2029}') {
            self.curr_posn.line += 1;
            self.curr_posn.column = 0;
        } else {
            self.curr_posn.column += 1;
        }

        self.curr_posn.offset += 1;
    }
}

struct TokenBuffer {
    tokens: LinkedList<Token>
}

impl TokenBuffer {
    fn new() -> TokenBuffer {
        TokenBuffer {
            tokens: LinkedList::new()
        }
    }

    fn is_empty(&mut self) -> bool {
        self.tokens.len() == 0
    }

    fn push_token(&mut self, token: Token) {
        assert!(self.tokens.len() == 0);
        self.tokens.push_back(token);
    }

    fn read_token(&mut self) -> Token {
        assert!(self.tokens.len() > 0);
        self.tokens.pop_front().unwrap()
    }

    fn peek_token(&mut self) -> &Token {
        assert!(self.tokens.len() > 0);
        self.tokens.front().unwrap()
    }

    fn unread_token(&mut self, token: Token) {
        assert!(self.tokens.len() >= 0);
        assert!(self.tokens.len() < 3);
        self.tokens.push_front(token);
    }
}

pub struct Lexer<I> {
    reader: LineOrientedReader<I>,
    cx: Rc<Cell<Context>>,
    lookahead: TokenBuffer
}

impl<I> Lexer<I> where I: Iterator<Item=char> {
    // constructor

    pub fn new(chars: I, cx: Rc<Cell<Context>>) -> Lexer<I> {
        Lexer {
            reader: LineOrientedReader::new(chars),
            cx: cx,
            lookahead: TokenBuffer::new()
        }
    }

    // public methods

    pub fn is_eof(&mut self) -> bool {
        match *self.peek_token() {
            Token::EOF => true,
            _ => false
        }
    }

    pub fn peek_token(&mut self) -> &Token {
        if self.lookahead.is_empty() {
            let token = self.read_next_token();
            self.lookahead.push_token(token);
        }
        self.lookahead.peek_token()
    }

    pub fn read_token(&mut self) -> Token {
        if self.lookahead.is_empty() {
            self.read_next_token()
        } else {
            self.lookahead.read_token()
        }
    }

    pub fn unread_token(&mut self, token: Token) {
        self.lookahead.unread_token(token);
    }

    // private methods

    fn skip_line_comment(&mut self) {
    }

    fn skip_block_comment(&mut self) {
    }

    fn div_or_regexp(&mut self) -> Token {
        if self.cx.borrow().get().operator {
            unimplemented!()
        } else {
            unimplemented!()
        }
    }

    fn read_next_token(&mut self) -> Token {
        self.skip_whitespace();
        loop {
            match self.reader.curr_char() {
                None => return Token::EOF,
                Some(ch) => {
                    if ch == '/' {
                        match self.reader.next_char() {
                            Some('/') => self.skip_line_comment(),
                            Some('*') => self.skip_block_comment(),
                            _ => return self.div_or_regexp()
                        }
                    }
                    unimplemented!()
                }
            }
        }
    }

    fn is_whitespace(&mut self) -> bool {
        match self.reader.curr_char() {
            Some(ch) => ch.is_es_whitespace(),
            None => false
        }
    }

    fn eat(&mut self) -> Option<char> {
        let ch = self.reader.curr_char();
        self.reader.bump();
        ch
    }

    fn skip_whitespace(&mut self) {
        while self.is_whitespace() {
            self.reader.bump();
        }
    }
}

impl<I> Iterator for Lexer<I> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.skip_whitespace();
        self.eat()
            .map(|ch| {
                match ch {
                    '1' => Token::DecimalInt(String::from_str("1")),
                    '+' => Token::Plus,
                    _ => Token::Error(ch)
                }
            })
    }
}
<|endoftext|>


<commit_before>// TODO: remove below
#![allow(dead_code)]

//let leftBlockDelim: String = "{%".to_string();
//let rightBlockDelim: String = "%}".to_string();
const LEFT_VARIABLE_DELIM: &'static str  = "{{";
const RIGHT_VARIABLE_DELIM: &'static str  = "}}";

// List of token types to emit to the parser.
// Different from the state enum despite some identical members
#[derive(PartialEq, Debug)]
pub enum TokenType {
  Text, // HTML text etc
  Space,
  VariableStart, // {{
  VariableEnd, // }}
  Variable, // variable name, tera keywords
  Number, // number in variable blocks
  Operator, // + - * /
  Error, // errors uncountered while lexing, such as 1.2.3 number
}

// List of different states the scanner can be in
#[derive(Debug)]
enum State {
  Text,
  VariableStart,
  VariableEnd,
  InsideBlock,
  Variable,
  Operator, // an operator in a block, such as * in {{ price * 100 }}
  Number, // a number in a block, such as 100 in {{ price * 100 }}
}

#[derive(PartialEq, Debug)]
pub struct Token {
  kind: TokenType,
  value: String,
}

impl Token {
  pub fn new(kind: TokenType, value: &str) -> Token {
    Token {
      kind: kind,
      value: value.to_string()
    }
  }
}

#[derive(Debug)]
pub struct Scanner {
  name: String,
  input: String,
  chars: Vec<(usize, char)>, // (bytes index, char)
  index: usize, // where we are in the chars vec
  state: State,
}

impl Scanner {
  pub fn new(input: &str) -> Scanner {
    Scanner {
      name: "test".to_string(),
      input: input.to_string(),
      chars: input.char_indices().collect(),
      index: 0,
      state: State::Text,
    }
  }

  // We know we have {{ with self.index being on the first
  fn lex_left_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::InsideBlock;

    Some(Token::new(TokenType::VariableStart, "{{"))
  }

  // TODO: merge with the one above?
  fn lex_right_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::Text;

    Some(Token::new(TokenType::VariableEnd, "}}"))
  }

  // TODO: see if we can simplify below
  fn lex_text(&mut self) -> Option<Token> {
    // Gets all chars until we reach {{ (only that for now)
    let start_position = self.chars[self.index].0;
    let mut next_index = self.chars[self.index].0;

    loop {
      if self.input[next_index..].starts_with(LEFT_VARIABLE_DELIM) {
        self.state = State::VariableStart;

        // If we have a delim right at the beginning
        if next_index == 0 {
          return self.lex_left_variable_delimiter();
        }
        break;
      }
      // TODO: add leftBlockDelim as the variable one

      // got to EOF
      if self.index == self.chars.len() - 1 {
        next_index = self.input.len();
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Text,
      &self.input[start_position..next_index]
    ))
  }

  // We know we have a space, we need to figure out how many
  fn lex_space(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;

    loop {
      if !self.chars[self.index].1.is_whitespace() {
        break;
      }

      self.index += 1;
    }

    Some(Token::new(
      TokenType::Space,
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_number(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;
    let mut seen_dot = false;
    let mut error = "";

    loop {
      let current = self.chars[self.index].1;
      // TODO: parametize '}' ?
      if current.is_whitespace() || current == '}' {
        break;
      }
      if current == '.' {
        if seen_dot {
          error = "A number has 2 dots";
        } else {
          seen_dot = true;
        }
      }
      if !current.is_numeric() && current != '.' {
        error = "A number has unallowed chars";
      }
      self.index += 1;
    }

    if error.len() > 0 {
      return Some(Token::new(
        TokenType::Error,
        error
      ));
    }
    Some(Token::new(
      TokenType::Number,
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_variable(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;

    loop {
      let current = self.chars[self.index].1;
      if current == '.' || current.is_whitespace() {
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Variable,
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_operator(&mut self) -> Option<Token> {
    self.index += 1;
    self.state = State::InsideBlock;

    Some(Token::new(
      TokenType::Operator,
      &self.input[self.chars[self.index - 1].0..self.chars[self.index].0]
    ))
  }

  // Works for both {{ }}
  fn lex_inside_variable_block(&mut self) -> Option<Token> {
    match self.chars[self.index].1 {
      x if x.is_whitespace() => return self.lex_space(),
      x if x.is_alphabetic() || x == '_' => return self.lex_variable(),
      '}' => return self.lex_right_variable_delimiter(),
      x if x.is_numeric() => return self.lex_number(),
      '*' | '+' | '-' | '/' | '.' => return self.lex_operator(),
      _ => None,
    }

  }
}

impl Iterator for Scanner {
  type Item = Token;

  fn next(&mut self) -> Option<Token> {
    // Empty template
    // TODO: maybe put it in lex_text if we return an Option?
    if self.input.len() == 0 {
      return None;
    }

    // Got to the end
    if self.index >= self.chars.len() - 1 {
      return None;
    }

    match self.state {
      State::Text => self.lex_text(),
      State::VariableStart => self.lex_left_variable_delimiter(),
      State::InsideBlock => self.lex_inside_variable_block(),
      _ => None,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[derive(Debug)]
  struct LexerTest {
    name: String,
    input: String,
    expected: Vec<Token>
  }

  impl LexerTest {
    pub fn new(name: &str, input: &str, expected: Vec<Token>) -> LexerTest {
      LexerTest {
        name: name.to_string(),
        input: input.to_string(),
        expected: expected
      }
    }
  }

  fn text_token(value: &str) -> Token {
    Token::new(TokenType::Text, value)
  }

  fn variable_token(value: &str) -> Token {
    Token::new(TokenType::Variable, value)
  }

  fn variable_start_token() -> Token {
    Token::new(TokenType::VariableStart, "{{")
  }

  fn variable_end_token() -> Token {
    Token::new(TokenType::VariableEnd, "}}")
  }

  fn space_token() -> Token {
    Token::new(TokenType::Space, " ")
  }

  fn number_token(value: &str) -> Token {
    Token::new(TokenType::Number, value)
  }

  fn operator_token(value: &str) -> Token {
    Token::new(TokenType::Operator, value)
  }

  fn error_token() -> Token {
    Token::new(TokenType::Error, "")
  }

  fn check_if_correct(expected: &Vec<Token>, obtained: &Vec<Token>) -> bool {
    if expected.len() != obtained.len() {
      return false;
    }

    for i in 0..expected.len() {
      if expected[i].kind != obtained[i].kind {
        return false;
      }

      // Do not check error values as i'll probably change them often
      if expected[i].kind == TokenType::Error {
        continue;
      }

      if expected[i].value != obtained[i].value {
        return false;
      }
    }
    return true;
  }

  #[test]
  fn test_lexer() {
    let tests: Vec<LexerTest> = vec![
      LexerTest::new("empty", "", vec![]),
      LexerTest::new("only text", "Hello 世界", vec![text_token("Hello 世界")]),
      LexerTest::new("variable and text", "{{ greeting }} 世界", vec![
        variable_start_token(),
        space_token(),
        variable_token("greeting"),
        space_token(),
        variable_end_token(),
        text_token(" 世界"),
      ]),
      LexerTest::new("numbers", "{{1 3.14}}", vec![
        variable_start_token(),
        number_token("1"),
        space_token(),
        number_token("3.14"),
        variable_end_token(),
      ]),
      LexerTest::new("invalid numbers", "{{1up 3.14.15}}", vec![
        variable_start_token(),
        error_token(),
        space_token(),
        error_token(),
        variable_end_token(),
      ]),
      LexerTest::new("operators", "{{+ - * / .}}", vec![
        variable_start_token(),
        operator_token("+"),
        space_token(),
        operator_token("-"),
        space_token(),
        operator_token("*"),
        space_token(),
        operator_token("/"),
        space_token(),
        operator_token("."),
        variable_end_token(),
      ])
    ];

    for test in tests {
      let tokens: Vec<Token> = Scanner::new(&test.input).collect();
      if tokens.len() != test.expected.len() {
        println!("Test {} failed: different number of tokens.", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }

      if check_if_correct(&test.expected, &tokens) {
        assert!(true);
      } else {
        println!("Test {} failed: different tokens", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }
    }
  }
}
<commit_msg>Separate int/float tokens<commit_after>// TODO: remove below
#![allow(dead_code)]

//let leftBlockDelim: String = "{%".to_string();
//let rightBlockDelim: String = "%}".to_string();
const LEFT_VARIABLE_DELIM: &'static str  = "{{";
const RIGHT_VARIABLE_DELIM: &'static str  = "}}";

// List of token types to emit to the parser.
// Different from the state enum despite some identical members
#[derive(PartialEq, Debug)]
pub enum TokenType {
  Text, // HTML text etc
  Space,
  VariableStart, // {{
  VariableEnd, // }}
  Variable, // variable name, tera keywords
  Int,
  Float,
  Operator, // + - * / .
  Error, // errors uncountered while lexing, such as 1.2.3 number
}

// List of different states the scanner can be in
#[derive(Debug)]
enum State {
  Text,
  VariableStart,
  VariableEnd,
  InsideBlock,
  Variable,
  Operator, // an operator in a block, such as * in blocks
  Number, // a number in a block, such as 100 in {{ price * 100 }}
}

#[derive(PartialEq, Debug)]
pub struct Token {
  kind: TokenType,
  value: String,
}

impl Token {
  pub fn new(kind: TokenType, value: &str) -> Token {
    Token {
      kind: kind,
      value: value.to_string()
    }
  }
}

#[derive(Debug)]
pub struct Scanner {
  name: String,
  input: String,
  chars: Vec<(usize, char)>, // (bytes index, char)
  index: usize, // where we are in the chars vec
  state: State,
}

impl Scanner {
  pub fn new(input: &str) -> Scanner {
    Scanner {
      name: "test".to_string(),
      input: input.to_string(),
      chars: input.char_indices().collect(),
      index: 0,
      state: State::Text,
    }
  }

  // We know we have {{ with self.index being on the first
  fn lex_left_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::InsideBlock;

    Some(Token::new(TokenType::VariableStart, "{{"))
  }

  // TODO: merge with the one above?
  fn lex_right_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::Text;

    Some(Token::new(TokenType::VariableEnd, "}}"))
  }

  // TODO: see if we can simplify below
  fn lex_text(&mut self) -> Option<Token> {
    // Gets all chars until we reach {{ (only that for now)
    let start_position = self.chars[self.index].0;
    let mut next_index = self.chars[self.index].0;

    loop {
      if self.input[next_index..].starts_with(LEFT_VARIABLE_DELIM) {
        self.state = State::VariableStart;

        // If we have a delim right at the beginning
        if next_index == 0 {
          return self.lex_left_variable_delimiter();
        }
        break;
      }
      // TODO: add leftBlockDelim as the variable one

      // got to EOF
      if self.index == self.chars.len() - 1 {
        next_index = self.input.len();
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Text,
      &self.input[start_position..next_index]
    ))
  }

  // We know we have a space, we need to figure out how many
  fn lex_space(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;

    loop {
      if !self.chars[self.index].1.is_whitespace() {
        break;
      }

      self.index += 1;
    }

    Some(Token::new(
      TokenType::Space,
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_number(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;
    let mut seen_dot = false;
    let mut error = "";

    loop {
      let current = self.chars[self.index].1;
      // TODO: parametize '}' ?
      if current.is_whitespace() || current == '}' {
        break;
      }
      if current == '.' {
        if seen_dot {
          error = "A number has 2 dots";
        } else {
          seen_dot = true;
        }
      }
      if !current.is_numeric() && current != '.' {
        error = "A number has unallowed chars";
      }
      self.index += 1;
    }

    if error.len() > 0 {
      return Some(Token::new(
        TokenType::Error,
        error
      ));
    }

    Some(Token::new(
      if seen_dot { TokenType::Float } else { TokenType::Int },
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_variable(&mut self) -> Option<Token> {
    let start_position = self.chars[self.index].0;

    loop {
      let current = self.chars[self.index].1;
      if current == '.' || current.is_whitespace() {
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Variable,
      &self.input[start_position..self.chars[self.index].0]
    ))
  }

  fn lex_operator(&mut self) -> Option<Token> {
    self.index += 1;
    self.state = State::InsideBlock;

    Some(Token::new(
      TokenType::Operator,
      &self.input[self.chars[self.index - 1].0..self.chars[self.index].0]
    ))
  }

  // Works for both {{ }}
  fn lex_inside_variable_block(&mut self) -> Option<Token> {
    match self.chars[self.index].1 {
      x if x.is_whitespace() => return self.lex_space(),
      x if x.is_alphabetic() || x == '_' => return self.lex_variable(),
      '}' => return self.lex_right_variable_delimiter(),
      x if x.is_numeric() => return self.lex_number(),
      '*' | '+' | '-' | '/' | '.' => return self.lex_operator(),
      _ => None,
    }

  }
}

impl Iterator for Scanner {
  type Item = Token;

  fn next(&mut self) -> Option<Token> {
    // Empty template
    // TODO: maybe put it in lex_text if we return an Option?
    if self.input.len() == 0 {
      return None;
    }

    // Got to the end
    if self.index >= self.chars.len() - 1 {
      return None;
    }

    match self.state {
      State::Text => self.lex_text(),
      State::VariableStart => self.lex_left_variable_delimiter(),
      State::InsideBlock => self.lex_inside_variable_block(),
      _ => None,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[derive(Debug)]
  struct LexerTest {
    name: String,
    input: String,
    expected: Vec<Token>
  }

  impl LexerTest {
    pub fn new(name: &str, input: &str, expected: Vec<Token>) -> LexerTest {
      LexerTest {
        name: name.to_string(),
        input: input.to_string(),
        expected: expected
      }
    }
  }

  fn text_token(value: &str) -> Token {
    Token::new(TokenType::Text, value)
  }

  fn variable_token(value: &str) -> Token {
    Token::new(TokenType::Variable, value)
  }

  fn variable_start_token() -> Token {
    Token::new(TokenType::VariableStart, "{{")
  }

  fn variable_end_token() -> Token {
    Token::new(TokenType::VariableEnd, "}}")
  }

  fn space_token() -> Token {
    Token::new(TokenType::Space, " ")
  }

  fn int_token(value: &str) -> Token {
    Token::new(TokenType::Int, value)
  }

  fn float_token(value: &str) -> Token {
    Token::new(TokenType::Float, value)
  }

  fn operator_token(value: &str) -> Token {
    Token::new(TokenType::Operator, value)
  }

  fn error_token() -> Token {
    Token::new(TokenType::Error, "")
  }

  fn check_if_correct(expected: &Vec<Token>, obtained: &Vec<Token>) -> bool {
    if expected.len() != obtained.len() {
      return false;
    }

    for i in 0..expected.len() {
      if expected[i].kind != obtained[i].kind {
        return false;
      }

      // Do not check error values as i'll probably change them often
      if expected[i].kind == TokenType::Error {
        continue;
      }

      if expected[i].value != obtained[i].value {
        return false;
      }
    }
    return true;
  }

  #[test]
  fn test_lexer() {
    let tests: Vec<LexerTest> = vec![
      LexerTest::new("empty", "", vec![]),
      LexerTest::new("only text", "Hello 世界", vec![text_token("Hello 世界")]),
      LexerTest::new("variable and text", "{{ greeting }} 世界", vec![
        variable_start_token(),
        space_token(),
        variable_token("greeting"),
        space_token(),
        variable_end_token(),
        text_token(" 世界"),
      ]),
      LexerTest::new("numbers", "{{1 3.14}}", vec![
        variable_start_token(),
        int_token("1"),
        space_token(),
        float_token("3.14"),
        variable_end_token(),
      ]),
      LexerTest::new("invalid numbers", "{{1up 3.14.15}}", vec![
        variable_start_token(),
        error_token(),
        space_token(),
        error_token(),
        variable_end_token(),
      ]),
      LexerTest::new("operators", "{{+ - * / .}}", vec![
        variable_start_token(),
        operator_token("+"),
        space_token(),
        operator_token("-"),
        space_token(),
        operator_token("*"),
        space_token(),
        operator_token("/"),
        space_token(),
        operator_token("."),
        variable_end_token(),
      ])
    ];

    for test in tests {
      let tokens: Vec<Token> = Scanner::new(&test.input).collect();
      if tokens.len() != test.expected.len() {
        println!("Test {} failed: different number of tokens.", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }

      if check_if_correct(&test.expected, &tokens) {
        assert!(true);
      } else {
        println!("Test {} failed: different tokens", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }
    }
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate std;

#[derive(Clone)]
pub struct Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    pub value: T,
    index: usize,
}

// TODO implement std::num::Float
// impl <T: std::num::Float, CT: super::context::Context<T>> std::num::Float for Float<T, CT> {
// }

impl <T, CT> std::num::ToPrimitive for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn to_i64(&self) -> Option<i64> { self.value.to_i64() }

    fn to_u64(&self) -> Option<u64> { self.value.to_u64() }
    //TODO implement the rest optional function.
}

// TODO implement std::num::NumCast, actually, can I? Should we allow?
// impl <T: std::num::Float, CT: super::context::Context<T>> std::num::NumCast for Float<T, CT> {
// }

impl <T, CT> std::ops::Neg for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn neg(self) -> Float<T, CT> {
        // TODO rust doesn't have T::one() yet.
        let one: T = std::num::Float::one();
        Float{value: -self.value,
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(one.neg(), self.index)}
    }
}

// TODO adjoints of 1 can be optimized out, i.e., not multiplying. Should we?
impl <T, CT> std::ops::Add<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn add(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value + rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[std::num::Float::one(), std::num::Float::one()],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Sub<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn sub(self, rhs: Float<T, CT>) -> Float<T, CT> {
        let one: T = std::num::Float::one();
        Float{value: self.value - rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[one, -one],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Mul<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn mul(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value * rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[rhs.value, self.value],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Div<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn div(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value / rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[rhs.value.recip(), -((self.value * self.value).recip())],
                  &[self.index, rhs.index])}
    }
}

// TODO 1. Does it make sense to support % operator between two Floats ?
//      2. If so, should we record rhs even though the multiplier is 0?
impl <T, CT> std::ops::Rem<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn rem(self, rhs: Float<T, CT>) -> Float<T, CT> {
        // TODO add this kind of assert everywhere.
        // assert!(( self . context as * const super::context::Context < T >
        //         ) == (
        //         rhs . context as * const super::context::Context < T > ));
        Float{value: self.value % rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[std::num::Float::one(), std::num::Float::zero()],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::cmp::PartialEq for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn eq(&self, other: &Float<T, CT>) -> bool { self.value == other.value }
}

impl <T, CT> std::cmp::PartialOrd for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn partial_cmp(&self, other: &Float<T, CT>) -> Option<std::cmp::Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl <T, CT> std::marker::Copy for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
}

// Crate private functions

pub trait FloatCratePrivate<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn new(value: T, index: usize) ->Self;
    fn float_get_index(&self) -> usize;
}

impl <T, CT> FloatCratePrivate<T, CT> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn new(value: T, index: usize) -> Self {
        Float{value: value, index: index}
    }

    fn float_get_index(&self) -> usize {
        self.index
    }
}
<commit_msg>Partial std::num::Float implementation.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate std;

pub struct Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    pub value: T,
    index: usize,
}

// TODO implement std::num::Float
impl <T, CT> std::num::Float for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn nan() -> Self {
        unimplemented!();
    }

    fn infinity() -> Self {
        unimplemented!();
    }

    fn neg_infinity() -> Self {
        unimplemented!();
    }

    fn zero() -> Self {
        unimplemented!();
    }

    fn neg_zero() -> Self {
        unimplemented!();
    }

    fn one() -> Self {
        unimplemented!();
    }

    fn mantissa_digits(unused_self: Option<Self>) -> usize {
        unimplemented!();
    }

    fn digits(unused_self: Option<Self>) -> usize {
        unimplemented!();
    }

    fn epsilon() -> Self {
        unimplemented!();
    }

    fn min_exp(unused_self: Option<Self>) -> isize {
        unimplemented!();
    }

    fn max_exp(unused_self: Option<Self>) -> isize {
        unimplemented!();
    }

    fn min_10_exp(unused_self: Option<Self>) -> isize {
        unimplemented!();
    }

    fn max_10_exp(unused_self: Option<Self>) -> isize {
        unimplemented!();
    }

    fn min_value() -> Self {
        unimplemented!();
    }

    fn min_pos_value(unused_self: Option<Self>) -> Self {
        unimplemented!();
    }

    fn max_value() -> Self {
        unimplemented!();
    }

    fn is_nan(self) -> bool {
        self.value.is_nan()
    }

    fn is_infinite(self) -> bool {
        self.value.is_infinite()
    }

    fn is_finite(self) -> bool {
        self.value.is_finite()
    }

    fn is_normal(self) -> bool {
        self.value.is_normal()
    }

    fn classify(self) -> std::num::FpCategory {
        self.value.classify()
    }

    fn integer_decode(self) -> (u64, i16, i8) {
        self.value.integer_decode()
    }

    fn floor(self) -> Self {
        unimplemented!();
    }

    fn ceil(self) -> Self {
        unimplemented!();
    }

    fn round(self) -> Self {
        unimplemented!();
    }

    fn trunc(self) -> Self {
        unimplemented!();
    }

    fn fract(self) -> Self {
        unimplemented!();
    }

    fn abs(self) -> Self {
        unimplemented!();
    }

    fn signum(self) -> Self {
        unimplemented!();
    }

    fn is_positive(self) -> bool {
        self.value.is_positive()
    }

    fn is_negative(self) -> bool {
        self.value.is_negative()
    }

    fn mul_add(self, a: Self, b: Self) -> Self {
        unimplemented!();
    }

    fn recip(self) -> Self {
        unimplemented!();
    }

    fn powi(self, n: i32) -> Self {
        unimplemented!();
    }

    fn powf(self, n: Self) -> Self {
        unimplemented!();
    }

    fn sqrt(self) -> Self {
        let one = <T as std::num::Float>::one();
        let two = one + one;
        let sqrt_value = self.value.sqrt();
        Float{value: sqrt_value,
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(
                  (two * sqrt_value).recip(), self.index)}
    }

    fn rsqrt(self) -> Self {
        unimplemented!();
    }

    fn exp(self) -> Self {
        let exp_value = self.value.exp();
        Float{value: exp_value,
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(
                  exp_value, self.index)}
    }

    fn exp2(self) -> Self {
        unimplemented!();
    }

    fn ln(self) -> Self {
        unimplemented!();
    }

    fn log(self, base: Self) -> Self {
        unimplemented!();
    }

    fn log2(self) -> Self {
        unimplemented!();
    }

    fn log10(self) -> Self {
        unimplemented!();
    }

    fn to_degrees(self) -> Self {
        unimplemented!();
    }

    fn to_radians(self) -> Self {
        unimplemented!();
    }

    fn ldexp(x: Self, exp: isize) -> Self {
        unimplemented!();
    }

    fn frexp(self) -> (Self, isize) {
        unimplemented!();
    }

    fn next_after(self, other: Self) -> Self {
        unimplemented!();
    }

    fn max(self, other: Self) -> Self {
        unimplemented!();
    }

    fn min(self, other: Self) -> Self {
        unimplemented!();
    }

    fn abs_sub(self, other: Self) -> Self {
        unimplemented!();
    }

    fn cbrt(self) -> Self {
        unimplemented!();
    }

    fn hypot(self, other: Self) -> Self {
        unimplemented!();
    }

    fn sin(self) -> Self {
        Float{value: self.value.sin(),
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(
                  self.value.cos(), self.index)}
    }

    fn cos(self) -> Self {
        Float{value: self.value.cos(),
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(
                  -self.value.sin(), self.index)}
    }

    fn tan(self) -> Self {
        unimplemented!();
    }

    fn asin(self) -> Self {
        unimplemented!();
    }

    fn acos(self) -> Self {
        unimplemented!();
    }

    fn atan(self) -> Self {
        unimplemented!();
    }

    fn atan2(self, other: Self) -> Self {
        unimplemented!();
    }

    fn sin_cos(self) -> (Self, Self) {
        unimplemented!();
    }

    fn exp_m1(self) -> Self {
        unimplemented!();
    }

    fn ln_1p(self) -> Self {
        unimplemented!();
    }

    fn sinh(self) -> Self {
        unimplemented!();
    }

    fn cosh(self) -> Self {
        unimplemented!();
    }

    fn tanh(self) -> Self {
        unimplemented!();
    }

    fn asinh(self) -> Self {
        unimplemented!();
    }

    fn acosh(self) -> Self {
        unimplemented!();
    }

    fn atanh(self) -> Self {
        unimplemented!();
    }
}

impl <T, CT> std::clone::Clone for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn clone(&self) -> Self {
        Float{value: self.value, index: self.index}
    }
}

impl <T, CT> std::num::ToPrimitive for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn to_i64(&self) -> Option<i64> { self.value.to_i64() }

    fn to_u64(&self) -> Option<u64> { self.value.to_u64() }
    //TODO implement the rest optional function.
}

impl <T, CT> std::num::NumCast for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn from<TP>(n: TP) -> Option<Self> where TP: std::num::ToPrimitive {
        None
    }
}

impl <T, CT> std::ops::Neg for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn neg(self) -> Float<T, CT> {
        // TODO rust doesn't have T::one() yet.
        let one: T = std::num::Float::one();
        Float{value: -self.value,
              index: <CT as super::context::ContextCratePrivate<T>>::unary_operation(one.neg(), self.index)}
    }
}

// TODO adjoints of 1 can be optimized out, i.e., not multiplying. Should we?
impl <T, CT> std::ops::Add<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn add(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value + rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[std::num::Float::one(), std::num::Float::one()],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Sub<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn sub(self, rhs: Float<T, CT>) -> Float<T, CT> {
        let one: T = std::num::Float::one();
        Float{value: self.value - rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[one, -one],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Mul<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn mul(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value * rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[rhs.value, self.value],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::ops::Div<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn div(self, rhs: Float<T, CT>) -> Float<T, CT> {
        Float{value: self.value / rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[rhs.value.recip(), -((self.value * self.value).recip())],
                  &[self.index, rhs.index])}
    }
}

// TODO 1. Does it make sense to support % operator between two Floats ?
//      2. If so, should we record rhs even though the multiplier is 0?
impl <T, CT> std::ops::Rem<Float<T, CT>> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    type Output = Float<T, CT>;
    fn rem(self, rhs: Float<T, CT>) -> Float<T, CT> {
        // TODO add this kind of assert everywhere.
        // assert!(( self . context as * const super::context::Context < T >
        //         ) == (
        //         rhs . context as * const super::context::Context < T > ));
        Float{value: self.value % rhs.value,
              index: <CT as super::context::ContextCratePrivate<T>>::binary_operation(
                  &[std::num::Float::one(), std::num::Float::zero()],
                  &[self.index, rhs.index])}
    }
}

impl <T, CT> std::cmp::PartialEq for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn eq(&self, other: &Float<T, CT>) -> bool { self.value == other.value }
}

impl <T, CT> std::cmp::PartialOrd for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn partial_cmp(&self, other: &Float<T, CT>) -> Option<std::cmp::Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl <T, CT> std::marker::Copy for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
}

// Crate private functions

pub trait FloatCratePrivate<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn new(value: T, index: usize) ->Self;
    fn float_get_index(&self) -> usize;
}

impl <T, CT> FloatCratePrivate<T, CT> for Float<T, CT> where T: std::num::Float, CT: super::context::Context<T> {
    fn new(value: T, index: usize) -> Self {
        Float{value: value, index: index}
    }

    fn float_get_index(&self) -> usize {
        self.index
    }
}
<|endoftext|>