parsing - 使用 match 查看 stdin

标签 parsing rust

我正在尝试将旧编译器教科书中的翻译器/解析器示例从 C 移植到 Rust。

我有以下代码:

use std::io::Read;

fn lexan() {
    let mut input = std::io::stdin().bytes().peekable();
    loop {
        match input.peek() {
            Some(&ch) => {
                match ch {
                    _ => println!("{:?}", input.next()),
                }
            }
            None => break,
        }
    }
}

此时我并没有主动尝试解析输入,只是想了解 match 是如何工作的。目的是将解析分支添加到内部匹配中。不幸的是,这无法编译,因为我似乎无法理解匹配的语义:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:7:18
  |
7 |             Some(&ch) => {
  |                  ^--
  |                  ||
  |                  |hint: to prevent move, use `ref ch` or `ref mut ch`
  |                  cannot move out of borrowed content

据我了解,这个错误是因为我不拥有match 的返回值。问题是,我不相信我正在使用任一匹配项的返回值。我认为 input.next() 可能是问题所在,但不管有没有这部分(或者实际上,整个 println! 调用)都会出现同样的错误。

我在这里错过了什么?自从我研究 Rust 以来已经有一段时间了(而且从来没有认真研究过),并且大多数针对这种性质的东西的搜索结果似乎已经过时了。

最佳答案

match的返回值无关,甚至 match本身::

use std::io::Read;

fn lexan() {
    let mut input = std::io::stdin().bytes().peekable();
    if let Some(&ch) = input.peek() {}
}

问题是您正在尝试绑定(bind) Peekable::peek 的结果在取消引用时(这就是 & 中的 &ch 所做的)。在这种情况下,返回类型是 Option<&Result<u8, std::io::Error>>因为Bytes迭代器从底层流返回错误。由于此类型未实现 Copy ,尝试取消引用该类型需要您转移该值的所有权。您不能这样做,因为您不拥有原始值——因此会出现错误消息。

导致无法复制的那一 block 是Result的错误类型.因此,您可以匹配更深一层:

match input.peek() {
    Some(&Ok(ch)) => {
        match ch {
            _ => println!("{:?}", input.next()),
        }
    }
    Some(&Err(_)) => panic!(),
    None => break,
}

请注意,这段代码几乎无法编译。 peek的结果next时会失效被调用,所以对这段代码的如此多的小改动将触发借用检查器使代码失败。事实上,我有点惊讶上面的方法在第一次尝试时就起作用了。

如果你根本不关心错误,你可以这样做

while let Some(&Ok(ch)) = input.peek() {
    match ch {
        _ => println!("{:?}", input.next()),
    }
}

不幸的是,您不能拆分中间部分,因为这会导致借用 input。在通话期间持续 next :

while let Some(x) = input.peek() {
    match *x {
        Ok(ch) => {
            match ch {
                _ => println!("{:?}", input.next()),
            }
        }
        Err(_) => {}
    }

    // Could still use `x` here, compiler doesn't currently see that we don't
}

关于parsing - 使用 match 查看 stdin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45177131/

相关文章:

regex - 什么时候最好在基本的字符串拆分/子字符串化上使用正则表达式?

string - 一行将键值对字符串转换为HashMap

file - 在 Rust 中以读写模式打开文件

rust - Rust 中两种风格的文档注释有什么区别? (///对//!)

java - 如何读取多级括号表达式之间的文本

java - Android - logInWithReadPermissionsInBackground 上的 NullPointerException

php - 是否存在用于解析 ASN.1 或基于它生成 PHP 代码的 PHP 库?

Rust mod 面临问题错误 : file not found for module bytes

rust - decl_storage 中 `storage_name` 的示例是什么

parsing - 在程序中使用 ocaml Args