如何在模块中划分我的程序?

时间:2017-02-07 13:40:15

标签: module rust

我在将代码划分为模块时遇到问题,我有很多编译错误,但我尝试了一些东西。单个文件程序使用四个基本数学运算符(+ - * /)来计算表达式,并用括号括起来。

我是Rust的新手,所以我无法理解模块系统,我希望你能帮助我理解它并从一开始就做好。

这是代码(所有文件都在货物项目的src /文件夹中):

Operator.rs

// An attribute to hide warnings for unused code.
#![allow(dead_code)]

pub enum Operator {
    Plus,
    Minus,
    Mul,
    Div,
}

RuntimeContext.rs

pub struct RuntimeContext;

Token.rs

// An attribute to hide warnings for unused code.
#![allow(dead_code)]

#[derive(Debug, PartialEq)]
pub enum Token {
    IllegalToken, // invalid token, error
    TokPlus, // +
    TokMinus, // -
    TokMul, // *
    TokDiv, // /
    TokOparen, // (
    TokCparen, // )
    TokFloating, // number
    TokEos, // end of string
}

lexer.rs

pub use Token;

mod lexer {
    use Token::Token;
    use Token::Token::*;
    use regex::Regex;

    pub fn lexer(input: &str) -> Vec<(Token, Option<f64>)> {
        let re = Regex::new(r"([-+*/)(])|([0-9]+\.[0-9]+)|([0-9]+)").unwrap();
        let mut tokens_and_values: Vec<(Token, Option<f64>)> = Vec::new();
        let mut number: f64;

        for cap in re.captures_iter(&input) {
            let cap1 = cap.get(1);
            let cap2 = cap.get(2);
            let cap3 = cap.get(3);
            if cap1.is_some() {
                tokens_and_values.push((match cap1.unwrap().as_str() {
                                            "+" => Token::TokPlus,
                                            "-" => Token::TokMinus,
                                            "*" => Token::TokMul,
                                            "/" => Token::TokDiv,
                                            "(" => Token::TokOparen,
                                            ")" => Token::TokCparen,
                                            _ => Token::IllegalToken,
                                        },
                                        None));
            } else if cap2.is_some() {
                number = cap2.unwrap().as_str().parse().unwrap();
                tokens_and_values.push((Token::TokFloating, Some(number)));
            } else if cap3.is_some() {
                number = cap3.unwrap().as_str().parse().unwrap();
                tokens_and_values.push((Token::TokFloating, Some(number)));
            }
            //println!("{:?}", cap);
        }
        tokens_and_values.push((TokEos, None));
        tokens_and_values
    }
}

recursive_descent_parser.rs

pub use Token;
pub use Operator;

mod recursive_descent_parser {
    use Token::Token;
    use Token::Token::*;
    use Operator::Operator::*;

    pub fn recursive_descent_parser(input: &str) -> Box<Exp> {
        let tokens_and_values = lexer(&input);
        fn expr(tokens_and_values: &Vec<(Token, Option<f64>)>, mut index: &mut usize) -> Box<Exp> {
            // println!("index = {}", index);
            let term = term(&tokens_and_values, index);

            match tokens_and_values[*index] {
                (TokPlus, None) => {
                    *index += 1;
                    Box::new(BinaryExp {
                        exp1: term,
                        exp2: expr(&tokens_and_values, &mut index),
                        op: Plus,
                    })
                }
                (TokMinus, None) => {
                    *index += 1;
                    Box::new(BinaryExp {
                        exp1: term,
                        exp2: expr(&tokens_and_values, &mut index),
                        op: Minus,
                    })
                }
                _ => term, 
            }
        }

        // <Term> ::= <Factor> | <Factor> {*|/} <Term>
        fn term(tokens_and_values: &Vec<(Token, Option<f64>)>, mut index: &mut usize) -> Box<Exp> {
            // println!("index = {}", index);
            let factor = factor(&tokens_and_values, index);
            //*index += 1;
            match tokens_and_values[*index] {
                (TokMul, None) => {
                    *index += 1;
                    Box::new(BinaryExp {
                        exp1: factor,
                        exp2: term(&tokens_and_values, &mut index),
                        op: Mul,
                    })
                }
                (TokDiv, None) => {
                    *index += 1;
                    Box::new(BinaryExp {
                        exp1: factor,
                        exp2: term(&tokens_and_values, &mut index),
                        op: Div,
                    })
                }
                _ => factor,
            }
        }

        // <Factor>::= <number> | ( <Expr> ) | {+|-} <Factor>
        fn factor(tokens_and_values: &Vec<(Token, Option<f64>)>,
                  mut index: &mut usize)
                  -> Box<Exp> {
            //println!("index = {}", index);

            match tokens_and_values[*index].1 {
                Some(num) => {
                    *index += 1;
                    return Box::new(NumericConstant { value: num });
                }
                None => {}
            };

            //println!("number = {}", number);
            match tokens_and_values[*index] {
                (TokOparen, None) => {
                    // println!("oparen");
                    *index += 1;
                    let result = Box::new(expr(&tokens_and_values, &mut index));

                    if tokens_and_values[*index].0 != TokCparen {
                        println!("unclosed paren");
                    }

                    *index += 1;
                    result
                }
                (TokPlus, None) => {
                    *index += 1;
                    Box::new(UnaryExp {
                        exp1: factor(&tokens_and_values, &mut index),
                        op: Plus,
                    })
                }
                (TokMinus, None) => {
                    *index += 1;
                    Box::new(UnaryExp {
                        exp1: factor(&tokens_and_values, index),
                        op: Minus,
                    })
                }
                _ => return Box::new(NumericConstant { value: 288 as f64 }),
            }
        }
        let mut index = 0;
        expr(&tokens_and_values, &mut index)
    }
}

main.rs

use Operator;
use Token;
use RuntimeContext;
use lexer;
use recursive_descent_parser;

extern crate regex;
use regex::Regex;

use std::ops::Deref;
use std::cmp::PartialEq;

trait Exp {
    fn evaluate(&self, &mut RuntimeContext) -> f64;
}

impl Exp for Box<Exp> {
    fn evaluate(&self, runtime_context: &mut RuntimeContext) -> f64 {
        self.deref().evaluate(runtime_context)
    }
}

struct NumericConstant {
    value: f64, 
    // marker: PhantomData<T>,
}

impl Exp for NumericConstant {
    fn evaluate(&self, runtime_context: &mut RuntimeContext) -> f64 {
        self.value
    }
}

impl Exp for Box<NumericConstant> {
    fn evaluate(&self, runtime_context: &mut RuntimeContext) -> f64 {
        self.deref().value
    }
}

struct BinaryExp<T: Exp, U: Exp> {
    exp1: T,
    exp2: U,
    op: Operator,
}

impl<T: Exp, U: Exp> Exp for BinaryExp<T, U> {
    fn evaluate(&self, runtime_context: &mut RuntimeContext) -> f64 {
        use Operator::*;
        match self.op {
            Plus => self.exp1.evaluate(runtime_context) + self.exp2.evaluate(runtime_context),
            Minus => self.exp1.evaluate(runtime_context) - self.exp2.evaluate(runtime_context),
            Mul => self.exp1.evaluate(runtime_context) * self.exp2.evaluate(runtime_context),
            Div => self.exp1.evaluate(runtime_context) / self.exp2.evaluate(runtime_context),
        }
    }
}

struct UnaryExp<T: Exp> {
    exp1: T,
    op: Operator,
}

impl<T: Exp> Exp for UnaryExp<T> {
    fn evaluate(&self, runtime_context: &mut RuntimeContext) -> f64 {
        use Operator::*;
        match self.op {
            Minus => -self.exp1.evaluate(runtime_context),
            _ => self.exp1.evaluate(runtime_context),
        }
    }
}

fn main() {
    use Operator::*;

    let expressions = vec!["2+2",
                           "5*10",
                           "(2+5)*10",
                           "(10 + (30 + 50 ))",
                           "(100 / 25)",
                           "(25 * 4 * 8)",
                           "25 * 4 * 8 + 100 / 25",
                           "-2*3+3",
                           "(25 * 4 * 8) + (100 / 25)"];

    for expression in expressions {
        //println!("{}", );
        //println!("{:?}", lexer(&expression));
        let parsed = recursive_descent_parser(expression);
        let mut runtime_context = RuntimeContext;
        let result = parsed.evaluate(&mut runtime_context);
        println!("{} = {}", &expression, result);
    }
}

1 个答案:

答案 0 :(得分:4)

此时这有点乱。我建议首先在lib.rs文件夹中创建一个额外的src文件,并在其中声明所有模块和外部包装箱:

pub mod operator;
pub mod token;
pub mod runtime_context;
pub mod lexer;
pub mod recursive_descent_parser;

extern crate regex;

注意略微修改的模块名称(这也适用于它们的文件名);根据The Rust Book:

  

模块名称遵循其他Rust标识符的约定:   lower_snake_case。

之后,您可以use main.rs SELECT TOP 1 email, rawEmail, Status FROM TestToDelete WHERE status IN (11, 22) GROUP BYrawEmail, email, status HAVING COUNT(*) > 2 ORDER BY MAX(validationDate) DESC 。我建议阅读The Rust Book的chapter on Crates and Modules