首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么对regex:find结果的匹配会抱怨期待一个struct::Match但是找到了tuple?

为什么对regex:find结果的匹配会抱怨期待一个struct::Match但是找到了tuple?
EN

Stack Overflow用户
提问于 2018-11-11 23:18:20
回答 1查看 381关注 0票数 1

我把此代码来自代码检查抄袭到IntelliJ的点子里,试着玩一玩。我有一个类似于这个作业的作业(我需要在Rust中编写Linux的bc版本),所以我使用这段代码只是为了参考。

代码语言:javascript
复制
use std::io;
extern crate regex;
#[macro_use]
extern crate lazy_static;

use regex::Regex;

fn main() {
    let tokenizer = Tokenizer::new();

    loop {
        println!("Enter input:");
        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");
        let tokens = tokenizer.tokenize(&input);
        let stack = shunt(tokens);
        let res = calculate(stack);
        println!("{}", res);
    }
}

#[derive(Debug, PartialEq)]
enum Token {
    Number(i64),
    Plus,
    Sub,
    Mul,
    Div,
    LeftParen,
    RightParen,
}

impl Token {
    /// Returns the precedence of op
    fn precedence(&self) -> usize {
        match *self {
            Token::Plus | Token::Sub => 1,
            Token::Mul | Token::Div => 2,
            _ => 0,
        }
    }
}

struct Tokenizer {
    number: Regex,
}

impl Tokenizer {
    fn new() -> Tokenizer {
        Tokenizer {
            number: Regex::new(r"^[0-9]+").expect("Unable to create the regex"),
        }
    }

    /// Tokenizes the input string into a Vec of Tokens.
    fn tokenize(&self, mut input: &str) -> Vec<Token> {
        let mut res = vec![];

        loop {
            input = input.trim_left();
            if input.is_empty() { break }

            let (token, rest) = match self.number.find(input) {
                Some((_, end)) => {
                    let (num, rest) = input.split_at(end);
                    (Token::Number(num.parse().unwrap()), rest)
                },
                _ => {
                    match input.chars().next() {
                        Some(chr) => {
                            (match chr {
                                '+' => Token::Plus,
                                '-' => Token::Sub,
                                '*' => Token::Mul,
                                '/' => Token::Div,
                                '(' => Token::LeftParen,
                                ')' => Token::RightParen,
                                _ => panic!("Unknown character!"),
                            }, &input[chr.len_utf8()..])
                        }
                        None => panic!("Ran out of input"),
                    }
                }
            };

            res.push(token);
            input = rest;
        }

        res
    }
}

/// Transforms the tokens created by `tokenize` into RPN using the
/// [Shunting-yard algorithm](https://en.wikipedia.org/wiki/Shunting-yard_algorithm)
fn shunt(tokens: Vec<Token>) -> Vec<Token> {
    let mut queue = vec![];
    let mut stack: Vec<Token> = vec![];
    for token in tokens {
        match token {
            Token::Number(_) => queue.push(token),
            Token::Plus | Token::Sub | Token::Mul | Token::Div => {
                while let Some(o) = stack.pop() {
                    if token.precedence() <= o.precedence() {
                        queue.push(o);
                    } else {
                        stack.push(o);
                        break;
                    }
                }
                stack.push(token)
            },
            Token::LeftParen => stack.push(token),
            Token::RightParen => {
                let mut found_paren = false;
                while let Some(op) = stack.pop() {
                    match op {
                        Token::LeftParen => {
                            found_paren = true;
                            break;
                        },
                        _ => queue.push(op),
                    }
                }
                assert!(found_paren)
            },
        }
    }
    while let Some(op) = stack.pop() {
        queue.push(op);
    }
    queue
}

/// Takes a Vec of Tokens converted to RPN by `shunt` and calculates the result
fn calculate(tokens: Vec<Token>) -> i64 {
    let mut stack = vec![];
    for token in tokens {
        match token {
            Token::Number(n) => stack.push(n),
            Token::Plus => {
                let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap());
                stack.push(a + b);
            },
            Token::Sub => {
                let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap());
                stack.push(a - b);
            },
            Token::Mul => {
                let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap());
                stack.push(a * b);
            },
            Token::Div => {
                let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap());
                stack.push(a / b);
            },
            _ => {
                // By the time the token stream gets here, all the LeftParen
                // and RightParen tokens will have been removed by shunt()
                unreachable!();
            },
        }
    }
    stack[0]
}

但是,当我运行它时,它会给出以下错误:

代码语言:javascript
复制
error[E0308]: mismatched types
  --> src\main.rs:66:22
   |
66 |                 Some((_, end)) => {
   |                      ^^^^^^^^ expected struct `regex::Match`, found tuple
   |
   = note: expected type `regex::Match<'_>`
              found type `(_, _)`

它抱怨说,当我应该使用令牌时,我使用的是Some()方法的元组。我不知道标记应该传递什么,因为元组似乎正在遍历Token选项。如何重写它以使Some()方法将元组识别为Token?我在这方面工作了一天,但我没有找到任何真正好的解决办法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-12 00:18:45

您所引用的代码已经超过两年了。值得注意的是,这早于regex 1.0。Regex::find版本如下:

代码语言:javascript
复制
fn find(&self, text: &str) -> Option<(usize, usize)>

版本1.0.6将其定义为

代码语言:javascript
复制
pub fn find<'t>(&self, text: &'t str) -> Option<Match<'t>>

但是,Match定义了一些方法来获得代码编写时假定的起始和结束索引。在这种情况下,由于只关心结束索引,所以可以调用Match::end

代码语言:javascript
复制
let (token, rest) = match self.number.find(input).map(|x| x.end()) {
    Some(end) => {
    // ...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53254221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档