impl OpBranch

This commit is contained in:
Kangzhi Shi
2020-12-29 13:02:43 +02:00
parent 0b2c8d1fa2
commit 93c2b8b555

View File

@@ -417,7 +417,6 @@ impl OpcodeDispatcher {
}
}),
SreOpcode::BRANCH => unimplemented(),
SreOpcode::CALL => unimplemented(),
SreOpcode::CATEGORY => once(|drive| {
let catcode = SreCatCode::try_from(drive.peek_code(1)).unwrap();
if drive.at_end() || !category(catcode, drive.peek_char()) {
@@ -1146,3 +1145,51 @@ impl OpcodeExecutor for OpMaxUntil {
}
}
}
struct OpBranch {
jump_id: usize,
child_ctx_id: usize,
current_branch_length: usize,
}
impl Default for OpBranch {
fn default() -> Self {
Self { jump_id: 0, child_ctx_id: 0, current_branch_length: 0 }
}
}
impl OpcodeExecutor for OpBranch {
fn next(&mut self, drive: &mut StackDrive) -> Option<()> {
match self.jump_id {
0 => {
drive.state.marks_push();
// jump out the head
self.current_branch_length = 1;
self.jump_id = 1;
self.next(drive)
}
1 => {
drive.skip_code(self.current_branch_length);
self.current_branch_length = drive.peek_code(0) as usize;
if self.current_branch_length == 0 {
drive.state.marks_pop_discard();
drive.ctx_mut().has_matched = Some(false);
return None;
}
drive.state.string_position = drive.ctx().string_position;
self.child_ctx_id = drive.push_new_context(1);
self.jump_id = 2;
Some(())
}
2 => {
let child_ctx = &drive.state.context_stack[self.child_ctx_id];
if child_ctx.has_matched == Some(true) {
drive.ctx_mut().has_matched = Some(true);
return None;
}
drive.state.marks_pop_keep();
self.jump_id = 1;
Some(())
}
_ => unreachable!()
}
}
}