<commit_before>use pom::parser::*;
use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::str::{self, FromStr};
use utils::*;

mod utils;

#[derive(Debug, PartialEq)]
pub struct Equation {
    pub left: Operand,
    pub right: Operand,
}

#[derive(Debug, PartialEq)]
pub struct Function {
    pub name: String,
    pub params: Vec<Operand>,
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Column(Column),
    Function(Function),
    Value(Value),
}

#[derive(Debug, PartialEq)]
pub struct Column {
    name: String,
}

#[derive(Debug, PartialEq)]
pub enum Value {
    Null,
    String(String),
    Number(f64),
    Bool(bool),
}

#[derive(Debug, PartialEq)]
pub enum Connector {
    And,
    Or,
}
#[derive(Debug, PartialEq)]
pub enum Direction {
    Asc,
    Desc,
}

#[derive(Debug, PartialEq)]
pub enum NullsWhere {
    First,
    Last,
}

#[derive(Debug, PartialEq)]
pub struct Order {
    pub operand: Operand,
    pub direction: Option<Direction>,
    pub nulls_where: Option<NullsWhere>,
}

#[derive(Debug, PartialEq)]
pub enum Equality {
    Eq,     // = ,  eq
    Neq,    // != , neq
    Lt,     // <,  lt
    Lte,    // <=, lte
    Gt,     // >, gt
    Gte,    // >=, gte
    In,     // IN, in
    NotIn,  // NOT IN, not_in
    Is,     // IS, is
    IsNot,  // IS NOT, is_not
    Like,   // LIKE, like
    Ilike,  // ILIKE case insensitive like, postgresql specific
    Starts, // Starts with, which will become ILIKE 'value%'
}

#[derive(Debug, PartialEq)]
pub struct Condition {
    pub left: Operand,
    pub equality: Equality,
    pub right: Operand,
}

#[derive(Debug, PartialEq)]
pub struct Filter {
    pub connector: Option<Connector>,
    pub condition: Condition,
    pub sub_filters: Vec<Filter>,
}

#[derive(Debug, PartialEq, Default)]
pub struct Select {
    pub from: Vec<Operand>,
    pub join: Vec<Join>,
    pub filters: Vec<Filter>,
    pub group_by: Vec<Operand>,
    pub having: Vec<Filter>,
    pub order_by: Vec<Order>,
    pub range: Option<Range>,
    pub equations: Vec<Equation>,
}

#[derive(Debug, PartialEq, Default)]
pub struct Page {
    pub page: i64,
    pub page_size: i64,
}

#[derive(Debug, PartialEq, Default)]
pub struct Limit {
    pub limit: i64,
    pub offset: Option<i64>,
}

#[derive(Debug, PartialEq)]
pub enum Range {
    Page(Page),
    Limit(Limit),
}

#[derive(Debug, PartialEq)]
pub enum JoinType {
    Cross,
    Inner,
    Outer,
    Natural,
}
#[derive(Debug, PartialEq)]
pub enum Modifier {
    Left,
    Right,
    Full,
}

#[derive(Debug, PartialEq)]
pub struct Join {
    pub modifier: Option<Modifier>,
    pub join_type: Option<JoinType>,
    pub table: Operand,
    pub column1: Vec<String>,
    pub column2: Vec<String>,
}

#[derive(Debug, PartialEq)]
pub enum Param {
    Condition(Condition),
    Equation(Equation),
}

fn space<'a>() -> Parser<'a, char, ()> {
    one_of(" \t\r\n").repeat(0..).discard()
}

fn ident<'a>() -> Parser<'a, char, String> {
    (is_a(alpha_or_underscore) + is_a(alphanum_or_underscore).repeat(0..))
        .map(|(ch1, rest_ch)| format!("{}{}", ch1, String::from_iter(rest_ch)))
}

/// table.column_name
fn table_column_name<'a>() -> Parser<'a, char, String> {
    (ident() - sym('.') + ident()).map(|(table, column)| format!("{}.{}", table, column)) | ident()
}

fn number<'a>() -> Parser<'a, char, f64> {
    let integer = one_of("123456789") - one_of("0123456789").repeat(0..) | sym('0');
    let frac = sym('.') + one_of("0123456789").repeat(1..);
    let exp = one_of("eE") + one_of("+-").opt() + one_of("0123456789").repeat(1..);
    let number = sym('-').opt() + integer + frac.opt() + exp.opt();
    number
        .collect()
        .map(String::from_iter)
        .convert(|s| f64::from_str(&s))
}

fn quoted_string<'a>() -> Parser<'a, char, String> {
    let special_char = sym('\\')
        | sym('/')
        | sym('"')
        | sym('b').map(|_| '\x08')
        | sym('f').map(|_| '\x0C')
        | sym('n').map(|_| '\n')
        | sym('r').map(|_| '\r')
        | sym('t').map(|_| '\t');
    let escape_sequence = sym('\\') * special_char;
    let char_string = (none_of("\\\"") | escape_sequence)
        .repeat(1..)
        .map(String::from_iter);
    let utf16_char = tag("\\u")
        * is_a(|c: char| c.is_digit(16))
            .repeat(4)
            .map(String::from_iter)
            .convert(|digits| u16::from_str_radix(&digits, 16));
    let utf16_string = utf16_char.repeat(1..).map(|chars| {
        decode_utf16(chars)
            .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
            .collect::<String>()
    });
    let string = sym('"') * (char_string | utf16_string).repeat(0..) - sym('"');
    string.map(|strings| strings.concat())
}

fn string<'a>() -> Parser<'a, char, String> {
    let char_string = none_of("=&()").repeat(1..).map(String::from_iter);
    let string = char_string.repeat(0..);
    string.map(|strings| strings.concat())
}

fn column<'a>() -> Parser<'a, char, Column> {
    table_column_name().map(|name| Column { name })
}

fn bool<'a>() -> Parser<'a, char, bool> {
    tag("true").map(|_| true) | tag("false").map(|_| false)
}

fn null<'a>() -> Parser<'a, char, Value> {
    tag("null").map(|_| Value::Null)
}

fn value<'a>() -> Parser<'a, char, Value> {
    null()
        | bool().map(|v| Value::Bool(v))
        | number().map(|n| Value::Number(n))
        | string().map(|s| Value::String(s))
}

fn connector<'a>() -> Parser<'a, char, Connector> {
    sym('|').map(|_| Connector::Or) | sym('&').map(|_| Connector::And)
}

fn equality<'a>() -> Parser<'a, char, Equality> {
    tag("eq").map(|_| Equality::Eq)
        | tag("neq").map(|_| Equality::Neq)
        | tag("lte").map(|_| Equality::Lte)
        | tag("lt").map(|_| Equality::Lt)
        | tag("gte").map(|_| Equality::Gte)
        | tag("gt").map(|_| Equality::Gt)
        | tag("in").map(|_| Equality::In)
        | tag("not_in").map(|_| Equality::NotIn)
        | tag("is_not").map(|_| Equality::IsNot)
        | tag("like").map(|_| Equality::Like)
        | tag("ilike").map(|_| Equality::Ilike)
        | tag("starts").map(|_| Equality::Starts)
}

fn operand<'a>() -> Parser<'a, char, Operand> {
    null().map(Operand::Value)
        | bool().map(|v| Operand::Value(Value::Bool(v)))
        | number().map(|v| Operand::Value(Value::Number(v)))
        | column().map(Operand::Column)
        | function().map(Operand::Function)
        | value().map(Operand::Value)
}

fn operands<'a>() -> Parser<'a, char, Vec<Operand>> {
    list(call(operand), space() - sym(',') - space())
}

fn function<'a>() -> Parser<'a, char, Function> {
    (ident() - sym('(') + operands() - sym(')')).map(|(name, params)| Function { name, params })
}

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

    #[test]
    fn test_function() {
        let input = to_chars("max(seq_no)");
        let ret = function().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Function {
                name: "max".into(),
                params: vec![Operand::Column(Column {
                    name: "seq_no".into()
                })]
            }
        );
    }

    #[test]
    fn test_column() {
        let input = to_chars("product_id");
        let ret = column().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Column {
                name: "product_id".into()
            }
        );
    }

    #[test]
    fn test_value_bool() {
        let input = to_chars("true");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Bool(true));
    }
    #[test]
    fn test_value_bool2() {
        let input = to_chars("false");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Bool(false));
    }
    #[test]
    fn test_value_number() {
        let input = to_chars("0.1312312");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Number(0.1312312));
    }
    #[test]
    fn test_value_number2() {
        let input = to_chars("3.14159");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Number(3.14159));
    }

    #[test]
    fn test_string() {
        let input = to_chars("product_id");
        let ret = string().parse(&input).expect("must be parsed");
        assert_eq!(ret, "product_id");
    }

    #[test]
    fn test_iregular_string() {
        let input = to_chars("a string value\"pr'oduct_id");
        let ret = string().parse(&input).expect("must be parsed");
        assert_eq!(ret, "a string value\"pr\'oduct_id");
    }

    #[test]
    fn test_bool_operand() {
        let input = to_chars("true");
        let ret = operand().parse(&input).expect("must be parsed");
        assert_eq!(ret, Operand::Value(Value::Bool(true)));
    }
    #[test]
    fn test_null_operand() {
        let input = to_chars("null");
        let ret = operand().parse(&input).expect("must be parsed");
        assert_eq!(ret, Operand::Value(Value::Null));
    }
}
<commit_msg>Implement parser for condition, rename Equality to Operand<commit_after>use pom::parser::*;
use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::str::{self, FromStr};
use utils::*;

mod utils;

#[derive(Debug, PartialEq)]
pub struct Equation {
    pub left: Operand,
    pub right: Operand,
}

#[derive(Debug, PartialEq)]
pub struct Function {
    pub name: String,
    pub params: Vec<Operand>,
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Column(Column),
    Function(Function),
    Value(Value),
}

#[derive(Debug, PartialEq)]
pub struct Column {
    name: String,
}

#[derive(Debug, PartialEq)]
pub enum Value {
    Null,
    String(String),
    Number(f64),
    Bool(bool),
}

#[derive(Debug, PartialEq)]
pub enum Connector {
    And,
    Or,
}
#[derive(Debug, PartialEq)]
pub enum Direction {
    Asc,
    Desc,
}

#[derive(Debug, PartialEq)]
pub enum NullsWhere {
    First,
    Last,
}

#[derive(Debug, PartialEq)]
pub struct Order {
    pub operand: Operand,
    pub direction: Option<Direction>,
    pub nulls_where: Option<NullsWhere>,
}

//TODO: rename to Operator, BinaryOperator
#[derive(Debug, PartialEq)]
pub enum Operator {
    Eq,     // = ,  eq
    Neq,    // != , neq
    Lt,     // <,  lt
    Lte,    // <=, lte
    Gt,     // >, gt
    Gte,    // >=, gte
    In,     // IN, in
    NotIn,  // NOT IN, not_in
    Is,     // IS, is
    IsNot,  // IS NOT, is_not
    Like,   // LIKE, like
    Ilike,  // ILIKE case insensitive like, postgresql specific
    Starts, // Starts with, which will become ILIKE 'value%'
}

#[derive(Debug, PartialEq)]
pub struct Condition {
    pub left: Operand,
    pub equality: Operator,
    pub right: Operand,
}

#[derive(Debug, PartialEq)]
pub struct Filter {
    pub connector: Option<Connector>,
    pub condition: Condition,
    pub sub_filters: Vec<Filter>,
}

#[derive(Debug, PartialEq, Default)]
pub struct Select {
    pub from: Vec<Operand>,
    pub join: Vec<Join>,
    pub filters: Vec<Filter>,
    pub group_by: Vec<Operand>,
    pub having: Vec<Filter>,
    pub order_by: Vec<Order>,
    pub range: Option<Range>,
    pub equations: Vec<Equation>,
}

#[derive(Debug, PartialEq, Default)]
pub struct Page {
    pub page: i64,
    pub page_size: i64,
}

#[derive(Debug, PartialEq, Default)]
pub struct Limit {
    pub limit: i64,
    pub offset: Option<i64>,
}

#[derive(Debug, PartialEq)]
pub enum Range {
    Page(Page),
    Limit(Limit),
}

#[derive(Debug, PartialEq)]
pub enum JoinType {
    Cross,
    Inner,
    Outer,
    Natural,
}
#[derive(Debug, PartialEq)]
pub enum Modifier {
    Left,
    Right,
    Full,
}

#[derive(Debug, PartialEq)]
pub struct Join {
    pub modifier: Option<Modifier>,
    pub join_type: Option<JoinType>,
    pub table: Operand,
    pub column1: Vec<String>,
    pub column2: Vec<String>,
}

#[derive(Debug, PartialEq)]
pub enum Param {
    Condition(Condition),
    Equation(Equation),
}

fn space<'a>() -> Parser<'a, char, ()> {
    one_of(" \t\r\n").repeat(0..).discard()
}

fn ident<'a>() -> Parser<'a, char, String> {
    (is_a(alpha_or_underscore) + is_a(alphanum_or_underscore).repeat(0..))
        .map(|(ch1, rest_ch)| format!("{}{}", ch1, String::from_iter(rest_ch)))
}

/// table.column_name
fn table_column_name<'a>() -> Parser<'a, char, String> {
    (ident() - sym('.') + ident()).map(|(table, column)| format!("{}.{}", table, column)) | ident()
}

fn number<'a>() -> Parser<'a, char, f64> {
    let integer = one_of("123456789") - one_of("0123456789").repeat(0..) | sym('0');
    let frac = sym('.') + one_of("0123456789").repeat(1..);
    let exp = one_of("eE") + one_of("+-").opt() + one_of("0123456789").repeat(1..);
    let number = sym('-').opt() + integer + frac.opt() + exp.opt();
    number
        .collect()
        .map(String::from_iter)
        .convert(|s| f64::from_str(&s))
}

fn quoted_string<'a>() -> Parser<'a, char, String> {
    let special_char = sym('\\')
        | sym('/')
        | sym('"')
        | sym('b').map(|_| '\x08')
        | sym('f').map(|_| '\x0C')
        | sym('n').map(|_| '\n')
        | sym('r').map(|_| '\r')
        | sym('t').map(|_| '\t');
    let escape_sequence = sym('\\') * special_char;
    let char_string = (none_of("\\\"") | escape_sequence)
        .repeat(1..)
        .map(String::from_iter);
    let utf16_char = tag("\\u")
        * is_a(|c: char| c.is_digit(16))
            .repeat(4)
            .map(String::from_iter)
            .convert(|digits| u16::from_str_radix(&digits, 16));
    let utf16_string = utf16_char.repeat(1..).map(|chars| {
        decode_utf16(chars)
            .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
            .collect::<String>()
    });
    let string = sym('"') * (char_string | utf16_string).repeat(0..) - sym('"');
    string.map(|strings| strings.concat())
}

fn string<'a>() -> Parser<'a, char, String> {
    let char_string = none_of("=&()").repeat(1..).map(String::from_iter);
    let string = char_string.repeat(0..);
    string.map(|strings| strings.concat())
}

fn column<'a>() -> Parser<'a, char, Column> {
    table_column_name().map(|name| Column { name })
}

fn bool<'a>() -> Parser<'a, char, bool> {
    tag("true").map(|_| true) | tag("false").map(|_| false)
}

fn null<'a>() -> Parser<'a, char, Value> {
    tag("null").map(|_| Value::Null)
}

fn value<'a>() -> Parser<'a, char, Value> {
    null()
        | bool().map(|v| Value::Bool(v))
        | number().map(|n| Value::Number(n))
        | string().map(|s| Value::String(s))
}

fn connector<'a>() -> Parser<'a, char, Connector> {
    sym('|').map(|_| Connector::Or) | sym('&').map(|_| Connector::And)
}

fn equality<'a>() -> Parser<'a, char, Operator> {
    tag("eq").map(|_| Operator::Eq)
        | tag("neq").map(|_| Operator::Neq)
        | tag("lte").map(|_| Operator::Lte)
        | tag("lt").map(|_| Operator::Lt)
        | tag("gte").map(|_| Operator::Gte)
        | tag("gt").map(|_| Operator::Gt)
        | tag("in").map(|_| Operator::In)
        | tag("not_in").map(|_| Operator::NotIn)
        | tag("is_not").map(|_| Operator::IsNot)
        | tag("like").map(|_| Operator::Like)
        | tag("ilike").map(|_| Operator::Ilike)
        | tag("starts").map(|_| Operator::Starts)
}

fn operand<'a>() -> Parser<'a, char, Operand> {
    null().map(Operand::Value)
        | bool().map(|v| Operand::Value(Value::Bool(v)))
        | number().map(|v| Operand::Value(Value::Number(v)))
        | column().map(Operand::Column)
        | function().map(Operand::Function)
        | value().map(Operand::Value)
}

fn operands<'a>() -> Parser<'a, char, Vec<Operand>> {
    list(call(operand), space() - sym(',') - space())
}

fn function<'a>() -> Parser<'a, char, Function> {
    (ident() - sym('(') + operands() - sym(')')).map(|(name, params)| Function { name, params })
}

// age=gt.42
// name=allan
fn condition<'a>() -> Parser<'a, char, Condition> {
    (operand() - sym('=') + (equality() - sym('.')).opt() + operand()).map(
        |((left, equality), right)| Condition {
            left,
            equality: equality.unwrap_or(Operator::Eq),
            right,
        },
    )
}

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

    #[test]
    fn test_condition_gt() {
        let input = to_chars("age=gt.42");
        let ret = condition().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Condition {
                left: Operand::Column(Column { name: "age".into() }),
                equality: Operator::Gt,
                right: Operand::Value(Value::Number(42.0))
            }
        );
    }
    #[test]
    fn test_condition_lte() {
        let input = to_chars("age=lte.42");
        let ret = condition().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Condition {
                left: Operand::Column(Column { name: "age".into() }),
                equality: Operator::Lte,
                right: Operand::Value(Value::Number(42.0))
            }
        );
    }

    #[test]
    fn test_condition_default_eq() {
        let input = to_chars("age=42");
        let ret = condition().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Condition {
                left: Operand::Column(Column { name: "age".into() }),
                equality: Operator::Eq,
                right: Operand::Value(Value::Number(42.0))
            }
        );
    }

    #[test]
    fn test_function() {
        let input = to_chars("max(seq_no)");
        let ret = function().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Function {
                name: "max".into(),
                params: vec![Operand::Column(Column {
                    name: "seq_no".into()
                })]
            }
        );
    }

    #[test]
    fn test_column() {
        let input = to_chars("product_id");
        let ret = column().parse(&input).expect("must be parsed");
        assert_eq!(
            ret,
            Column {
                name: "product_id".into()
            }
        );
    }

    #[test]
    fn test_value_bool() {
        let input = to_chars("true");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Bool(true));
    }
    #[test]
    fn test_value_bool2() {
        let input = to_chars("false");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Bool(false));
    }
    #[test]
    fn test_value_number() {
        let input = to_chars("0.1312312");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Number(0.1312312));
    }
    #[test]
    fn test_value_number2() {
        let input = to_chars("3.14159");
        let ret = value().parse(&input).expect("must be parsed");
        assert_eq!(ret, Value::Number(3.14159));
    }

    #[test]
    fn test_string() {
        let input = to_chars("product_id");
        let ret = string().parse(&input).expect("must be parsed");
        assert_eq!(ret, "product_id");
    }

    #[test]
    fn test_iregular_string() {
        let input = to_chars("a string value\"pr'oduct_id");
        let ret = string().parse(&input).expect("must be parsed");
        assert_eq!(ret, "a string value\"pr\'oduct_id");
    }

    #[test]
    fn test_bool_operand() {
        let input = to_chars("true");
        let ret = operand().parse(&input).expect("must be parsed");
        assert_eq!(ret, Operand::Value(Value::Bool(true)));
    }
    #[test]
    fn test_null_operand() {
        let input = to_chars("null");
        let ret = operand().parse(&input).expect("must be parsed");
        assert_eq!(ret, Operand::Value(Value::Null));
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Read;

#[derive(Debug)]
#[derive(Clone)]
pub struct Command {
    pub cmd: String,
    pub argv: Vec<String>
}

impl Command {
    pub fn new() -> Command {
        Command{
            cmd: String::from(""),
            argv: Vec::new()
        }
    }
}

impl PartialEq for Command {
    fn eq(&self, other: &Command) -> bool {
        if self.cmd != other.cmd {
            println!("CMD DOESN'T MATCH");
            return false
        }
        if self.argv.len() != other.argv.len() {
            println!("ARGV DOESN'T MATCH");
            return false
        }
        let matches = self.argv.iter().zip(other.argv.iter()).filter(|&(a,b)|a == b).count();
        matches == self.argv.len()
    }
}

pub struct Parser {
    current: Command,
    buffer: Vec<char>,
    in_progress: bool,
    escape: bool
}

pub enum Line {
    Full(Command),
    Partial,
    Empty,
}

impl Parser {
    pub fn new() -> Parser {
        Parser{
            current: Command::new(),
            buffer: Vec::new(),
            in_progress: false,
            escape: false
        }
    }

    pub fn get_command(&mut self) -> Result<Line, &'static str> {
        for character in io::stdin().chars() {
            match self.parse(character.expect("Unable to read from stdin")).expect("Parse error") {
                Line::Full(cmd) => return Ok(Line::Full(cmd)),
                Line::Partial => return Ok(Line::Partial),
                Line::Empty => ()
            }
        }

        return Ok(Line::Empty)
    }

    fn parse(&mut self, input: char) -> Result<Line,&'static str> {
        if self.in_progress == false {
            self.current = Command::new();
        }

        self.in_progress = true;

        match input {
                ' ' => {
                    if self.escape {
                        self.buffer.push(' ');
                        self.escape = false;
                    } else {
                        if self.current.cmd == "" {
                            self.current.cmd = self.buffer.iter().cloned().collect();
                            self.buffer = Vec::new();
                        } else {
                            self.current.argv.push(self.buffer.iter().cloned().collect());
                            self.buffer = Vec::new();
                        }
                    }
                }
                '\\' => {
                    if self.escape {
                        self.buffer.push('\\');
                        self.escape = false;
                    } else {
                        self.escape = true;
                    }
                }
                '\n' => {
                    if ! self.escape {
                        self.in_progress = false;
                        if self.current.cmd == "" {
                            self.current.cmd = self.buffer.iter().cloned().collect();
                            self.buffer = Vec::new();
                        } else {
                            self.current.argv.push(self.buffer.iter().cloned().collect());
                            self.buffer = Vec::new();
                        }
                        if self.current.cmd == "" {
                            return Ok(Line::Empty)
                        } else {
                            return Ok(Line::Full(self.current.clone()))
                        }
                    } else {
                        self.escape = false;
						return Ok(Line::Partial)
                    }
                }
                x => {
                    self.buffer.push(x);
                }
            }

        Ok(Line::Empty)
    }
}

mod tests {
    #[allow(unused_imports)]
    use super::*;

    #[test]
    fn basic_parser_test() {
        let input = String::from("echo hello world");
        let expected = Command{
            cmd: String::from("echo"),
            argv: vec!(String::from("hello"), String::from("world"))
        };

        let mut parser = Parser::new();
        for c in input.chars() {
            parser.parse(c).unwrap();
        }

        let result = parser.parse('\n').unwrap().unwrap();
        assert_eq!(result, expected)
    }

    #[test]
    fn newline_parser_test() {
        let input = String::from("echo hello world");
        let other_input = String::from("foo");
        let expected = Command{
            cmd: String::from("echo"),
            argv: vec!(String::from("hello"), String::from("worldfoo"))
        };

        let mut parser = Parser::new();
        for c in input.chars() {
            parser.parse(c).unwrap();
        }

        parser.parse('\\').unwrap();
        parser.parse('\n').unwrap();

        for c in other_input.chars() {
            parser.parse(c).unwrap();
        }

        let result = parser.parse('\n').unwrap().unwrap();
        assert_eq!(result, expected)
    }
}
<commit_msg>Fix tests<commit_after>use std::io;
use std::io::Read;

#[derive(Debug)]
#[derive(Clone)]
pub struct Command {
    pub cmd: String,
    pub argv: Vec<String>
}

impl Command {
    pub fn new() -> Command {
        Command{
            cmd: String::from(""),
            argv: Vec::new()
        }
    }
}

impl PartialEq for Command {
    fn eq(&self, other: &Command) -> bool {
        if self.cmd != other.cmd {
            println!("CMD DOESN'T MATCH");
            return false
        }
        if self.argv.len() != other.argv.len() {
            println!("ARGV DOESN'T MATCH");
            return false
        }
        let matches = self.argv.iter().zip(other.argv.iter()).filter(|&(a,b)|a == b).count();
        matches == self.argv.len()
    }
}

pub struct Parser {
    current: Command,
    buffer: Vec<char>,
    in_progress: bool,
    escape: bool
}

pub enum Line {
    Full(Command),
    Partial,
    Empty,
}

impl Parser {
    pub fn new() -> Parser {
        Parser{
            current: Command::new(),
            buffer: Vec::new(),
            in_progress: false,
            escape: false
        }
    }

    pub fn get_command(&mut self) -> Result<Line, &'static str> {
        for character in io::stdin().chars() {
            match self.parse(character.expect("Unable to read from stdin")).expect("Parse error") {
                Line::Full(cmd) => return Ok(Line::Full(cmd)),
                Line::Partial => return Ok(Line::Partial),
                Line::Empty => ()
            }
        }

        return Ok(Line::Empty)
    }

    fn parse(&mut self, input: char) -> Result<Line,&'static str> {
        if self.in_progress == false {
            self.current = Command::new();
        }

        self.in_progress = true;

        match input {
                ' ' => {
                    if self.escape {
                        self.buffer.push(' ');
                        self.escape = false;
                    } else {
                        if self.current.cmd == "" {
                            self.current.cmd = self.buffer.iter().cloned().collect();
                            self.buffer = Vec::new();
                        } else {
                            self.current.argv.push(self.buffer.iter().cloned().collect());
                            self.buffer = Vec::new();
                        }
                    }
                }
                '\\' => {
                    if self.escape {
                        self.buffer.push('\\');
                        self.escape = false;
                    } else {
                        self.escape = true;
                    }
                }
                '\n' => {
                    if ! self.escape {
                        self.in_progress = false;
                        if self.current.cmd == "" {
                            self.current.cmd = self.buffer.iter().cloned().collect();
                            self.buffer = Vec::new();
                        } else {
                            self.current.argv.push(self.buffer.iter().cloned().collect());
                            self.buffer = Vec::new();
                        }
                        if self.current.cmd == "" {
                            return Ok(Line::Empty)
                        } else {
                            return Ok(Line::Full(self.current.clone()))
                        }
                    } else {
                        self.escape = false;
						return Ok(Line::Partial)
                    }
                }
                x => {
                    self.buffer.push(x);
                }
            }

        Ok(Line::Empty)
    }
}

mod tests {
    #[allow(unused_imports)]
    use super::*;

    #[test]
    fn basic_parser_test() {
        let input = String::from("echo hello world");
        let expected = Command{
            cmd: String::from("echo"),
            argv: vec!(String::from("hello"), String::from("world"))
        };

        let mut parser = Parser::new();
        for c in input.chars() {
            parser.parse(c).unwrap();
        }

        match parser.parse('\n').unwrap() {
            Line::Full(result) => assert_eq!(result, expected),
            _ => panic!("Failed to get result from parser on newline")
        }
    }

    #[test]
    fn newline_parser_test() {
        let input = String::from("echo hello world");
        let other_input = String::from("foo");
        let expected = Command{
            cmd: String::from("echo"),
            argv: vec!(String::from("hello"), String::from("worldfoo"))
        };

        let mut parser = Parser::new();
        for c in input.chars() {
            parser.parse(c).unwrap();
        }

        parser.parse('\\').unwrap();
        parser.parse('\n').unwrap();

        for c in other_input.chars() {
            parser.parse(c).unwrap();
        }

        match parser.parse('\n').unwrap() {
            Line::Full(result) => assert_eq!(result, expected),
            _ => panic!("Failed to get result from parser on newline")
        }
    }
}
<|endoftext|>


<commit_before>use ast::*;
use scanner::{Token, TokenWithContext};
use std::iter::Peekable;

#[derive(Debug)]
pub struct ParseError {
    message: String,
}

impl ParseError {
    fn from_message(message: String) -> ParseError {
        ParseError { message: message }
    }
}

pub fn parse(tokens: Vec<TokenWithContext>) -> Result<Expr, Vec<ParseError>> {
    let mut iter = tokens.iter().peekable();
    if let Some(result) = parse_expression(&mut iter) {
        match result {
            Ok(expr) => {
                if let None = iter.next() {
                    Ok(expr)
                } else {
                    Err(vec![ParseError::from_message("Parser didn't consume all the tokens"
                                 .into())])
                }
            }
            Err(error) => {
                {
                    synchronise(&mut iter);
                }
                Err(vec![error])
            }
        }

    } else {
        Err(vec![ParseError::from_message("Parser didn't return anything".into())])
    }
}

fn synchronise<'a, I>(tokens: &mut Peekable<I>)
    where I: Iterator<Item = &'a TokenWithContext>
{
    while let Some(token_with_context) = tokens.peek().cloned() {
        match token_with_context.token {
            Token::Semicolon => {
                let _ = tokens.next();
                break;
            }
            Token::Class => break,
            Token::Fun => break,
            Token::Var => break,
            Token::For => break,
            Token::If => break,
            Token::While => break,
            Token::Print => break,
            Token::Return => break,
            _ => {
                let _ = tokens.next();
            }
        }
    }
}

fn parse_expression<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    parse_equality(tokens)
}

fn parse_binary<'a, I>(tokens: &mut Peekable<I>,
                       map_operator: &Fn(&Token) -> Option<Operator>,
                       parse_subexpression: &Fn(&mut Peekable<I>)
                                                -> Option<Result<Expr, ParseError>>)
                       -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let mut expr;
    {
        if let Some(result) = parse_subexpression(tokens) {
            match result {
                Ok(subexpression) => expr = subexpression,
                _ => return Some(result),
            }
        } else {
            return None;
        }
    };
    while let Some(Some(mapped_operator)) = tokens.peek().map(|pt| map_operator(&pt.token)) {
        let operator; // We know it's right, we read it just for error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_subexpression(tokens) {
                match result {
                    Ok(subexpression) => right = subexpression,
                    _ => return Some(result),
                }
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let binary_expression = BinaryExpr {
            left: expr,
            operator: mapped_operator,
            right: right,
        };
        expr = Expr::Binary(Box::new(binary_expression));
    }
    Some(Ok(expr))
}

fn parse_equality<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::BangEqual => Some(Operator::NotEqual),
            &Token::EqualEqual => Some(Operator::Equal),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_comparison)
}

fn parse_comparison<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Greater => Some(Operator::Greater),
            &Token::GreaterEqual => Some(Operator::GreaterEqual),
            &Token::Less => Some(Operator::Less),
            &Token::LessEqual => Some(Operator::LessEqual),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_term)
}

fn parse_term<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Plus => Some(Operator::Plus),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_factor)
}

fn parse_factor<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Slash => Some(Operator::Slash),
            &Token::Star => Some(Operator::Star),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_unary)
}

fn parse_unary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Bang => Some(Operator::Bang),
            _ => None,
        }
    }
    if let Some(Some(mapped_operator)) = tokens.peek().cloned().map(|pt| map_operator(&pt.token)) {
        let operator; // For error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_unary(tokens) {
                match result {
                    Ok(unary_expression) => right = unary_expression,
                    _ => return Some(result),
                }
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let unary_expression = UnaryExpr {
            operator: mapped_operator,
            right: right,
        };
        return Some(Ok(Expr::Unary(Box::new(unary_expression))));
    } else {
        parse_primary(tokens)
    }
}

fn parse_primary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let primary_token;
    {
        primary_token = tokens.next();
    };
    if let Some(primary_token) = primary_token {
        let parsed_expression = match primary_token.token {
            Token::False => Expr::Literal(Literal::BoolLiteral(false)),
            Token::True => Expr::Literal(Literal::BoolLiteral(true)),
            Token::Nil => Expr::Literal(Literal::NilLiteral),
            Token::NumberLiteral(n) => Expr::Literal(Literal::NumberLiteral(n)),
            Token::StringLiteral(ref s) => Expr::Literal(Literal::StringLiteral(s.clone())),
            Token::LeftParen => {
                let expr;
                {
                    if let Some(result) = parse_expression(tokens) {
                        match result {
                            Ok(expression) => expr = expression,
                            _ => return Some(result),
                        }
                    } else {
                        return Some(Err(ParseError::from_message(format!("Unfinished grouping \
                                                                     expression near {:?} at \
                                                                     {:?}",
                                                                         primary_token.lexeme,
                                                                         primary_token.position))));
                    }
                };
                {
                    if let Some(token) = tokens.next() {
                        if token.token == Token::RightParen {
                            let grouping_expression = Grouping { expr: expr };
                            return Some(Ok(Expr::Grouping(Box::new(grouping_expression))));
                        } else {
                            return Some(Err(ParseError::from_message(format!("Missing ) near \
                                                                              {:?} at {:?}",
                                                                             token.lexeme,
                                                                             token.position))));
                        }

                    }
                    return Some(Err(ParseError::from_message(format!("Missing ) before end of \
                                                                      file"))));
                }
            }
            _ => {
                return Some(Err(ParseError::from_message(format!("Unexpected token {:?} at \
                                                                  {:?}",
                                                                 primary_token.lexeme,
                                                                 primary_token.position))));
            }
        };
        Some(Ok(parsed_expression))
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use pretty_printer::PrettyPrint;

    #[test]
    fn literal() {
        let (tokens, _) = scan(&"123".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("123", &expr.pretty_print());
    }

    #[test]
    fn binary() {
        let (tokens, _) = scan(&"123+456".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 456)", &expr.pretty_print());
    }

    #[test]
    fn precedence_add_mul() {
        let (tokens, _) = scan(&"123+456*789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 (* 456 789))", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add() {
        let (tokens, _) = scan(&"123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* 123 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add_unary() {
        let (tokens, _) = scan(&"-123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* (- 123) 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn unclosed_group() {
        let (tokens, _) = scan(&"(2".into());
        assert!(parse(tokens).is_err());
    }

    #[test]
    fn unopened_group() {
        let (tokens, _) = scan(&"2)".into());
        assert!(parse(tokens).is_err());
    }
}
<commit_msg>Simplified pattern matching<commit_after>use ast::*;
use scanner::{Token, TokenWithContext};
use std::iter::Peekable;

#[derive(Debug)]
pub struct ParseError {
    message: String,
}

impl ParseError {
    fn from_message(message: String) -> ParseError {
        ParseError { message: message }
    }
}

pub fn parse(tokens: Vec<TokenWithContext>) -> Result<Expr, Vec<ParseError>> {
    let mut iter = tokens.iter().peekable();
    if let Some(result) = parse_expression(&mut iter) {
        match result {
            Ok(expr) => {
                if let None = iter.next() {
                    Ok(expr)
                } else {
                    Err(vec![ParseError::from_message("Parser didn't consume all the tokens"
                                 .into())])
                }
            }
            Err(error) => {
                {
                    synchronise(&mut iter);
                }
                Err(vec![error])
            }
        }

    } else {
        Err(vec![ParseError::from_message("Parser didn't return anything".into())])
    }
}

fn synchronise<'a, I>(tokens: &mut Peekable<I>)
    where I: Iterator<Item = &'a TokenWithContext>
{
    while let Some(token_with_context) = tokens.peek().cloned() {
        match token_with_context.token {
            Token::Semicolon => {
                let _ = tokens.next();
                break;
            }
            Token::Class => break,
            Token::Fun => break,
            Token::Var => break,
            Token::For => break,
            Token::If => break,
            Token::While => break,
            Token::Print => break,
            Token::Return => break,
            _ => {
                let _ = tokens.next();
            }
        }
    }
}

fn parse_expression<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    parse_equality(tokens)
}

fn parse_binary<'a, I>(tokens: &mut Peekable<I>,
                       map_operator: &Fn(&Token) -> Option<Operator>,
                       parse_subexpression: &Fn(&mut Peekable<I>)
                                                -> Option<Result<Expr, ParseError>>)
                       -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let mut expr;
    {
        let result = parse_subexpression(tokens);
        if let Some(Ok(subexpression)) =  result{
            expr = subexpression;
        } else {
            return result;
        }
    };
    while let Some(Some(mapped_operator)) = tokens.peek().map(|pt| map_operator(&pt.token)) {
        let operator; // We know it's right, we read it just for error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_subexpression(tokens) {
                match result {
                    Ok(subexpression) => right = subexpression,
                    _ => return Some(result),
                }
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let binary_expression = BinaryExpr {
            left: expr,
            operator: mapped_operator,
            right: right,
        };
        expr = Expr::Binary(Box::new(binary_expression));
    }
    Some(Ok(expr))
}

fn parse_equality<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::BangEqual => Some(Operator::NotEqual),
            &Token::EqualEqual => Some(Operator::Equal),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_comparison)
}

fn parse_comparison<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Greater => Some(Operator::Greater),
            &Token::GreaterEqual => Some(Operator::GreaterEqual),
            &Token::Less => Some(Operator::Less),
            &Token::LessEqual => Some(Operator::LessEqual),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_term)
}

fn parse_term<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Plus => Some(Operator::Plus),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_factor)
}

fn parse_factor<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Slash => Some(Operator::Slash),
            &Token::Star => Some(Operator::Star),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_unary)
}

fn parse_unary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Bang => Some(Operator::Bang),
            _ => None,
        }
    }
    if let Some(Some(mapped_operator)) = tokens.peek().cloned().map(|pt| map_operator(&pt.token)) {
        let operator; // For error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_unary(tokens) {
                match result {
                    Ok(unary_expression) => right = unary_expression,
                    _ => return Some(result),
                }
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let unary_expression = UnaryExpr {
            operator: mapped_operator,
            right: right,
        };
        return Some(Ok(Expr::Unary(Box::new(unary_expression))));
    } else {
        parse_primary(tokens)
    }
}

fn parse_primary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let primary_token;
    {
        primary_token = tokens.next();
    };
    if let Some(primary_token) = primary_token {
        let parsed_expression = match primary_token.token {
            Token::False => Expr::Literal(Literal::BoolLiteral(false)),
            Token::True => Expr::Literal(Literal::BoolLiteral(true)),
            Token::Nil => Expr::Literal(Literal::NilLiteral),
            Token::NumberLiteral(n) => Expr::Literal(Literal::NumberLiteral(n)),
            Token::StringLiteral(ref s) => Expr::Literal(Literal::StringLiteral(s.clone())),
            Token::LeftParen => {
                let expr;
                {
                    if let Some(result) = parse_expression(tokens) {
                        match result {
                            Ok(expression) => expr = expression,
                            _ => return Some(result),
                        }
                    } else {
                        return Some(Err(ParseError::from_message(format!("Unfinished grouping \
                                                                     expression near {:?} at \
                                                                     {:?}",
                                                                         primary_token.lexeme,
                                                                         primary_token.position))));
                    }
                };
                {
                    if let Some(token) = tokens.next() {
                        if token.token == Token::RightParen {
                            let grouping_expression = Grouping { expr: expr };
                            return Some(Ok(Expr::Grouping(Box::new(grouping_expression))));
                        } else {
                            return Some(Err(ParseError::from_message(format!("Missing ) near \
                                                                              {:?} at {:?}",
                                                                             token.lexeme,
                                                                             token.position))));
                        }

                    }
                    return Some(Err(ParseError::from_message(format!("Missing ) before end of \
                                                                      file"))));
                }
            }
            _ => {
                return Some(Err(ParseError::from_message(format!("Unexpected token {:?} at \
                                                                  {:?}",
                                                                 primary_token.lexeme,
                                                                 primary_token.position))));
            }
        };
        Some(Ok(parsed_expression))
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use pretty_printer::PrettyPrint;

    #[test]
    fn literal() {
        let (tokens, _) = scan(&"123".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("123", &expr.pretty_print());
    }

    #[test]
    fn binary() {
        let (tokens, _) = scan(&"123+456".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 456)", &expr.pretty_print());
    }

    #[test]
    fn precedence_add_mul() {
        let (tokens, _) = scan(&"123+456*789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 (* 456 789))", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add() {
        let (tokens, _) = scan(&"123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* 123 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add_unary() {
        let (tokens, _) = scan(&"-123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* (- 123) 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn unclosed_group() {
        let (tokens, _) = scan(&"(2".into());
        assert!(parse(tokens).is_err());
    }

    #[test]
    fn unopened_group() {
        let (tokens, _) = scan(&"2)".into());
        assert!(parse(tokens).is_err());
    }
}
<|endoftext|>


<commit_before>use lexer;
use lexer::{Lexer, Token, TokenKind};
use node::AST;
use node;
use error;
use types::Type;

use std::fs::OpenOptions;
use std::io::prelude::*;
use std::{str, u32};
use std::rc::Rc;

pub fn run_file(filename: String) -> Vec<AST> {
    let mut nodes: Vec<AST> = Vec::new();
    let mut file = OpenOptions::new()
        .read(true)
        .open(filename.to_string())
        .unwrap();
    let mut s = String::new();
    file.read_to_string(&mut s);
    let mut lexer = Lexer::new(filename.to_string(), s.as_str());
    loop {
        let tok = lexer.get();
        match tok {
            Some(t) => {
                // if t.kind == TokenKind::Newline {
                //     println!();
                // } else {
                println!("t:{}{}", if t.space { " " } else { "" }, t.val);
                // }
            }
            None => break,
        }
    }

    // lexer = Lexer::new(filename.to_string(), s.as_str());
    // nodes.push(read_toplevel(&mut lexer));
    // nodes.pop().unwrap().show();

    nodes
}

pub fn run(input: String) -> Vec<AST> {
    let mut nodes: Vec<AST> = Vec::new();
    let mut lexer = Lexer::new("__input__".to_string(), input.as_str());

    nodes.push(read_toplevel(&mut lexer));

    nodes
}

fn read_toplevel(lexer: &mut Lexer) -> AST {
    if is_function_def(lexer) {
        println!("this is function");
        read_func_def(lexer)
    } else {
        read_expr(lexer)
    }
}

fn read_func_def(lexer: &mut Lexer) -> AST {
    AST::Int(0)
}

fn is_function_def(lexer: &mut Lexer) -> bool {
    let mut buf: Vec<Token> = Vec::new();
    let mut is_funcdef = false;

    loop {
        let mut tok = lexer.get().unwrap();
        buf.push(tok.clone());

        if is_type(&tok) {
            continue;
        }

        if tok.val == "(" {
            skip_brackets(lexer, &mut buf);
            continue;
        }

        if tok.kind != TokenKind::Identifier {
            continue;
        }

        if tok.val == "(" {
            continue;
        }

        skip_brackets(lexer, &mut buf);

        tok = lexer.peek().unwrap();
        is_funcdef = tok.val.as_str() == "{";
        break;
    }

    lexer.unget_all(buf);
    is_funcdef
}

fn skip_brackets(lexer: &mut Lexer, buf: &mut Vec<Token>) {
    loop {
        let tok = lexer.get().unwrap();
        buf.push(tok.clone());

        match tok.val.as_str() {
            "(*" => skip_brackets(lexer, buf),
            ")" => break,
            _ => {}
        }
    }
}

fn is_type(token: &Token) -> bool {
    if token.kind != TokenKind::Identifier {
        return true;
    }
    match token.val.as_str() {
        "int" => true,
        _ => false,
    }
}

fn read_decl(lexer: &mut Lexer) -> AST {
    let basety = read_type_spec(lexer);
    AST::Int(0)
}

fn read_type_spec(lexer: &mut Lexer) -> Type {
    enum Sign {
        Signed,
        Unsigned,
    };
    enum Size {
        Short,
        Normal,
        Long,
        LLong,
    };
    let sign: Sign = Sign::Signed;
    let size: Size = Size::Normal;

    loop {
        let tok = lexer
            .get()
            .or_else(|| error::error_exit(lexer.cur_line, "expect types but reach EOF"))
            .unwrap();

        match tok.val.as_str() {
            "void" => {}
            _ => {}
        }
    }
}

pub fn read_expr(lexer: &mut Lexer) -> AST {
    let lhs = read_comma(lexer);
    lhs
}
////////// operators start from here
fn read_comma(lexer: &mut Lexer) -> AST {
    let mut lhs = read_logor(lexer);
    while lexer.skip(",") {
        let rhs = read_logor(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Comma);
    }
    lhs
}
fn read_logor(lexer: &mut Lexer) -> AST {
    let mut lhs = read_logand(lexer);
    while lexer.skip("||") {
        let rhs = read_logand(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::LOr);
    }
    lhs
}
fn read_logand(lexer: &mut Lexer) -> AST {
    let mut lhs = read_or(lexer);
    while lexer.skip("&&") {
        let rhs = read_or(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::LAnd);
    }
    lhs
}
fn read_or(lexer: &mut Lexer) -> AST {
    let mut lhs = read_xor(lexer);
    while lexer.skip("|") {
        let rhs = read_xor(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Or);
    }
    lhs
}
fn read_xor(lexer: &mut Lexer) -> AST {
    let mut lhs = read_and(lexer);
    while lexer.skip("^") {
        let rhs = read_and(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Xor);
    }
    lhs
}
fn read_and(lexer: &mut Lexer) -> AST {
    let mut lhs = read_eq_ne(lexer);
    while lexer.skip("&") {
        let rhs = read_eq_ne(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::And);
    }
    lhs
}
fn read_eq_ne(lexer: &mut Lexer) -> AST {
    let mut lhs = read_relation(lexer);
    loop {
        if lexer.skip("==") {
            let rhs = read_relation(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Eq);
        } else if lexer.skip("!=") {
            let rhs = read_relation(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Ne);
        } else {
            break;
        }
    }
    lhs
}
fn read_relation(lexer: &mut Lexer) -> AST {
    let mut lhs = read_shl_shr(lexer);
    loop {
        if lexer.skip("<") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Lt);
        } else if lexer.skip("<=") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Le);
        } else if lexer.skip(">") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Gt);
        } else if lexer.skip(">=") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Ge);
        } else {
            break;
        }
    }
    lhs
}
fn read_shl_shr(lexer: &mut Lexer) -> AST {
    let mut lhs = read_add_sub(lexer);
    loop {
        if lexer.skip("<<") {
            let rhs = read_add_sub(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Shl);
        } else if lexer.skip(">>") {
            let rhs = read_add_sub(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Shr);
        } else {
            break;
        }
    }
    lhs
}
fn read_add_sub(lexer: &mut Lexer) -> AST {
    let mut lhs = read_mul_div_rem(lexer);
    loop {
        if lexer.skip("+") {
            let rhs = read_mul_div_rem(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Add);
        } else if lexer.skip("-") {
            let rhs = read_mul_div_rem(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Sub);
        } else {
            break;
        }
    }
    lhs
}
fn read_mul_div_rem(lexer: &mut Lexer) -> AST {
    let mut lhs = read_cast(lexer);
    loop {
        if lexer.skip("*") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Mul);
        } else if lexer.skip("/") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Div);
        } else if lexer.skip("%") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Rem);
        } else {
            break;
        }
    }
    lhs
}
fn read_cast(lexer: &mut Lexer) -> AST {
    read_unary(lexer)
}
fn read_unary(lexer: &mut Lexer) -> AST {
    let tok = lexer
        .get()
        .or_else(|| error::error_exit(lexer.cur_line, "expected unary op"))
        .unwrap();
    if tok.kind == TokenKind::Symbol {
        match tok.val.as_str() {
            "!" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::LNot),
            "~" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::BNot),
            "+" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Plus),
            "-" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Minus),
            "++" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Inc),
            "--" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Dec),
            "*" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Indir),
            "&" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Addr),
            _ => {}
        }
    }
    lexer.unget(tok);
    read_postfix(lexer)
}
fn read_postfix(lexer: &mut Lexer) -> AST {
    read_primary(lexer)
}

fn read_primary(lexer: &mut Lexer) -> AST {
    let tok = lexer
        .get()
        .or_else(|| error::error_exit(lexer.cur_line, "expected primary"))
        .unwrap();
    match tok.kind {
        // TokenKind::Identifier => None,
        TokenKind::IntNumber => {
            let a = tok.val.clone();
            if a.len() > 2 && a.chars().nth(1).unwrap() == 'x' {
                AST::Int(u32::from_str_radix(&a[2..], 16).unwrap() as i32)
            } else {
                let mut n = 0;
                for c in a.chars() {
                    match c {
                        '0'...'9' => n = n * 10 + c.to_digit(10).unwrap() as i32,
                        _ => {} // TODO: suffix
                    }
                }
                AST::Int(n)
            }
        }
        // TokenKind::FloatNumber => None,
        // TokenKind::String => None,
        // TokenKind::Char => None,
        TokenKind::Symbol => {
            match tok.val.as_str() {
                "(" => {
                    let expr = read_expr(lexer);
                    lexer.skip(")");
                    expr
                }
                _ => {
                    error::error_exit(lexer.cur_line,
                                      format!("read_primary unknown symbol '{}'", tok.val.as_str())
                                          .as_str())
                }
            }
        }
        // TokenKind::Newline => None,
        _ => {
            error::error_exit(lexer.cur_line,
                              format!("read_primary unknown token {:?}", tok.kind).as_str())
        }
    }
}
////////// operators end here
<commit_msg>Fix typo<commit_after>use lexer;
use lexer::{Lexer, Token, TokenKind};
use node::AST;
use node;
use error;
use types::Type;

use std::fs::OpenOptions;
use std::io::prelude::*;
use std::{str, u32};
use std::rc::Rc;

pub fn run_file(filename: String) -> Vec<AST> {
    let mut nodes: Vec<AST> = Vec::new();
    let mut file = OpenOptions::new()
        .read(true)
        .open(filename.to_string())
        .unwrap();
    let mut s = String::new();
    file.read_to_string(&mut s);
    let mut lexer = Lexer::new(filename.to_string(), s.as_str());
    loop {
        let tok = lexer.get();
        match tok {
            Some(t) => {
                // if t.kind == TokenKind::Newline {
                //     println!();
                // } else {
                println!("t:{}{}", if t.space { " " } else { "" }, t.val);
                // }
            }
            None => break,
        }
    }

    // lexer = Lexer::new(filename.to_string(), s.as_str());
    // nodes.push(read_toplevel(&mut lexer));
    // nodes.pop().unwrap().show();

    nodes
}

pub fn run(input: String) -> Vec<AST> {
    let mut nodes: Vec<AST> = Vec::new();
    let mut lexer = Lexer::new("__input__".to_string(), input.as_str());

    nodes.push(read_toplevel(&mut lexer));

    nodes
}

fn read_toplevel(lexer: &mut Lexer) -> AST {
    if is_function_def(lexer) {
        println!("this is function");
        read_func_def(lexer)
    } else {
        read_expr(lexer)
    }
}

fn read_func_def(lexer: &mut Lexer) -> AST {
    AST::Int(0)
}

fn is_function_def(lexer: &mut Lexer) -> bool {
    let mut buf: Vec<Token> = Vec::new();
    let mut is_funcdef = false;

    loop {
        let mut tok = lexer.get().unwrap();
        buf.push(tok.clone());

        if is_type(&tok) {
            continue;
        }

        if tok.val == "(" {
            skip_brackets(lexer, &mut buf);
            continue;
        }

        if tok.kind != TokenKind::Identifier {
            continue;
        }

        if tok.val == "(" {
            continue;
        }

        skip_brackets(lexer, &mut buf);

        tok = lexer.peek().unwrap();
        is_funcdef = tok.val.as_str() == "{";
        break;
    }

    lexer.unget_all(buf);
    is_funcdef
}

fn skip_brackets(lexer: &mut Lexer, buf: &mut Vec<Token>) {
    loop {
        let tok = lexer.get().unwrap();
        buf.push(tok.clone());

        match tok.val.as_str() {
            "(" => skip_brackets(lexer, buf),
            ")" => break,
            _ => {}
        }
    }
}

fn is_type(token: &Token) -> bool {
    if token.kind != TokenKind::Identifier {
        return true;
    }
    match token.val.as_str() {
        "int" => true,
        _ => false,
    }
}

fn read_decl(lexer: &mut Lexer) -> AST {
    let basety = read_type_spec(lexer);
    AST::Int(0)
}

fn read_type_spec(lexer: &mut Lexer) -> Type {
    enum Sign {
        Signed,
        Unsigned,
    };
    enum Size {
        Short,
        Normal,
        Long,
        LLong,
    };
    let sign: Sign = Sign::Signed;
    let size: Size = Size::Normal;

    loop {
        let tok = lexer
            .get()
            .or_else(|| error::error_exit(lexer.cur_line, "expect types but reach EOF"))
            .unwrap();

        match tok.val.as_str() {
            "void" => {}
            _ => {}
        }
    }
}

pub fn read_expr(lexer: &mut Lexer) -> AST {
    let lhs = read_comma(lexer);
    lhs
}
////////// operators start from here
fn read_comma(lexer: &mut Lexer) -> AST {
    let mut lhs = read_logor(lexer);
    while lexer.skip(",") {
        let rhs = read_logor(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Comma);
    }
    lhs
}
fn read_logor(lexer: &mut Lexer) -> AST {
    let mut lhs = read_logand(lexer);
    while lexer.skip("||") {
        let rhs = read_logand(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::LOr);
    }
    lhs
}
fn read_logand(lexer: &mut Lexer) -> AST {
    let mut lhs = read_or(lexer);
    while lexer.skip("&&") {
        let rhs = read_or(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::LAnd);
    }
    lhs
}
fn read_or(lexer: &mut Lexer) -> AST {
    let mut lhs = read_xor(lexer);
    while lexer.skip("|") {
        let rhs = read_xor(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Or);
    }
    lhs
}
fn read_xor(lexer: &mut Lexer) -> AST {
    let mut lhs = read_and(lexer);
    while lexer.skip("^") {
        let rhs = read_and(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Xor);
    }
    lhs
}
fn read_and(lexer: &mut Lexer) -> AST {
    let mut lhs = read_eq_ne(lexer);
    while lexer.skip("&") {
        let rhs = read_eq_ne(lexer);
        lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::And);
    }
    lhs
}
fn read_eq_ne(lexer: &mut Lexer) -> AST {
    let mut lhs = read_relation(lexer);
    loop {
        if lexer.skip("==") {
            let rhs = read_relation(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Eq);
        } else if lexer.skip("!=") {
            let rhs = read_relation(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Ne);
        } else {
            break;
        }
    }
    lhs
}
fn read_relation(lexer: &mut Lexer) -> AST {
    let mut lhs = read_shl_shr(lexer);
    loop {
        if lexer.skip("<") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Lt);
        } else if lexer.skip("<=") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Le);
        } else if lexer.skip(">") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Gt);
        } else if lexer.skip(">=") {
            let rhs = read_shl_shr(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Ge);
        } else {
            break;
        }
    }
    lhs
}
fn read_shl_shr(lexer: &mut Lexer) -> AST {
    let mut lhs = read_add_sub(lexer);
    loop {
        if lexer.skip("<<") {
            let rhs = read_add_sub(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Shl);
        } else if lexer.skip(">>") {
            let rhs = read_add_sub(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Shr);
        } else {
            break;
        }
    }
    lhs
}
fn read_add_sub(lexer: &mut Lexer) -> AST {
    let mut lhs = read_mul_div_rem(lexer);
    loop {
        if lexer.skip("+") {
            let rhs = read_mul_div_rem(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Add);
        } else if lexer.skip("-") {
            let rhs = read_mul_div_rem(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Sub);
        } else {
            break;
        }
    }
    lhs
}
fn read_mul_div_rem(lexer: &mut Lexer) -> AST {
    let mut lhs = read_cast(lexer);
    loop {
        if lexer.skip("*") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Mul);
        } else if lexer.skip("/") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Div);
        } else if lexer.skip("%") {
            let rhs = read_cast(lexer);
            lhs = AST::BinaryOp(Rc::new(lhs), Rc::new(rhs), node::CBinOps::Rem);
        } else {
            break;
        }
    }
    lhs
}
fn read_cast(lexer: &mut Lexer) -> AST {
    read_unary(lexer)
}
fn read_unary(lexer: &mut Lexer) -> AST {
    let tok = lexer
        .get()
        .or_else(|| error::error_exit(lexer.cur_line, "expected unary op"))
        .unwrap();
    if tok.kind == TokenKind::Symbol {
        match tok.val.as_str() {
            "!" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::LNot),
            "~" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::BNot),
            "+" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Plus),
            "-" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Minus),
            "++" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Inc),
            "--" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Dec),
            "*" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Indir),
            "&" => return AST::UnaryOp(Rc::new(read_cast(lexer)), node::CUnaryOps::Addr),
            _ => {}
        }
    }
    lexer.unget(tok);
    read_postfix(lexer)
}
fn read_postfix(lexer: &mut Lexer) -> AST {
    read_primary(lexer)
}

fn read_primary(lexer: &mut Lexer) -> AST {
    let tok = lexer
        .get()
        .or_else(|| error::error_exit(lexer.cur_line, "expected primary"))
        .unwrap();
    match tok.kind {
        // TokenKind::Identifier => None,
        TokenKind::IntNumber => {
            let a = tok.val.clone();
            if a.len() > 2 && a.chars().nth(1).unwrap() == 'x' {
                AST::Int(u32::from_str_radix(&a[2..], 16).unwrap() as i32)
            } else {
                let mut n = 0;
                for c in a.chars() {
                    match c {
                        '0'...'9' => n = n * 10 + c.to_digit(10).unwrap() as i32,
                        _ => {} // TODO: suffix
                    }
                }
                AST::Int(n)
            }
        }
        // TokenKind::FloatNumber => None,
        // TokenKind::String => None,
        // TokenKind::Char => None,
        TokenKind::Symbol => {
            match tok.val.as_str() {
                "(" => {
                    let expr = read_expr(lexer);
                    lexer.skip(")");
                    expr
                }
                _ => {
                    error::error_exit(lexer.cur_line,
                                      format!("read_primary unknown symbol '{}'", tok.val.as_str())
                                          .as_str())
                }
            }
        }
        // TokenKind::Newline => None,
        _ => {
            error::error_exit(lexer.cur_line,
                              format!("read_primary unknown token {:?}", tok.kind).as_str())
        }
    }
}
////////// operators end here
<|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/. */

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use protocol::{ActorDescription, JsonPacketStream, Method};
use serde_json::Value;
use std::collections::BTreeMap;
use std::net::TcpStream;

pub struct PerformanceActor {
    name: String,
}

#[derive(Serialize)]
struct PerformanceFeatures {
    withMarkers: bool,
    withMemory: bool,
    withTicks: bool,
    withAllocations: bool,
    withJITOptimizations: bool,
}

#[derive(Serialize)]
struct PerformanceTraits {
    features: PerformanceFeatures,
}

#[derive(Serialize)]
struct ConnectReply {
    from: String,
    traits: PerformanceTraits,
}

impl Actor for PerformanceActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      _registry: &ActorRegistry,
                      msg_type: &str,
                      _msg: &BTreeMap<String, Value>,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "connect" => {
                let msg = ConnectReply {
                    from: self.name(),
                    traits: PerformanceTraits {
                        features: PerformanceFeatures {
                            withMarkers: true,
                            withMemory: true,
                            withTicks: true,
                            withAllocations: true,
                            withJITOptimizations: true,
                        },
                    },
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },
            _ => ActorMessageStatus::Ignored,
        })
    }
}

impl PerformanceActor {
    pub fn new(name: String) -> PerformanceActor {
        PerformanceActor {
            name: name,
        }
    }

    pub fn description() -> ActorDescription {
        ActorDescription {
            category: "actor",
            typeName: "performance",
            methods: vec![],
        }
    }
}
<commit_msg>Implement a dummy canCurrentlyRecord method in performance actor<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/. */

use actor::{Actor, ActorMessageStatus, ActorRegistry};
use protocol::{ActorDescription, JsonPacketStream, Method};
use serde_json::Value;
use std::collections::BTreeMap;
use std::net::TcpStream;

pub struct PerformanceActor {
    name: String,
}

#[derive(Serialize)]
struct PerformanceFeatures {
    withMarkers: bool,
    withMemory: bool,
    withTicks: bool,
    withAllocations: bool,
    withJITOptimizations: bool,
}

#[derive(Serialize)]
struct PerformanceTraits {
    features: PerformanceFeatures,
}

#[derive(Serialize)]
struct ConnectReply {
    from: String,
    traits: PerformanceTraits,
}

#[derive(Serialize)]
struct CanCurrentlyRecordReply {
    from: String,
    value: SuccessMsg,
}

#[derive(Serialize)]
struct SuccessMsg {
    success: bool,
    errors: Vec<Error>,
}

#[derive(Serialize)]
enum Error {}

impl Actor for PerformanceActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      _registry: &ActorRegistry,
                      msg_type: &str,
                      _msg: &BTreeMap<String, Value>,
                      stream: &mut TcpStream) -> Result<ActorMessageStatus, ()> {
        Ok(match msg_type {
            "connect" => {
                let msg = ConnectReply {
                    from: self.name(),
                    traits: PerformanceTraits {
                        features: PerformanceFeatures {
                            withMarkers: true,
                            withMemory: true,
                            withTicks: true,
                            withAllocations: true,
                            withJITOptimizations: true,
                        },
                    },
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            },
            "canCurrentlyRecord" => {
                let msg = CanCurrentlyRecordReply {
                    from: self.name(),
                    value: SuccessMsg {
                        success: true,
                        errors: vec![],
                    }
                };
                stream.write_json_packet(&msg);
                ActorMessageStatus::Processed
            }
            _ => ActorMessageStatus::Ignored,
        })
    }
}

impl PerformanceActor {
    pub fn new(name: String) -> PerformanceActor {
        PerformanceActor {
            name: name,
        }
    }

    pub fn description() -> ActorDescription {
        ActorDescription {
            category: "actor",
            typeName: "performance",
            methods: vec![
                Method {
                    name: "canCurrentlyRecord",
                    request: Value::Object(vec![
                        ("type".to_owned(), Value::String("canCurrentlyRecord".to_owned())),
                    ].into_iter().collect()),
                    response: Value::Object(vec![
                        ("value".to_owned(), Value::Object(vec![
                            ("_retval".to_owned(), Value::String("json".to_owned())),
                        ].into_iter().collect())),
                    ].into_iter().collect()),
                },
            ],
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

static METHODS: &'static [method::Method] =
    &[method::Get, method::Post, method::Post,
      method::Put, method::Delete, method::Head,
      method::Patch];

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>
}

#[derive(Debug)]
/// The error thrown by router if there is no matching route.
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

impl Router {
    /// `new` constructs a new, blank `Router`.
    pub fn new() -> Router { Router { routers: HashMap::new() } }
    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// # use iron::method;
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: Str {
        match self.routers.entry(method) {
            Vacant(entry)   => entry.insert(Recognizer::new()),
            Occupied(entry) => entry.into_mut()
        }.add(glob.as_slice().trim_right_matches('/'),
              Box::new(handler) as Box<Handler>);
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    fn recognize<'a>(&'a self, method: &method::Method, path: &str)
                     -> Option<Match<&'a Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
    }

    fn handle_options(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        // If there is an override, use it.
        if let Some(matched) = self.recognize(&method::Options, path) {
            req.extensions.insert::<Router>(matched.params);
            return matched.handler.handle(req);
        }

        // Else, get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        Ok(res)
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path_string = req.url.path.connect("/");
        let path = path_string.trim_right_matches('/');

        if let method::Options = req.method {
            return self.handle_options(req, path);
        }

        let matched = match self.recognize(&req.method, path) {
            Some(matched) => matched,
            // No match.
            None => return Err(IronError {
                error: Box::new(NoRoute),
                response: Response::with(status::NotFound)
            })
        };

        req.extensions.insert::<Router>(matched.params);
        matched.handler.handle(req)
    }
}

<commit_msg>(fix) Send 301 on trailing slashes and use an error.<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;
use iron::modifiers::Redirect;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>
}

impl Router {
    /// Construct a new, empty `Router`.
    ///
    /// ```
    /// # use router::Router;
    /// let router = Router::new();
    /// ```
    pub fn new() -> Router {
        Router {
            routers: HashMap::new()
        }
    }

    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// # use iron::method;
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: Str {
        match self.routers.entry(method) {
            Vacant(entry)   => entry.insert(Recognizer::new()),
            Occupied(entry) => entry.into_mut()
        }.add(glob.as_slice().trim_right_matches('/'),
              Box::new(handler) as Box<Handler>);
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: Str>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    fn recognize<'a>(&'a self, method: &method::Method, path: &str)
                     -> Option<Match<&'a Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
    }

    fn handle_options(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        static METHODS: &'static [method::Method] =
            &[method::Get, method::Post, method::Post, method::Put,
              method::Delete, method::Head, method::Patch];

        // If there is an override, use it.
        if let Some(matched) = self.recognize(&method::Options, path) {
            req.extensions.insert::<Router>(matched.params);
            return matched.handler.handle(req);
        }

        // Else, get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        Ok(res)
    }

    fn handle_trailing_slash(&self, req: &mut Request) -> IronResult<Response> {
        let mut url_no_trailing_slash = req.url.clone();
        url_no_trailing_slash.path.pop();

        Err(IronError {
            error: Box::new(TrailingSlash),
            response: Response::with(
                (status::MovedPermanently, Redirect(url_no_trailing_slash))
            )
        })
    }

    fn handle_method(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        let matched = match self.recognize(&req.method, path) {
            Some(matched) => matched,
            // No match.
            None => return Err(IronError {
                error: Box::new(NoRoute),
                response: Response::with(status::NotFound)
            })
        };

        req.extensions.insert::<Router>(matched.params);
        matched.handler.handle(req)
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        if req.url.path.len() != 1 && Some(&String::new()) == req.url.path.last() {
            return self.handle_trailing_slash(req);
        }

        // No trailing slash
        let path = req.url.path.connect("/");

        if let method::Options = req.method {
            return self.handle_options(req, &*path);
        }

        self.handle_method(req, &*path)
    }
}

/// The error thrown by router if there is no matching route,
/// it is always accompanied by a NotFound response.
#[derive(Debug)]
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

/// The error thrown by router if the request had a trailing slash,
/// it is always accompanied by a redirect.
#[derive(Debug)]
pub struct TrailingSlash;

impl fmt::Display for TrailingSlash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("The request had a trailing slash.")
    }
}

impl Error for TrailingSlash {
    fn description(&self) -> &str { "Trailing Slash" }
}

<|endoftext|>