Skip to content

Commit

Permalink
added basic assembly tests and refactored errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbinth committed Nov 18, 2021
1 parent 32467cd commit 7ed951b
Show file tree
Hide file tree
Showing 8 changed files with 456 additions and 215 deletions.
52 changes: 39 additions & 13 deletions assembly/src/v1/block_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn parse_blocks(
// make sure at least one block has been read
if blocks.is_empty() {
let start_op = tokens.read_at(start_pos).expect("no start token");
Err(AssemblyError::empty_block(start_op.parts(), start_pos))
Err(AssemblyError::empty_block(start_op))
} else {
// build a binary tree out of the parsed list of blocks
Ok(combine_blocks(blocks))
Expand Down Expand Up @@ -70,7 +70,7 @@ impl BlockParser {
Self::IfElse => {
// --------------------------------------------------------------------------------
// record start of the if-else block and consume the 'if' token
let block_start = tokens.pos();
let if_start = tokens.pos();
tokens.advance();

// read the `if` clause
Expand All @@ -91,10 +91,15 @@ impl BlockParser {

// consume the `end` token
match tokens.read() {
None => Err(AssemblyError::unmatched_else(else_start)),
None => Err(AssemblyError::unmatched_else(
tokens.read_at(else_start).expect("no else token"),
)),
Some(token) => match token.parts()[0] {
Token::END => token.validate_end(),
_ => Err(AssemblyError::unmatched_else(else_start)),
Token::ELSE => Err(AssemblyError::dangling_else(token)),
_ => Err(AssemblyError::unmatched_else(
tokens.read_at(else_start).expect("no else token"),
)),
},
}?;
tokens.advance();
Expand All @@ -110,28 +115,41 @@ impl BlockParser {
// when no `else` clause was specified, a Span with a single noop
CodeBlock::new_span(vec![Operation::Noop])
}
_ => return Err(AssemblyError::unmatched_if(block_start)),
_ => {
return Err(AssemblyError::unmatched_if(
tokens.read_at(if_start).expect("no if token"),
))
}
},
None => return Err(AssemblyError::unmatched_if(block_start)),
None => {
return Err(AssemblyError::unmatched_if(
tokens.read_at(if_start).expect("no if token"),
))
}
};

Ok(CodeBlock::new_split(t_branch, f_branch))
}
Self::While => {
// --------------------------------------------------------------------------------
// record start of the while block and consume the 'while' token
let block_start = tokens.pos();
let while_start = tokens.pos();
tokens.advance();

// read the loop body
let loop_body = parse_blocks(tokens, proc_map)?;

// consume the `end` token
match tokens.read() {
None => Err(AssemblyError::unmatched_while(block_start)),
None => Err(AssemblyError::unmatched_while(
tokens.read_at(while_start).expect("no if token"),
)),
Some(token) => match token.parts()[0] {
Token::END => token.validate_end(),
_ => Err(AssemblyError::unmatched_while(block_start)),
Token::ELSE => Err(AssemblyError::dangling_else(token)),
_ => Err(AssemblyError::unmatched_while(
tokens.read_at(while_start).expect("no if token"),
)),
},
}?;
tokens.advance();
Expand All @@ -141,18 +159,23 @@ impl BlockParser {
Self::Repeat(iter_count) => {
// --------------------------------------------------------------------------------
// record start of the repeat block and consume the 'repeat' token
let block_start = tokens.pos();
let repeat_start = tokens.pos();
tokens.advance();

// read the loop body
let loop_body = parse_blocks(tokens, proc_map)?;

// consume the `end` token
match tokens.read() {
None => Err(AssemblyError::unmatched_while(block_start)),
None => Err(AssemblyError::unmatched_repeat(
tokens.read_at(repeat_start).expect("no repeat token"),
)),
Some(token) => match token.parts()[0] {
Token::END => token.validate_end(),
_ => Err(AssemblyError::unmatched_while(block_start)),
Token::ELSE => Err(AssemblyError::dangling_else(token)),
_ => Err(AssemblyError::unmatched_repeat(
tokens.read_at(repeat_start).expect("no repeat token"),
)),
},
}?;
tokens.advance();
Expand All @@ -174,7 +197,9 @@ impl BlockParser {
// retrieve the procedure block from the proc map and consume the 'exec' token
let proc_root = proc_map
.get(label)
.ok_or_else(|| AssemblyError::undefined_proc(tokens.pos(), label))?
.ok_or_else(|| {
AssemblyError::undefined_proc(tokens.read().expect("no exec token"), label)
})?
.clone();
tokens.advance();
Ok(proc_root)
Expand Down Expand Up @@ -211,6 +236,7 @@ impl BlockParser {
token.validate_end()?;
None
}
Token::BEGIN | Token::PROC => None,
_ => Some(Self::Span),
},
};
Expand Down
Loading

0 comments on commit 7ed951b

Please sign in to comment.