Tôi có một số trình phân tích cú pháp. Có một cấp cao nhất có thể ủy quyền cho người khác.
Bộ phân tích cú pháp
chúng tôi bắt đầu từ Người đọc
Nhận đầu vào của họ (biến). Tôi chỉ muốn một cái Bộ phân tích cú pháp
Để có thể phân tích cú pháp cùng một lúc, chỉ cần có một trình phân tích cú pháp Người đọc
.
Tôi đã thực hiện điều này bằng cách tạo một enum cho trình phân tích cú pháp cấp cao nhất, có thể là trình đọc hoặc trình phân tích cú pháp đại biểu (có trình đọc). Bằng cách này, nó chỉ có thể được đọc khi không được ủy quyền, đó là điều tôi muốn.
Từ trình phân tích cú pháp cấp cao nhất, tôi cần phải mượn enum này để xác định những việc cần làm và lấy trình phân tích cú pháp trình đọc hoặc đại biểu. Vấn đề là nếu tôi muốn bắt đầu hoặc dừng việc ủy quyền, tôi cần phải di chuyển Người đọc
Về. Nhưng tại thời điểm này nó vẫn có thể thay đổi được mượn.
Tôi đã tạo một ví dụ tối thiểu và bao gồm thông tin về thay thế
Gợi ý trong các ý kiến. và vòng đời phi từ vựng:
#![tính năng(nll)]
sử dụng std::mem::replace;
cấu trúc Reader {
tôi: u8,
}
impl Reader {
fn tiếp theo(&mut chính nó) -> u8 {
/* một số logic ở đây */
tự.i += 1;
bản thân tôi
}
}
Trình phân tích cú pháp đặc điểm {
fn phân tích(&mut bản thân) -> u8;
}
enum ReaderOrDelegate {
Đọc(Người đọc),
Delegate(AnotherParser), /* Đối tượng đặc điểm trong thực tế, nhưng giữ cho nó đơn giản ở đây. */
}
cấu trúc OneParser {
reader_or_delegate: Người đọc hoặc người đại diện,
}
impl Parser cho OneParser {
fn phân tích(&mut bản thân) -> u8 {
khớp với self.reader_or_delegate {
ReaderOrDelegate::Delegate(tham chiếu mut đại biểu) => {
khớp lệnh delegate.parse() {
0 => {
thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Read(delegate.consume()));
tự phân tích()
},
x => 2 * x
}
},
ReaderOrDelegate::Read(tham chiếu mut reader) => {
khớp reader.next() {
0 => {
thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
tự phân tích()
},
x => 3 * x
}
},
}
}
}
cấu trúc AnotherParser {
người đọc: Người đọc,
}
triển khai AnotherParser {
fn tiêu thụ(bản thân) -> Người đọc {
tự.đọc
}
}
impl Parser cho AnotherParser {
fn phân tích(&mut bản thân) -> u8 {
self.reader.next() * 2
}
}
Với gợi ý bình luận vẫn còn lỗi:
lỗi[E0308]: các loại không khớp
--> src/main.rs:42:106
|
42 | thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
| ^^^^^^ mong đợi struct `Reader`, tìm thấy &mut Reader
|
= lưu ý: loại mong đợi `Reader`
tìm thấy loại `&mut Reader`
Tôi tin tôi có thể vượt qua người đọc
Giải pháp cho vấn đề này xuất phát từ Người đọc hoặc đại biểu
và sử dụng nó như Rc<>>>
trong mỗi trình phân tích cú pháp Nhưng tôi nghĩ sẽ hợp lý hơn nếu đặt nó trong một enum: mỗi lần chỉ có một trình phân tích cú pháp có thể sử dụng trình đọc. Điều này có thể thực hiện được không?
Tôi biết lỗi này có ý nghĩa trong trường hợp này, nhưng tôi cảm thấy ở cấp độ cao, tôi có thể làm được những gì mình muốn. Người đọc
Chỉ cần một chủ sở hữu.
biên tập:đối với tôi,thay thế
Điều quan trọng là câu hỏi có thể được áp dụng cho trường hợp này bằng cách "lồng" (người đọc
đã được cuộc thi đấu
Mượn rồi muốn đổi ruộng). Vì vậy, mặc dù nó có thể phù hợp nhưng tôi không nghĩ một câu hỏi khác là đủ để giải quyết vấn đề này. Dù sao thì cũng không dành cho tôi.
Chỉnh sửa 2: Bao gồm các đề xuất nhận xét trong các ví dụ về mã và lỗi.
Hãy xem xét dòng này:
thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
bạn cần một cáingười đọc
Giá trị, không phải tài liệu tham khảo, xây dựnganotherParser
:
lỗi[E0308]: các loại không khớp
--> src/main.rs:42:106
|
42 | thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
| ^^^^^^ mong đợi struct `Reader`, tìm thấy &mut Reader
|
= lưu ý: loại mong đợi `Reader`
tìm thấy loại `&mut Reader`
Nhưng không thể có được giá trị như vậy. Nếu chúng ta cố gắng:
ReaderOrDelegate::Đọc(người đọc) => {
khớp reader.next() {
0 => {
thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
tự phân tích()
},
x => 3 * x
}
},
Bây giờ chúng tôi đã tìm thấy vấn đề thực sự với thiết kế của bạn:
lỗi[E0507]: không thể di chuyển ra khỏi nội dung đã mượn
--> src/main.rs:39:36
|
39 | ReaderOrDelegate::Đọc(người đọc) => {
| ^^^^^^ không thể di chuyển ra khỏi nội dung đã mượn
phân tích
Tham khảo phương phápbản thân
Điều này có nghĩa là tại thời điểm này chúng ta không thể loại bỏ giá trị sở hữu khỏi tài sản được mượn.bản thân
.
Cũng lưu ý những lỗi E0507Cũng áp dụng cho dòng này:
thay thế(&mut self.reader_or_delegate, ReaderOrDelegate::Read(delegate.consume()));
bởi vìtiêu thụ
thử mượn từ đại biểu
Di chuyển một giá trị ra khỏi .
Trong mã của bạn, trình biên dịch không hiển thị vấn đề, nhưng nếu bạn nhận xét dòng dường như là vấn đề duy nhất có trong ví dụ của bạn thì đúng là như vậy.
Giải pháp duy nhất tôi có thể sắp xếp mà không gây ra lỗi kiểm tra mượn và không chuyển đổi quá nhiều thiết kế của bạn là dựa trên việc sử dụng bộ đếm tham chiếu Người đọc
, được chia sẻ giữa trình phân tích cú pháp cấp cao nhất và trình phân tích cú pháp đại biểu.
Và Rc
Bạn chỉ có một trình đọc được chia sẻ với trình phân tích cú pháp của mình thông qua con trỏ thông minh.
ĐọcHoặcDelegate
Enum chỉ cho biết trình phân tích cú pháp của sự kiện, không còn người đọc nào để di chuyển nữa.
#![tính năng(nll)]
sử dụng std::rc::Rc;
cấu trúc Reader {
tôi: u8,
}
impl Reader {
fn tiếp theo(&mut chính nó) -> u8 {
/* một số logic ở đây */
tự.i += 1;
bản thân tôi
}
}
Trình phân tích cú pháp đặc điểm {
fn phân tích(&mut bản thân) -> u8;
}
enum ReaderOrDelegate {
Đọc,
Đại biểu,
}
cấu trúc OneParser {
reader_or_delegate: Người đọc hoặc người đại diện,
người đọc: Rc,
đại biểu: AnotherParser
}
impl Parser cho OneParser {
fn phân tích(&mut bản thân) -> u8 {
khớp với self.reader_or_delegate {
Người đọc hoặc đại diện::Đại diện => {
khớp với self.delegate.parse() {
0 => {
self.reader_or_delegate = Người đọc hoặc Người ủy quyền::Đọc;
tự phân tích()
},
x => 2 * x
}
},
Người đọc hoặc đại diện::Đọc => {
khớp Rc::get_mut(&mut self.reader).unwrap().next() {
0 => {
self.reader_or_delegate = Người đọc hoặc Người đại diện::Người đại diện;
tự phân tích()
},
x => 3 * x
}
},
}
}
}
cấu trúc AnotherParser {
người đọc: Rc
}
impl Parser cho AnotherParser {
fn phân tích(&mut bản thân) -> u8 {
Rc::get_mut(&mut self.reader).unwrap().next() * 2
}
}
Tôi là một lập trình viên xuất sắc, rất giỏi!