<commit_before>use token::Token;
use tokenizer::{Tokenizer, LexerError};
pub use ast::*;

pub struct Parser {
    lexer: Tokenizer,
}

pub type ParseResult<T> = Result<T, ParseError>;

#[derive(PartialEq, Debug)]
pub enum ParseError {
    ExpectedToken(Token),
    UnexpectedToken(Token),
    InvalidStringLiteral,
    SyntaxError(LexerError),
}

impl Parser {
    pub fn new(lexer: Tokenizer) -> Parser {
        Parser {
            lexer: lexer,
        }
    }

    pub fn parse(&mut self) -> ParseResult<Program> {
        let mut statements: Program = Vec::new();

        loop {
            let statement = try!(self.statement());
            if statement.is_none() {
                break;
            }

            let statement = statement.unwrap();
            statements.push(statement);
        }

        Ok(statements)
    }

    fn statement(&mut self) -> ParseResult<Option<Statement>> {
        loop {
            let line = try!(self.line());
            if line.is_none() {
                return Ok(None);
            }

            let line = line.unwrap();
            if line.is_empty() {
                continue;
            }

            return Ok(Some(try!(self.dispatch_statement(line))));
        }
    }

    fn line(&mut self) -> ParseResult<Option<Vec<Token>>> {
        let mut line_tokens: Vec<Token> = Vec::new();

        let mut reached_eof = true;
        for next_token in &mut self.lexer {
            let next_token = try!(
                next_token.map_err(|e| ParseError::SyntaxError(e))
            );

            if next_token == Token::EOL {
                reached_eof = false;
                break;
            }

            line_tokens.push(next_token);
        }

        if reached_eof && line_tokens.is_empty() {
            return Ok(None);
        }

        Ok(Some(line_tokens))
    }

    fn dispatch_statement(&self, statement_tokens: Vec<Token>) -> ParseResult<Statement> {
        assert!(statement_tokens.len() > 0, "Got zero tokens to dispatch");

        let function_parts = self.partition_function(&statement_tokens);

        // Error here is okay and does not need to be propagated yet because
        // it probably just means that this is an expression
        if function_parts.is_err() {
            Ok(Statement::Expression(
                try!(self.expr(&statement_tokens[..]))
            ))
        }
        else {
            let (lhs, rhs) = function_parts.unwrap();

            // partition_function is guarenteed to return non-empty slices
            debug_assert!(!lhs.is_empty() && !rhs.is_empty());

            if lhs[0] == Token::Backslash {
                return self.anonymous_function(lhs, rhs);
            }

            match lhs.len() {
                // only one argument: name = ...
                1 => self.assignment(lhs, rhs),
                // more than one argument: name arg1 ... = ...
                _ => self.named_function(lhs, rhs),
            }
        }
    }

    fn anonymous_function(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        debug_assert!(lhs[0] == Token::Backslash);

        Ok(Statement::AnonymousFunction(try!(self.function(&lhs[1..], rhs))))
    }

    fn named_function(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        let name = lhs[0].clone().unwrap_symbol();

        Ok(Statement::NamedFunction {
            name: name.clone(),
            definition: try!(self.function(&lhs[0..], rhs)),
        })
    }

    fn function(&self, params: &[Token], rhs: &[Token]) -> ParseResult<Function> {
        debug_assert!(params.len() > 0);

        Ok(Function {
            params: params.into_iter().map(|ref sym| (*sym).clone().unwrap_symbol()).collect(),
            body: try!(self.expr(rhs)),
        })
    }

    fn assignment(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        debug_assert!(lhs.len() == 1);

        Ok(Statement::Assignment {
            name: lhs[0].clone().unwrap_symbol(),
            value: try!(self.expr(rhs)),
        })
    }

    fn expr(&self, tokens: &[Token]) -> ParseResult<Expr> {
        let mut result = Expr::new();

        let mut remaining = tokens;
        loop {
            let (item, leftover) = try!(self.expr_item(remaining));
            remaining = leftover;

            result.push(item);

            if remaining.is_empty() {
                break;
            }
        }

        Ok(result)
    }

    fn expr_item<'a>(&self, tokens: &'a [Token]) -> ParseResult<(ExprItem, &'a [Token])> {
        debug_assert!(!tokens.is_empty());

        if tokens[0] == Token::Backslash {
            let (lhs, rhs) = try!(self.partition_function(tokens));

            debug_assert!(lhs[0] == Token::Backslash);

            Ok((
                ExprItem::AnonymousFunction(
                    try!(self.function(&lhs[1..], rhs))
                ),
                &[]
            ))
        }
        else if tokens[0] == Token::ParenOpen {
            let close = tokens.iter().position(|ref t| **t == Token::ParenClose);
            if close.is_none() {
                return Err(ParseError::ExpectedToken(Token::ParenClose));
            }
            let close = close.unwrap();

            Ok((
                ExprItem::Group(
                    try!(self.expr(&tokens[1..close]))
                ),
                &tokens[(close+1)..]
            ))
        }
        else if tokens[0] == Token::StringBoundary {
            // since strings can only be a single word, not a number
            const STRING_VALUE: usize = 1;
            const STRING_END: usize = 2;
            const AFTER_STRING: usize = 3;

            if tokens[STRING_END] != Token::StringBoundary {
                Err(ParseError::ExpectedToken(Token::StringBoundary))
            }
            else if let Token::Symbol(ref value) = tokens[STRING_VALUE] {
                Ok((ExprItem::SingleTerm(
                    Term::StringLiteral(value.clone())
                ), &tokens[AFTER_STRING..]))
            }
            else {
                Err(ParseError::InvalidStringLiteral)
            }
        }
        else {
            Ok((ExprItem::SingleTerm(
                try!(self.simple_term(&tokens[0]))
            ), &tokens[1..]))
        }
    }

    fn simple_term(&self, token: &Token) -> ParseResult<Term> {
        match *token {
            Token::Symbol(ref s) => Ok(Term::Symbol(s.clone())),
            Token::Number(ref n) => Ok(Term::Number(n.clone())),
            _ => Err(ParseError::UnexpectedToken(token.clone())),
        }
    }

    // partitions a function by its Equals token, returning None if no
    // valid function is found
    // Returns (lhs, rhs)
    fn partition_function<'a>(&self, tokens: &'a [Token]) -> ParseResult<(&'a [Token], &'a [Token])> {
        // looking for either assignment or a named function
        // both are a collection of only symbols followed by equals
        let mut equals = None;
        for (i, token) in tokens.iter().enumerate() {
            if *token == Token::Equals && i > 0 {
                equals = Some(i);
                break;
            }
            else if let Token::Symbol(_) = *token {
                // Symbols are good, continue
                continue;
            }
            else if *token == Token::Backslash && i == 0 {
                // Anonymous functions have backslashes,
                // but only in the first position
                continue;
            }
            else {
                // Found something that is not a symbol, cannot be
                // assignment or named function, stop
                return Err(ParseError::UnexpectedToken(token.clone()));
            }
        }

        if equals.is_none() {
            Err(ParseError::ExpectedToken(Token::Equals))
        }
        else {
            let equals = equals.unwrap();

            // The 1 or many assumption being assumed in this
            // is only okay because of the i > 0 above
            debug_assert!(equals > 0);

            Ok((&tokens[..equals], &tokens[(equals+1)..]))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use scanner::Scanner;
    use tokenizer::Tokenizer;

    #[test]
    fn call_function_with_string() {
        test_statement(r#"defineUnit "km/h""#,
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ])
        );
    }

    #[test]
    fn complete_program() {
        let program = r#"
        defineUnit "km/h"

        my_var = 30 km/h
        f x yy = x km/h * 2 + (my_var / -3.5) * (8 ** yy) - 1.3e-3
        print (f 30)

        \q r = q / (r - 3)
        doubleMe = \e = e * 2
        operator INFIX 6 "$$" (\x y = x * y + x)
        "#;

        let syntax_tree: Program = vec![
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ]),
            Statement::Assignment {
                name: "my_var".to_owned(),
                value: vec![
                    ExprItem::SingleTerm(Term::Number(30f64)),
                    ExprItem::SingleTerm(Term::Symbol("km/h".to_owned())),
                ],
            },
            Statement::NamedFunction {
                name: "f".to_owned(),
                definition: Function {
                    params: vec![
                        "x".to_owned(),
                        "yy".to_owned()
                    ],
                    body: vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("x".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("km/h".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(2f64)
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("+".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("my_var".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("/".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(-3.5f64)
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Number(8f64)
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("**".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("yy".to_owned())
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(1.3e-3f64)
                        ),
                    ],
                },
            },
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("print".to_owned())
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("f".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Number(30f64)
                    ),
                ]),
            ]),
            Statement::AnonymousFunction(Function {
                params: vec!["q".to_owned(), "r".to_owned()],
                body: vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("q".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Symbol("/".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("r".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(3f64)
                        ),
                    ]),
                ],
            }),
            Statement::Assignment {
                name: "doubleMe".to_owned(),
                value: vec![
                    ExprItem::AnonymousFunction(Function {
                        params: vec!["e".to_owned()],
                        body: vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("e".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("*".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(2f64)
                            ),
                        ],
                    }),
                ],
            },
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("operator".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Symbol("INFIX".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Number(6f64)
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::StringLiteral("$$".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::AnonymousFunction(
                            Function {
                                params: vec![
                                    "x".to_owned(),
                                    "y".to_owned()
                                ],
                                body: vec![
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("*".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("y".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("+".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                ],
                            },
                        ),
                    ]),
                ]),
            ]),
        ];

        test_program(program, syntax_tree);
    }

    fn test_program(string: &str, expected: Program) {
        let mut parser = parser_for(string);
        let parsed = parser.parse().unwrap();
        assert_eq!(parsed, expected);
    }

    fn test_statement(string: &str, expected: Statement) {
        let mut parser = parser_for(string);
        let parsed = parser.parse().unwrap();
        assert_eq!(parsed[0], expected);
    }

    fn parser_for(string: &str) -> Parser {
        Parser::new(Tokenizer::new(Scanner::from_str(string)))
    }
}

<commit_msg>Further splitting large test into smaller tests<commit_after>use token::Token;
use tokenizer::{Tokenizer, LexerError};
pub use ast::*;

pub struct Parser {
    lexer: Tokenizer,
}

pub type ParseResult<T> = Result<T, ParseError>;

#[derive(PartialEq, Debug)]
pub enum ParseError {
    ExpectedToken(Token),
    UnexpectedToken(Token),
    InvalidStringLiteral,
    SyntaxError(LexerError),
}

impl Parser {
    pub fn new(lexer: Tokenizer) -> Parser {
        Parser {
            lexer: lexer,
        }
    }

    pub fn parse(&mut self) -> ParseResult<Program> {
        let mut statements: Program = Vec::new();

        loop {
            let statement = try!(self.statement());
            if statement.is_none() {
                break;
            }

            let statement = statement.unwrap();
            statements.push(statement);
        }

        Ok(statements)
    }

    fn statement(&mut self) -> ParseResult<Option<Statement>> {
        loop {
            let line = try!(self.line());
            if line.is_none() {
                return Ok(None);
            }

            let line = line.unwrap();
            if line.is_empty() {
                continue;
            }

            return Ok(Some(try!(self.dispatch_statement(line))));
        }
    }

    fn line(&mut self) -> ParseResult<Option<Vec<Token>>> {
        let mut line_tokens: Vec<Token> = Vec::new();

        let mut reached_eof = true;
        for next_token in &mut self.lexer {
            let next_token = try!(
                next_token.map_err(|e| ParseError::SyntaxError(e))
            );

            if next_token == Token::EOL {
                reached_eof = false;
                break;
            }

            line_tokens.push(next_token);
        }

        if reached_eof && line_tokens.is_empty() {
            return Ok(None);
        }

        Ok(Some(line_tokens))
    }

    fn dispatch_statement(&self, statement_tokens: Vec<Token>) -> ParseResult<Statement> {
        assert!(statement_tokens.len() > 0, "Got zero tokens to dispatch");

        let function_parts = self.partition_function(&statement_tokens);

        // Error here is okay and does not need to be propagated yet because
        // it probably just means that this is an expression
        if function_parts.is_err() {
            Ok(Statement::Expression(
                try!(self.expr(&statement_tokens[..]))
            ))
        }
        else {
            let (lhs, rhs) = function_parts.unwrap();

            // partition_function is guarenteed to return non-empty slices
            debug_assert!(!lhs.is_empty() && !rhs.is_empty());

            if lhs[0] == Token::Backslash {
                return self.anonymous_function(lhs, rhs);
            }

            match lhs.len() {
                // only one argument: name = ...
                1 => self.assignment(lhs, rhs),
                // more than one argument: name arg1 ... = ...
                _ => self.named_function(lhs, rhs),
            }
        }
    }

    fn anonymous_function(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        debug_assert!(lhs[0] == Token::Backslash);

        Ok(Statement::AnonymousFunction(try!(self.function(&lhs[1..], rhs))))
    }

    fn named_function(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        let name = lhs[0].clone().unwrap_symbol();

        Ok(Statement::NamedFunction {
            name: name.clone(),
            definition: try!(self.function(&lhs[0..], rhs)),
        })
    }

    fn function(&self, params: &[Token], rhs: &[Token]) -> ParseResult<Function> {
        debug_assert!(params.len() > 0);

        Ok(Function {
            params: params.into_iter().map(|ref sym| (*sym).clone().unwrap_symbol()).collect(),
            body: try!(self.expr(rhs)),
        })
    }

    fn assignment(&self, lhs: &[Token], rhs: &[Token]) -> ParseResult<Statement> {
        debug_assert!(lhs.len() == 1);

        Ok(Statement::Assignment {
            name: lhs[0].clone().unwrap_symbol(),
            value: try!(self.expr(rhs)),
        })
    }

    fn expr(&self, tokens: &[Token]) -> ParseResult<Expr> {
        let mut result = Expr::new();

        let mut remaining = tokens;
        loop {
            let (item, leftover) = try!(self.expr_item(remaining));
            remaining = leftover;

            result.push(item);

            if remaining.is_empty() {
                break;
            }
        }

        Ok(result)
    }

    fn expr_item<'a>(&self, tokens: &'a [Token]) -> ParseResult<(ExprItem, &'a [Token])> {
        debug_assert!(!tokens.is_empty());

        if tokens[0] == Token::Backslash {
            let (lhs, rhs) = try!(self.partition_function(tokens));

            debug_assert!(lhs[0] == Token::Backslash);

            Ok((
                ExprItem::AnonymousFunction(
                    try!(self.function(&lhs[1..], rhs))
                ),
                &[]
            ))
        }
        else if tokens[0] == Token::ParenOpen {
            let close = tokens.iter().position(|ref t| **t == Token::ParenClose);
            if close.is_none() {
                return Err(ParseError::ExpectedToken(Token::ParenClose));
            }
            let close = close.unwrap();

            Ok((
                ExprItem::Group(
                    try!(self.expr(&tokens[1..close]))
                ),
                &tokens[(close+1)..]
            ))
        }
        else if tokens[0] == Token::StringBoundary {
            // since strings can only be a single word, not a number
            const STRING_VALUE: usize = 1;
            const STRING_END: usize = 2;
            const AFTER_STRING: usize = 3;

            if tokens[STRING_END] != Token::StringBoundary {
                Err(ParseError::ExpectedToken(Token::StringBoundary))
            }
            else if let Token::Symbol(ref value) = tokens[STRING_VALUE] {
                Ok((ExprItem::SingleTerm(
                    Term::StringLiteral(value.clone())
                ), &tokens[AFTER_STRING..]))
            }
            else {
                Err(ParseError::InvalidStringLiteral)
            }
        }
        else {
            Ok((ExprItem::SingleTerm(
                try!(self.simple_term(&tokens[0]))
            ), &tokens[1..]))
        }
    }

    fn simple_term(&self, token: &Token) -> ParseResult<Term> {
        match *token {
            Token::Symbol(ref s) => Ok(Term::Symbol(s.clone())),
            Token::Number(ref n) => Ok(Term::Number(n.clone())),
            _ => Err(ParseError::UnexpectedToken(token.clone())),
        }
    }

    // partitions a function by its Equals token, returning None if no
    // valid function is found
    // Returns (lhs, rhs)
    fn partition_function<'a>(&self, tokens: &'a [Token]) -> ParseResult<(&'a [Token], &'a [Token])> {
        // looking for either assignment or a named function
        // both are a collection of only symbols followed by equals
        let mut equals = None;
        for (i, token) in tokens.iter().enumerate() {
            if *token == Token::Equals && i > 0 {
                equals = Some(i);
                break;
            }
            else if let Token::Symbol(_) = *token {
                // Symbols are good, continue
                continue;
            }
            else if *token == Token::Backslash && i == 0 {
                // Anonymous functions have backslashes,
                // but only in the first position
                continue;
            }
            else {
                // Found something that is not a symbol, cannot be
                // assignment or named function, stop
                return Err(ParseError::UnexpectedToken(token.clone()));
            }
        }

        if equals.is_none() {
            Err(ParseError::ExpectedToken(Token::Equals))
        }
        else {
            let equals = equals.unwrap();

            // The 1 or many assumption being assumed in this
            // is only okay because of the i > 0 above
            debug_assert!(equals > 0);

            Ok((&tokens[..equals], &tokens[(equals+1)..]))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use scanner::Scanner;
    use tokenizer::Tokenizer;

    #[test]
    fn call_function_with_string() {
        test_statement(r#"defineUnit "km/h""#,
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ])
        );
    }

    #[test]
    fn define_simple_variable() {
        test_statement(r"my_var = 30 km/h",
            Statement::Assignment {
                name: "my_var".to_owned(),
                value: vec![
                    ExprItem::SingleTerm(Term::Number(30f64)),
                    ExprItem::SingleTerm(Term::Symbol("km/h".to_owned())),
                ],
            },
        );
    }

    #[test]
    fn named_function_complex_expression() {
        test_statement(r"f x yy = x km/h * 2 + (my_var / -3.5) * (8 ** yy) - 1.3e-3",
            Statement::NamedFunction {
                name: "f".to_owned(),
                definition: Function {
                    params: vec![
                        "x".to_owned(),
                        "yy".to_owned()
                    ],
                    body: vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("x".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("km/h".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(2f64)
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("+".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("my_var".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("/".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(-3.5f64)
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Number(8f64)
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("**".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("yy".to_owned())
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(1.3e-3f64)
                        ),
                    ],
                },
            },
        );
    }

    #[test]
    fn complete_program() {
        let program = r#"
        defineUnit "km/h"

        my_var = 30 km/h
        f x yy = x km/h * 2 + (my_var / -3.5) * (8 ** yy) - 1.3e-3
        print (f 30)

        \q r = q / (r - 3)
        doubleMe = \e = e * 2
        operator INFIX 6 "$$" (\x y = x * y + x)
        "#;

        let syntax_tree: Program = vec![
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ]),

            Statement::Assignment {
                name: "my_var".to_owned(),
                value: vec![
                    ExprItem::SingleTerm(Term::Number(30f64)),
                    ExprItem::SingleTerm(Term::Symbol("km/h".to_owned())),
                ],
            },

            Statement::NamedFunction {
                name: "f".to_owned(),
                definition: Function {
                    params: vec![
                        "x".to_owned(),
                        "yy".to_owned()
                    ],
                    body: vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("x".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("km/h".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(2f64)
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("+".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("my_var".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("/".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(-3.5f64)
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Number(8f64)
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("**".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("yy".to_owned())
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(1.3e-3f64)
                        ),
                    ],
                },
            },

            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("print".to_owned())
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("f".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Number(30f64)
                    ),
                ]),
            ]),

            Statement::AnonymousFunction(Function {
                params: vec!["q".to_owned(), "r".to_owned()],
                body: vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("q".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Symbol("/".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("r".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(3f64)
                        ),
                    ]),
                ],
            }),

            Statement::Assignment {
                name: "doubleMe".to_owned(),
                value: vec![
                    ExprItem::AnonymousFunction(Function {
                        params: vec!["e".to_owned()],
                        body: vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("e".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("*".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(2f64)
                            ),
                        ],
                    }),
                ],
            },

            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("operator".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Symbol("INFIX".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Number(6f64)
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::StringLiteral("$$".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::AnonymousFunction(
                            Function {
                                params: vec![
                                    "x".to_owned(),
                                    "y".to_owned()
                                ],
                                body: vec![
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("*".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("y".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("+".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                ],
                            },
                        ),
                    ]),
                ]),
            ]),
        ];

        test_program(program, syntax_tree);
    }

    fn test_program(string: &str, expected: Program) {
        let mut parser = parser_for(string);
        let parsed = parser.parse().unwrap();
        assert_eq!(parsed, expected);
    }

    fn test_statement(string: &str, expected: Statement) {
        let mut parser = parser_for(string);
        let parsed = parser.parse().unwrap();
        assert_eq!(parsed[0], expected);
    }

    fn parser_for(string: &str) -> Parser {
        Parser::new(Tokenizer::new(Scanner::from_str(string)))
    }
}

<|endoftext|>


<commit_before>//! A parser for lambda expressions

use term::*;
use self::Token::*;
use self::CToken::*;
use self::Error::*;
use self::Expression::*;
pub use term::Notation::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// an invalid character was encountered
    InvalidCharacter((usize, char)),
    /// the expression is invalid
    InvalidExpression,
    /// the expression is empty
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    /// λ or \
    Lambda,
    /// left parenthesis
    Lparen,
    /// right parenthesis
    Rparen,
    /// a number
    Number(usize)
}

#[derive(Debug, PartialEq)]
enum CToken {
    /// an abstraction with a bound variable
    CLambda(String),
    /// left parenthesis
    CLparen,
    /// right parenthesis
    CRparen,
    /// a variable with an identifier
    CName(String)
}

fn tokenize_dbr(input: &str) -> Result<Vec<Token>, Error> {
    let chars = input.chars().enumerate();
    let mut tokens = Vec::new();

    for (i, c) in chars {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             _  => {
                if let Some(n) = c.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if c.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((i + 1, c)))
                }
            }
        }
    }

    Ok(tokens)
}

fn tokenize_cla(input: &str) -> Result<Vec<CToken>, Error> {
    let mut chars = input.chars().enumerate().peekable();
    let mut tokens = Vec::new();
    let valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    while let Some((i, c)) = chars.next() {
        match c {
            '\\' | 'λ' => {
                let mut name = String::new();
                while let Some((i, c)) = chars.next() {
                    if c == '.' {
                        break
                    } else if valid_chars.contains(c) {
                        name.push(c)
                    } else {
                        return Err(InvalidCharacter((i + 1, c)))
                    }
                }
                tokens.push(CLambda(name))
            },
            '(' => { tokens.push(CLparen) },
            ')' => { tokens.push(CRparen) },
             _  => {
                if c.is_whitespace() {
                    ()
                } else if valid_chars.contains(c) {
                    let mut name = c.to_string();
                    while let Some(&(_, c)) = chars.peek() {
                        if c.is_whitespace() || c == '(' || c == ')' {
                            break
                        } else {
                            name.push(c);
                            chars.next();
                        }
                    }
                    tokens.push(CName(name))
                } else {
                    return Err(InvalidCharacter((i + 1, c)))
                }
            }
        }
    }

    Ok(tokens)
}

fn convert_classic_tokens(tokens: &[CToken]) -> Vec<Token> {
    _convert_classic_tokens(tokens, &mut Vec::new(), &mut 0)
}

fn _convert_classic_tokens(tokens: &[CToken], stack: &mut Vec<String>, pos: &mut usize) -> Vec<Token>
{
    let mut output = Vec::with_capacity(tokens[*pos..].len());
    let mut inner_stack_count = 0;

    while *pos < tokens.len() {
        match tokens[*pos] {
            CLambda(ref name) => {
                output.push(Lambda);
                stack.push(name.clone());
                inner_stack_count += 1;
            },
            CLparen => {
                output.push(Lparen);
                *pos += 1;
                output.append(&mut _convert_classic_tokens(tokens, stack, pos));
            },
            CRparen => {
                output.push(Rparen);
                for _ in 0..inner_stack_count { stack.pop(); }
                return output
            },
            CName(ref name) => {
                if let Some(index) = stack.iter().rev().position(|t| t == name) {
                    output.push(Number(index + 1))
                } else {
                    output.push(Number(stack.len() + 1))
                }
            }
        }
        *pos += 1;
    }

    output
}

#[derive(Debug, PartialEq)]
enum Expression {
    /// an abstraction
    Abstraction,
    /// a sequence of Expressions
    Sequence(Vec<Expression>),
    /// a variable with a De Bruijn index
    Variable(usize)
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    _get_ast(tokens, &mut 0)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

/// Parses the input `&str` as a lambda `Term`.
///
/// - lambdas can be represented either with the greek letter (λ) or a backslash (\\ -
/// less aesthetic, but only one byte in size)
/// - the identifiers in `Classic` mode are `String`s of ASCII alphabetic characters
/// - `Classic` mode ignores whitespaces where unambiguous
/// - `DeBruijn` mode ignores all whitespaces (since indices > 15 are very unlikely)
/// - the indices in the `DeBruijn` notation mode start with 1 and are hexadecimal digits
///
/// # Example
/// ```
/// use lambda_calculus::parser::*;
/// use lambda_calculus::church::numerals::{succ, pred};
///
/// assert_eq!(parse(&"λn. λf. λx. n (λg. λh. h (g f)) (λu. x) (λu. u)", Classic), Ok(pred()));
/// assert_eq!(parse(&"λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u)", Classic), Ok(pred()));
///
/// assert_eq!(parse(  &"λλλ2(321)",  DeBruijn), Ok(succ()));
/// assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), Ok(succ()));
/// ```
pub fn parse(input: &str, notation: Notation) -> Result<Term, Error> {
    let tokens = if notation == DeBruijn {
        try!(tokenize_dbr(input))
    } else {
        convert_classic_tokens(&try!(tokenize_cla(input)))
    };
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    fold_exprs(&exprs)
}

fn fold_exprs(exprs: &[Expression]) -> Result<Term, Error> {
    let iter = exprs.into_iter();
    let mut stack  = Vec::new();
    let mut output = Vec::new();

    for expr in iter {
        match *expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let subexpr = try!(fold_exprs(exprs));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output));

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        let fst = terms.remove(0);
        Ok( terms.into_iter().fold(fst, app) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() ) // safe; ensured above
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize_dbr(&"λλx2"),    Err(InvalidCharacter((3, 'x'))));
        assert_eq!(tokenize_cla(&"λa.λb a"), Err(InvalidCharacter((6, ' '))));
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize_dbr(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn tokenization_success_classic() {
        let blc_dbr = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
            (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        let blc_cla = format!("{}", parse(&blc_dbr, DeBruijn).unwrap());

        let tokens_cla = tokenize_cla(&blc_cla);
        let tokens_dbr = tokenize_dbr(&blc_dbr);

        assert!(tokens_cla.is_ok());
        assert!(tokens_dbr.is_ok());

        assert_eq!(convert_classic_tokens(&tokens_cla.unwrap()), tokens_dbr.unwrap());
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), parse(&"λλλ2(321)", DeBruijn))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize_dbr(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y, DeBruijn).unwrap(),
            abs(
                app(
                    abs(app(Var(2), app(Var(1), Var(1)))),
                    abs(app(Var(2), app(Var(1), Var(1))))
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine, DeBruijn).unwrap(),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc, DeBruijn).unwrap(),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<commit_msg>another fold_exprs() speedup<commit_after>//! A parser for lambda expressions

use term::*;
use self::Token::*;
use self::CToken::*;
use self::Error::*;
use self::Expression::*;
pub use term::Notation::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// an invalid character was encountered
    InvalidCharacter((usize, char)),
    /// the expression is invalid
    InvalidExpression,
    /// the expression is empty
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    /// λ or \
    Lambda,
    /// left parenthesis
    Lparen,
    /// right parenthesis
    Rparen,
    /// a number
    Number(usize)
}

#[derive(Debug, PartialEq)]
enum CToken {
    /// an abstraction with a bound variable
    CLambda(String),
    /// left parenthesis
    CLparen,
    /// right parenthesis
    CRparen,
    /// a variable with an identifier
    CName(String)
}

fn tokenize_dbr(input: &str) -> Result<Vec<Token>, Error> {
    let chars = input.chars().enumerate();
    let mut tokens = Vec::new();

    for (i, c) in chars {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             _  => {
                if let Some(n) = c.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if c.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((i + 1, c)))
                }
            }
        }
    }

    Ok(tokens)
}

fn tokenize_cla(input: &str) -> Result<Vec<CToken>, Error> {
    let mut chars = input.chars().enumerate().peekable();
    let mut tokens = Vec::new();
    let valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    while let Some((i, c)) = chars.next() {
        match c {
            '\\' | 'λ' => {
                let mut name = String::new();
                while let Some((i, c)) = chars.next() {
                    if c == '.' {
                        break
                    } else if valid_chars.contains(c) {
                        name.push(c)
                    } else {
                        return Err(InvalidCharacter((i + 1, c)))
                    }
                }
                tokens.push(CLambda(name))
            },
            '(' => { tokens.push(CLparen) },
            ')' => { tokens.push(CRparen) },
             _  => {
                if c.is_whitespace() {
                    ()
                } else if valid_chars.contains(c) {
                    let mut name = c.to_string();
                    while let Some(&(_, c)) = chars.peek() {
                        if c.is_whitespace() || c == '(' || c == ')' {
                            break
                        } else {
                            name.push(c);
                            chars.next();
                        }
                    }
                    tokens.push(CName(name))
                } else {
                    return Err(InvalidCharacter((i + 1, c)))
                }
            }
        }
    }

    Ok(tokens)
}

fn convert_classic_tokens(tokens: &[CToken]) -> Vec<Token> {
    _convert_classic_tokens(tokens, &mut Vec::new(), &mut 0)
}

fn _convert_classic_tokens(tokens: &[CToken], stack: &mut Vec<String>, pos: &mut usize) -> Vec<Token>
{
    let mut output = Vec::with_capacity(tokens[*pos..].len());
    let mut inner_stack_count = 0;

    while *pos < tokens.len() {
        match tokens[*pos] {
            CLambda(ref name) => {
                output.push(Lambda);
                stack.push(name.clone());
                inner_stack_count += 1;
            },
            CLparen => {
                output.push(Lparen);
                *pos += 1;
                output.append(&mut _convert_classic_tokens(tokens, stack, pos));
            },
            CRparen => {
                output.push(Rparen);
                for _ in 0..inner_stack_count { stack.pop(); }
                return output
            },
            CName(ref name) => {
                if let Some(index) = stack.iter().rev().position(|t| t == name) {
                    output.push(Number(index + 1))
                } else {
                    output.push(Number(stack.len() + 1))
                }
            }
        }
        *pos += 1;
    }

    output
}

#[derive(Debug, PartialEq)]
enum Expression {
    /// an abstraction
    Abstraction,
    /// a sequence of Expressions
    Sequence(Vec<Expression>),
    /// a variable with a De Bruijn index
    Variable(usize)
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    _get_ast(tokens, &mut 0)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

/// Parses the input `&str` as a lambda `Term`.
///
/// - lambdas can be represented either with the greek letter (λ) or a backslash (\\ -
/// less aesthetic, but only one byte in size)
/// - the identifiers in `Classic` mode are `String`s of ASCII alphabetic characters
/// - `Classic` mode ignores whitespaces where unambiguous
/// - `DeBruijn` mode ignores all whitespaces (since indices > 15 are very unlikely)
/// - the indices in the `DeBruijn` notation mode start with 1 and are hexadecimal digits
///
/// # Example
/// ```
/// use lambda_calculus::parser::*;
/// use lambda_calculus::church::numerals::{succ, pred};
///
/// assert_eq!(parse(&"λn. λf. λx. n (λg. λh. h (g f)) (λu. x) (λu. u)", Classic), Ok(pred()));
/// assert_eq!(parse(&"λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u)", Classic), Ok(pred()));
///
/// assert_eq!(parse(  &"λλλ2(321)",  DeBruijn), Ok(succ()));
/// assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), Ok(succ()));
/// ```
pub fn parse(input: &str, notation: Notation) -> Result<Term, Error> {
    let tokens = if notation == DeBruijn {
        try!(tokenize_dbr(input))
    } else {
        convert_classic_tokens(&try!(tokenize_cla(input)))
    };
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    fold_exprs(&exprs)
}

fn fold_exprs(exprs: &[Expression]) -> Result<Term, Error> {
    let mut depth  = 0;
    let mut output = Vec::new();

    for expr in exprs.iter() {
        match *expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => depth += 1,
            Sequence(ref exprs) => {
                let subexpr = try!(fold_exprs(exprs));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output));

    for _ in 0..depth {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        let fst = terms.remove(0);
        Ok( terms.into_iter().fold(fst, app) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() ) // safe; ensured above
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize_dbr(&"λλx2"),    Err(InvalidCharacter((3, 'x'))));
        assert_eq!(tokenize_cla(&"λa.λb a"), Err(InvalidCharacter((6, ' '))));
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize_dbr(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn tokenization_success_classic() {
        let blc_dbr = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
            (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        let blc_cla = format!("{}", parse(&blc_dbr, DeBruijn).unwrap());

        let tokens_cla = tokenize_cla(&blc_cla);
        let tokens_dbr = tokenize_dbr(&blc_dbr);

        assert!(tokens_cla.is_ok());
        assert!(tokens_dbr.is_ok());

        assert_eq!(convert_classic_tokens(&tokens_cla.unwrap()), tokens_dbr.unwrap());
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&r#"\\\2(321)"#, DeBruijn), parse(&"λλλ2(321)", DeBruijn))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize_dbr(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y, DeBruijn).unwrap(),
            abs(
                app(
                    abs(app(Var(2), app(Var(1), Var(1)))),
                    abs(app(Var(2), app(Var(1), Var(1))))
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine, DeBruijn).unwrap(),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc, DeBruijn).unwrap(),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Tink-Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use prost::Message;
use std::sync::Arc;

// TODO: re-enable when real primitives registered
#[test]
#[ignore]
fn test_register_key_manager() {
    // get HMACKeyManager
    tink::registry::get_key_manager(tink_testutil::HMAC_TYPE_URL).unwrap();
    // get AESGCMKeyManager
    tink::registry::get_key_manager(tink_testutil::AES_GCM_TYPE_URL).unwrap();
    // some random typeurl
    assert!(
        tink::registry::get_key_manager("some url").is_err(),
        "expect an error when a type url doesn't exist in the registry"
    );
}

/* TODO: enable when tink-aead crate is available.
#[test]
#[ignore]
fn test_register_key_manager_with_collision() {
    tink_aead::init();
    // dummy_key_manager's type_url is equal to that of AES-GCM by default.
    let dummy_key_manager = Arc::new(tink_testutil::DummyAeadKeyManager::default());
    // This should fail because overwriting is disallowed.
    assert!(
        tink::registry::register_key_manager(dummy_key_manager).is_err(),
        "AES_GCM_TYPE_URL shouldn't be registered again",
    );
}
*/

#[test]
fn test_register_key_manager_duplicate() {
    let dummy_key_manager = Arc::new(tink_testutil::DummyAeadKeyManager {
        type_url: "blah".to_string(),
    });
    tink::registry::register_key_manager(dummy_key_manager.clone()).unwrap();

    // This should fail because overwriting is disallowed.
    assert!(
        tink::registry::register_key_manager(dummy_key_manager).is_err(),
        "Shouldn't allow double registration",
    );
}

/* TODO: need tink_mac crate
#[test]
fn test_new_key_data() {
    tink_mac::init();
    // new KeyData from a Hmac KeyTemplate
    let key_data =
        tink::registry::new_key_data(&tink_mac::hmac_sha256_tag128_key_template()).unwrap();
    assert_eq!(
        tink_testutil::HMAC_TYPE_URL,
        key_data.type_url,
        "invalid key data"
    );
    let _key = tink::proto::HmacKey::decode(key_data.value.as_ref())
        .expect("unexpected error when unmarshal HmacKey");

    // unregistered type url
    let template = tink::proto::KeyTemplate {
        type_url: "some url".to_string(),
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        value: vec![0],
    };
    assert!(
        tink::registry::new_key_data(&template).is_err(),
        "expect an error when key template contains unregistered type_url"
    );
}
*/

/* TODO: enable when tink-aead crate is available.
#[test]
fn test_new_key() {
    tink_aead::init();
    // aead template
    let aes_gcm_template = tink_aead::aes128_gcm_key_template();
    let key = tink::registry::new_key(aes_gcm_template).unwrap();

    let aes_gcm_key: tink::proto::AesGcmKey = key;

    let aes_gcm_format =
        tink::proto::AesGcmKeyFormat::decode(aes_gcm_template.value.as_ref()).unwrap();
    assert_eq!(
        aes_gcm_key.key_value.len(),
        aes_gcm_format.key_size as usize
    );

    // unregistered type url
    let template = tink::proto::KeyTemplate {
        type_url: "some url".to_string(),
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        value: vec![0],
    };
    assert!(
        tink::registry::new_key(&template).is_err(),
        "expect an error when key template is not registered"
    );
}
*/

#[test]
fn test_primitive_from_key_data() {
    // hmac keydata
    let mut key_data = tink_testutil::new_hmac_key_data(tink::proto::HashType::Sha256, 16);
    let _p = tink::registry::primitive_from_key_data(&key_data);

    /* TODO: need real hmac registration
    let p = p.unwrap();
    use std::any::Any;
    assert_eq!(std::any::TypeId::of::<tink_hmac::subtle::HMAC>(), p.type_id());
    */

    // unregistered url
    key_data.type_url = "some url".to_string();
    assert!(
        tink::registry::primitive_from_key_data(&key_data).is_err(),
        "expect an error when type_url has not been registered"
    );
    // unmatched url
    key_data.type_url = tink_testutil::AES_GCM_TYPE_URL.to_string();
    assert!(
        tink::registry::primitive_from_key_data(&key_data).is_err(),
        "expect an error when type_url doesn't match key"
    );
}

#[test]
fn test_primitive() {
    // hmac key
    let key = tink_testutil::new_hmac_key(tink::proto::HashType::Sha256, 16);
    let mut serialized_key = vec![];
    key.encode(&mut serialized_key).unwrap();
    let _p = tink::registry::primitive(tink_testutil::HMAC_TYPE_URL, &serialized_key);

    /* TODO: need real hmac registration
    let p = p.unwrap();
    use std::any::Any;
    assert_eq!(std::any::TypeId::of::<tink_hmac::subtle::HMAC>(), p.type_id());
     */

    // unregistered url
    assert!(
        tink::registry::primitive("some url", &serialized_key).is_err(),
        "expect an error when type_url has not been registered"
    );
    // unmatched url
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &serialized_key).is_err(),
        "expect an error when type_url doesn't match key"
    );
    // empty key
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &[]).is_err(),
        "expect an error when key is empty"
    );
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &[0]).is_err(),
        "expect an error when key is short"
    );
}

#[test]
fn test_register_kms_client() {
    let kms = tink_testutil::DummyKmsClient {};
    tink::registry::register_kms_client(kms);

    tink::registry::get_kms_client("dummy").expect("error fetching dummy kms client");
}
<commit_msg>Enable registry tests now tink-mac available<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use prost::Message;
use std::sync::Arc;

#[test]
fn test_register_key_manager() {
    tink_mac::init();
    // get HMACKeyManager
    tink::registry::get_key_manager(tink_testutil::HMAC_TYPE_URL).unwrap();
    /* TODO: enable when tink-aead crate is available.
        // get AESGCMKeyManager
        tink::registry::get_key_manager(tink_testutil::AES_GCM_TYPE_URL).unwrap();
    */
    // some random typeurl
    assert!(
        tink::registry::get_key_manager("some url").is_err(),
        "expect an error when a type url doesn't exist in the registry"
    );
}

/* TODO: enable when tink-aead crate is available.
#[test]
#[ignore]
fn test_register_key_manager_with_collision() {
    tink_aead::init();
    // dummy_key_manager's type_url is equal to that of AES-GCM by default.
    let dummy_key_manager = Arc::new(tink_testutil::DummyAeadKeyManager::default());
    // This should fail because overwriting is disallowed.
    assert!(
        tink::registry::register_key_manager(dummy_key_manager).is_err(),
        "AES_GCM_TYPE_URL shouldn't be registered again",
    );
}
*/

#[test]
fn test_register_key_manager_duplicate() {
    let dummy_key_manager = Arc::new(tink_testutil::DummyAeadKeyManager {
        type_url: "blah".to_string(),
    });
    tink::registry::register_key_manager(dummy_key_manager.clone()).unwrap();

    // This should fail because overwriting is disallowed.
    assert!(
        tink::registry::register_key_manager(dummy_key_manager).is_err(),
        "Shouldn't allow double registration",
    );
}

#[test]
fn test_new_key_data() {
    tink_mac::init();
    // new KeyData from a Hmac KeyTemplate
    let key_data =
        tink::registry::new_key_data(&tink_mac::hmac_sha256_tag128_key_template()).unwrap();
    assert_eq!(
        tink_testutil::HMAC_TYPE_URL,
        key_data.type_url,
        "invalid key data"
    );
    let _key = tink::proto::HmacKey::decode(key_data.value.as_ref())
        .expect("unexpected error when unmarshal HmacKey");

    // unregistered type url
    let template = tink::proto::KeyTemplate {
        type_url: "some url".to_string(),
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        value: vec![0],
    };
    assert!(
        tink::registry::new_key_data(&template).is_err(),
        "expect an error when key template contains unregistered type_url"
    );
}

/* TODO: enable when tink-aead crate is available.
#[test]
fn test_new_key() {
    tink_aead::init();
    // aead template
    let aes_gcm_template = tink_aead::aes128_gcm_key_template();
    let key = tink::registry::new_key(aes_gcm_template).unwrap();

    let aes_gcm_key: tink::proto::AesGcmKey = key;

    let aes_gcm_format =
        tink::proto::AesGcmKeyFormat::decode(aes_gcm_template.value.as_ref()).unwrap();
    assert_eq!(
        aes_gcm_key.key_value.len(),
        aes_gcm_format.key_size as usize
    );

    // unregistered type url
    let template = tink::proto::KeyTemplate {
        type_url: "some url".to_string(),
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        value: vec![0],
    };
    assert!(
        tink::registry::new_key(&template).is_err(),
        "expect an error when key template is not registered"
    );
}
*/

#[test]
fn test_primitive_from_key_data() {
    tink_mac::init();
    // hmac keydata
    let mut key_data = tink_testutil::new_hmac_key_data(tink::proto::HashType::Sha256, 16);
    let p = tink::registry::primitive_from_key_data(&key_data).unwrap();
    if let tink::Primitive::Mac(_) = p {
    } else {
        panic!("Primitive not a Mac");
    }

    // unregistered url
    key_data.type_url = "some url".to_string();
    assert!(
        tink::registry::primitive_from_key_data(&key_data).is_err(),
        "expect an error when type_url has not been registered"
    );
    // unmatched url
    key_data.type_url = tink_testutil::AES_GCM_TYPE_URL.to_string();
    assert!(
        tink::registry::primitive_from_key_data(&key_data).is_err(),
        "expect an error when type_url doesn't match key"
    );
}

#[test]
fn test_primitive() {
    tink_mac::init();
    // hmac key
    let key = tink_testutil::new_hmac_key(tink::proto::HashType::Sha256, 16);
    let mut serialized_key = vec![];
    key.encode(&mut serialized_key).unwrap();
    let p = tink::registry::primitive(tink_testutil::HMAC_TYPE_URL, &serialized_key).unwrap();
    if let tink::Primitive::Mac(_) = p {
    } else {
        panic!("Primitive not a Mac");
    }

    // unregistered url
    assert!(
        tink::registry::primitive("some url", &serialized_key).is_err(),
        "expect an error when type_url has not been registered"
    );
    // unmatched url
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &serialized_key).is_err(),
        "expect an error when type_url doesn't match key"
    );
    // empty key
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &[]).is_err(),
        "expect an error when key is empty"
    );
    assert!(
        tink::registry::primitive(tink_testutil::AES_GCM_TYPE_URL, &[0]).is_err(),
        "expect an error when key is short"
    );
}

#[test]
fn test_register_kms_client() {
    let kms = tink_testutil::DummyKmsClient {};
    tink::registry::register_kms_client(kms);

    tink::registry::get_kms_client("dummy").expect("error fetching dummy kms client");
}
<|endoftext|>


<commit_before>use std::vec::Vec;

pub mod errors;
pub use self::errors::{Result, Error};

use proto::metapb;

// Client to communicate with placement driver (pd).
pub trait Client {
    // Bootstrap the cluster with cluster ID, if the cluster is
    // already bootstrapped, return ClusterBootstrapped error.
    // We must first bootstrap the cluster and then use it.
    // So at first, we start a node with "--bootstrap" flag,
    // bootstraps the node with node 1, store 1 and peer 1 for
    // region 1, and then call bootstrap_cluster to
    // let pd know that a node has already bootstrap the cluster.
    // TODO: how about bootstrap_cluster OK, but the node can't
    // run successfully later?
    fn bootstrap_cluster(cluster_id: u64) -> Result<()>;

    // Return whether the cluster is bootstrapped or not.
    // We must use the cluster after bootstrapped, so when the
    // node starts, it must check it with is_cluster_bootstrapped,
    // and panic if not bootstrapped.
    fn is_cluster_bootstrapped(cluster_id: u64) -> Result<bool>;

    // Allocate a node id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use node 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_node_id(cluster_id: u64) -> Result<u64>;

    // Allocate a store id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use store 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_store_id(cluster_id: u64) -> Result<u64>;

    // Allocate a peer id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use peer 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_peer_id(cluster_id: u64) -> Result<u64>;

    // Allocate a region id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use region 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_region_id(cluster_id: u64) -> Result<u64>;

    // When the node starts, or some node information changed, it
    // uses put_node to tell pd know it.
    fn put_node(cluster_id: u64, node: metapb::Node) -> Result<()>;

    // When the store starts, or some store information changed, it
    // uses put_store to tell pd know it.
    fn put_store(cluster_id: u64, store: metapb::Store) -> Result<()>;

    // Delete the node from cluster, it is a very dangerous operation
    // and can not be recoverable, all the data belongs to this node
    // will be removed and we can't re-add this node again.
    // Sometimes, the node may crash and restart again, if the node is
    // off-line for a long time, pd will try to do auto-balance and then
    // delete the node.
    fn delete_node(cluster_id: u64, node_id: u64) -> Result<()>;

    // Delete the store from cluster, it is a very dangerous operation
    // and can not be recoverable, all the data belongs to this store
    // will be removed and we can't re-add this store again.
    // If the store is off-line for a long time, pd will try to do
    // auto-balance and then delete the store.
    fn delete_store(cluster_id: u64, store_id: u64) -> Result<()>;

    // Discuss (@ngaut): We don't need to support region and peer put/delete,
    // because pd knows all region and peers itself.
    // When bootstrapping, pd knows region 1 and peer 1 exists in node 1, store 1.
    // When changing peer, pd determines where to add a new peer in some store
    // for this region.
    // When region splitting, pd determines the new region id and peer id for the
    // split region.
    // When region merging, pd knows which two regions will be merged and which region
    // and peers will be removed.
    // When doing auto-balance, pd determines how to move the region from one store to another.

    // Get node address so that we can send message to it.
    fn get_node_addr(cluster_id: u64, node_id: u64) -> Result<String>;

    // For route.
    // Get the region which the key belongs to.
    fn get_region_with_key(cluster_id: u64, key: &[u8]) -> Result<metapb::Region>;

    // For route.
    // Get all regions which the keys belong to.
    fn get_regions_with_keys(cluster_id: u64, keys: Vec<Vec<u8>>) -> Result<Vec<metapb::Region>>;

    // For route.
    // Scan all regions which the region key range is in [start_key, end_key].
    fn scan_regions(cluster_id: u64,
                    start_key: &[u8],
                    end_key: &[u8],
                    limit: usize)
                    -> Result<Vec<metapb::Region>>;
}
<commit_msg>pd: update comment and add self arg.<commit_after>use std::vec::Vec;

pub mod errors;
pub use self::errors::{Result, Error};

use proto::metapb;

// Client to communicate with placement driver (pd).
pub trait Client {
    // Bootstrap the cluster with cluster ID, if the cluster is
    // already bootstrapped, return ClusterBootstrapped error.
    // We must first bootstrap the cluster and then use it.
    // When a node starts, if it finds nothing in the node and
    // cluster is not bootstrapped, it begin to bootstrap
    // itself with node 1, store 1 and peer 1 for region 1,
    // and then call bootstrap_cluster to let pd know it.
    // It may happen that multi nodes start at same time to try to
    // bootstrap, and only one can success, others will fail
    // and must remove their created local data themselves.
    fn bootstrap_cluster(&mut self, cluster_id: u64) -> Result<()>;

    // Return whether the cluster is bootstrapped or not.
    // We must use the cluster after bootstrapped, so when the
    // node starts, it must check it with is_cluster_bootstrapped,
    // and panic if not bootstrapped.
    fn is_cluster_bootstrapped(&self, cluster_id: u64) -> Result<bool>;

    // Allocate a node id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use node 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_node_id(&mut self, cluster_id: u64) -> Result<u64>;

    // Allocate a store id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use store 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_store_id(&mut self, cluster_id: u64) -> Result<u64>;

    // Allocate a peer id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use peer 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_peer_id(&mut self, cluster_id: u64) -> Result<u64>;

    // Allocate a region id for this cluster. Pd must guarantee that
    // the id is increased monotonically, because we use region 1
    // for bootstrap already, so this function returns 2 at first.
    fn alloc_region_id(&mut self, cluster_id: u64) -> Result<u64>;

    // When the node starts, or some node information changed, it
    // uses put_node to tell pd know it.
    fn put_node(&mut self, cluster_id: u64, node: metapb::Node) -> Result<()>;

    // When the store starts, or some store information changed, it
    // uses put_store to tell pd know it.
    fn put_store(&mut self, cluster_id: u64, store: metapb::Store) -> Result<()>;

    // Delete the node from cluster, it is a very dangerous operation
    // and can not be recoverable, all the data belongs to this node
    // will be removed and we can't re-add this node again.
    // Sometimes, the node may crash and restart again, if the node is
    // off-line for a long time, pd will try to do auto-balance and then
    // delete the node.
    fn delete_node(&mut self, cluster_id: u64, node_id: u64) -> Result<()>;

    // Delete the store from cluster, it is a very dangerous operation
    // and can not be recoverable, all the data belongs to this store
    // will be removed and we can't re-add this store again.
    // If the store is off-line for a long time, pd will try to do
    // auto-balance and then delete the store.
    fn delete_store(&mut self, cluster_id: u64, store_id: u64) -> Result<()>;

    // Discuss (@ngaut): We don't need to support region and peer put/delete,
    // because pd knows all region and peers itself.
    // When bootstrapping, pd knows region 1 and peer 1 exists in node 1, store 1.
    // When changing peer, pd determines where to add a new peer in some store
    // for this region.
    // When region splitting, pd determines the new region id and peer id for the
    // split region.
    // When region merging, pd knows which two regions will be merged and which region
    // and peers will be removed.
    // When doing auto-balance, pd determines how to move the region from one store to another.

    // Get node address so that we can send message to it.
    fn get_node_addr(&self, cluster_id: u64, node_id: u64) -> Result<String>;

    // For route.
    // Get the region which the key belongs to.
    fn get_region_with_key(&self, cluster_id: u64, key: &[u8]) -> Result<metapb::Region>;

    // For route.
    // Get all regions which the keys belong to.
    fn get_regions_with_keys(&self,
                             cluster_id: u64,
                             keys: Vec<Vec<u8>>)
                             -> Result<Vec<metapb::Region>>;

    // For route.
    // Scan all regions which the region key range is in [start_key, end_key].
    fn scan_regions(&self,
                    cluster_id: u64,
                    start_key: &[u8],
                    end_key: &[u8],
                    limit: usize)
                    -> Result<Vec<metapb::Region>>;
}
<|endoftext|>