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