如何在 Rust 结构中存储动态类型变量?
How to store a dynamically typed variable in a Rust struct?
我否认我是 Rust 的初学者,这是我的第一个项目。我正在尝试用 Rust 编写 SQL 编译器。我必须创建一个 Token
结构来表示 SQL 查询的语法单元。在 C/C++ 我会写这样的结构:
typedef unsigned long Value;
// Represents the type of the token (e.g. number, string, identifier...)
typedef enum class TokenType { ... }
struct Token {
TokenType type;
unsigned char priority;
Value value;
}
使用这种方法,我使用 Value
类型来存储任何类型的值。如果它是一个数字,value
被解释为一个整数,浮点数...,而当 value
表示一个字符串或标识符时,它被转换为一个字符串指针,然后用于访问堆-它指向的已分配数据。
为了决定如何处理 Token
的 value
属性,我使用 type
字段。例如,如果 type
告诉我令牌是一个整数,我就将 value
转换为一个整数。如果 type
告诉我令牌是标识符,我将 value
转换为字符串指针。
我的问题是,是否可以在安全 Rust 中做类似的事情?如果不是,那么实现可以基于 TokenType
以多种方式解释的动态类型变量的好方法是什么?或者是否有更简洁的方法来创建在 Rust 中运行良好的语法标记?
提前致谢。
在 Rust 中,如果你有一组可能的类型,你应该使用 enum。 Rust 中的枚举与 C 中的不同:它们可以携带有效负载(即它们是求和类型)。
enum TokenType {
Number(i32),
Identifier(String),
String(String),
Plus,
Minus,
// ...
}
然后match
反对:
let e: TokenType = ...;
match e {
TokenType::Number(n) => println!("number: {n}"),
TokenType::String(s) => println!("string: {s}"),
TokenType::Plus => println!("plus"),
// ...
}
// some variants can hold parsed data
pub enum TokenKind {
Ident,
Op,
Int(i64),
Float(f64),
String,
Eof,
}
pub struct Source {
pub content: String,
}
impl Source {
// no need to allocate a new string for each token, just store the span
// and access the slice when needed
pub fn get_underlying_string(&self, token: &Token) -> &str {
&self.content[token.span.clone()]
}
}
// we use struct because token has some common parts
pub struct Token {
pub kind: TokenKind,
pub span: Range<usize>,
}
fn main() {
let mut token = Token {
kind: TokenKind::Int(10),
span: 0..1,
};
println!("int: {}", match token.kind {
TokenKind::Int(i) => i,
_ => panic!("unexpected token kind"),
}); // prints "int: 10"
}
在 Rust 中,这个问题有更好的解决方案。
Rust 的 enum
工作方式有点不同,但它们更适合这种情况:枚举变体本身可以具有仅适用于枚举的一个变体的字段。
这样,您可以将值 存储在 您的枚举中:
struct Token{
priority: u8,
value: TokenValue
}
enum TokenValue{
Int (i32),
Str (String),
Id {
name: String,
id: u32
}
// ... other variants
}
这也为使用它的代码提供了类型安全,Rust 可以优化它为每个变体分配的内存量。
这个功能解释的很好in The Rust Programming Language book。
我否认我是 Rust 的初学者,这是我的第一个项目。我正在尝试用 Rust 编写 SQL 编译器。我必须创建一个 Token
结构来表示 SQL 查询的语法单元。在 C/C++ 我会写这样的结构:
typedef unsigned long Value;
// Represents the type of the token (e.g. number, string, identifier...)
typedef enum class TokenType { ... }
struct Token {
TokenType type;
unsigned char priority;
Value value;
}
使用这种方法,我使用 Value
类型来存储任何类型的值。如果它是一个数字,value
被解释为一个整数,浮点数...,而当 value
表示一个字符串或标识符时,它被转换为一个字符串指针,然后用于访问堆-它指向的已分配数据。
为了决定如何处理 Token
的 value
属性,我使用 type
字段。例如,如果 type
告诉我令牌是一个整数,我就将 value
转换为一个整数。如果 type
告诉我令牌是标识符,我将 value
转换为字符串指针。
我的问题是,是否可以在安全 Rust 中做类似的事情?如果不是,那么实现可以基于 TokenType
以多种方式解释的动态类型变量的好方法是什么?或者是否有更简洁的方法来创建在 Rust 中运行良好的语法标记?
提前致谢。
在 Rust 中,如果你有一组可能的类型,你应该使用 enum。 Rust 中的枚举与 C 中的不同:它们可以携带有效负载(即它们是求和类型)。
enum TokenType {
Number(i32),
Identifier(String),
String(String),
Plus,
Minus,
// ...
}
然后match
反对:
let e: TokenType = ...;
match e {
TokenType::Number(n) => println!("number: {n}"),
TokenType::String(s) => println!("string: {s}"),
TokenType::Plus => println!("plus"),
// ...
}
// some variants can hold parsed data
pub enum TokenKind {
Ident,
Op,
Int(i64),
Float(f64),
String,
Eof,
}
pub struct Source {
pub content: String,
}
impl Source {
// no need to allocate a new string for each token, just store the span
// and access the slice when needed
pub fn get_underlying_string(&self, token: &Token) -> &str {
&self.content[token.span.clone()]
}
}
// we use struct because token has some common parts
pub struct Token {
pub kind: TokenKind,
pub span: Range<usize>,
}
fn main() {
let mut token = Token {
kind: TokenKind::Int(10),
span: 0..1,
};
println!("int: {}", match token.kind {
TokenKind::Int(i) => i,
_ => panic!("unexpected token kind"),
}); // prints "int: 10"
}
在 Rust 中,这个问题有更好的解决方案。
Rust 的 enum
工作方式有点不同,但它们更适合这种情况:枚举变体本身可以具有仅适用于枚举的一个变体的字段。
这样,您可以将值 存储在 您的枚举中:
struct Token{
priority: u8,
value: TokenValue
}
enum TokenValue{
Int (i32),
Str (String),
Id {
name: String,
id: u32
}
// ... other variants
}
这也为使用它的代码提供了类型安全,Rust 可以优化它为每个变体分配的内存量。
这个功能解释的很好in The Rust Programming Language book。