Continue keyword

This commit is contained in:
2024-05-04 20:37:47 -05:00
parent cd53a21e8f
commit f19736cb8a
13 changed files with 147 additions and 23 deletions
+1
View File
@@ -63,6 +63,7 @@ pub enum Macro {
Do,
End,
Break,
Continue,
}
#[derive(Debug, PartialEq, Clone)]
+1 -1
View File
@@ -69,7 +69,7 @@ org_directive = { label_def? ~ ".org" ~ expr }
equ_directive = { label_def ~ ".equ" ~ expr }
include = { "include" ~ string }
control = { "if" | "unless" | "while" | "until" | "do" | "else" | "end" | "break" }
control = { "if" | "unless" | "while" | "until" | "do" | "else" | "end" | "break" | "continue" }
preprocessor = {"#" ~ (control | include) }
blank = { WHITESPACE? ~ COMMENT? }
+1
View File
@@ -209,6 +209,7 @@ fn parse_macro(line: Pair) -> Macro {
"do" => Macro::Do,
"end" => Macro::End,
"break" => Macro::Break,
"continue" => Macro::Continue,
_ => unreachable!(),
},
Rule::include => Macro::Include(create_string(pre.only())),
+53 -8
View File
@@ -217,23 +217,32 @@ impl<T: IntoIterator<Item = String>, F: Fn(String) -> Result<T, AssembleError>>
}
_ => return Some(AssembleError::MacroError(self.current_location())),
},
Macro::Break => {
let innermost_loop = self.control_stack.iter().rev().find(|cs| {
match cs {
ControlStructure::LoopDo(_, _) => true,
_ => false
}
});
if let Some(ControlStructure::LoopDo(_, after)) = innermost_loop {
if let Some(ControlStructure::LoopDo(_, after)) = self.innermost_loop() {
self.emit(format!("jmpr @{}", after));
} else {
return Some(AssembleError::MacroError(self.current_location()))
}
}
Macro::Continue => {
if let Some(ControlStructure::LoopDo(test, _)) = self.innermost_loop() {
self.emit(format!("jmpr @{}", test));
} else {
return Some(AssembleError::MacroError(self.current_location()))
}
}
}
None
}
pub fn innermost_loop(&self) -> Option<&ControlStructure> {
self.control_stack.iter().rev().find(|cs| {
match cs {
ControlStructure::LoopDo(_, _) => true,
_ => false
}
})
}
}
#[cfg(test)]
@@ -386,4 +395,40 @@ mod tests {
Some(AssembleError::MacroError(Location::from(2)))
)
}
#[test]
fn test_preprocess_continue() {
// First a working one
assert_eq!(
lines_for(stringify(vec!["#while", "#do", "#continue", "#end"])),
vec![
VASMLine::LabelDef(Label("__gensym_1".to_string())),
VASMLine::Instruction(
None,
Brz,
Some(Node::RelativeLabel("__gensym_2".to_string()))
),
VASMLine::Instruction(
None,
Jmpr,
Some(Node::RelativeLabel("__gensym_1".to_string()))
),
VASMLine::Instruction(
None,
Jmpr,
Some(Node::RelativeLabel("__gensym_1".to_string()))
),
VASMLine::LabelDef(Label::from("__gensym_2"))
]
);
}
#[test]
fn test_malformed_continue() {
// Malformed one
assert_eq!(
error_for(stringify(vec!["#while", "#continue"])),
Some(AssembleError::MacroError(Location::from(2)))
)
}
}