Add Parser::match_imm8 for parsing signed 8-bit integers

Also, make some stylistic tweaks to `match_imm16` and `match_imm32` based on the review comments.
This commit is contained in:
Andrew Brown
2020-03-30 12:27:21 -07:00
parent 508042101f
commit 07fc9d33bd

View File

@@ -683,6 +683,49 @@ impl<'a> Parser<'a> {
} }
} }
// Match and consume an i8 immediate.
fn match_imm8(&mut self, err_msg: &str) -> ParseResult<i8> {
if let Some(Token::Integer(text)) = self.token() {
self.consume();
let negative = text.starts_with('-');
let positive = text.starts_with('+');
let text = if negative || positive {
// Strip sign prefix.
&text[1..]
} else {
text
};
// Parse the text value; the lexer gives us raw text that looks like an integer.
let value = if text.starts_with("0x") {
// Skip underscores.
let text = text.replace("_", "");
// Parse it as a i8 in hexadecimal form.
u8::from_str_radix(&text[2..], 16)
.map_err(|_| self.error("unable to parse i8 as a hexadecimal immediate"))?
} else {
// Parse it as a i8 to check for overflow and other issues.
text.parse()
.map_err(|_| self.error("expected i8 decimal immediate"))?
};
// Apply sign if necessary.
let signed = if negative {
let value = value.wrapping_neg() as i8;
if value > 0 {
return Err(self.error("negative number too small"));
}
value
} else {
value as i8
};
Ok(signed)
} else {
err!(self.loc, err_msg)
}
}
// Match and consume a signed 16-bit immediate. // Match and consume a signed 16-bit immediate.
fn match_imm16(&mut self, err_msg: &str) -> ParseResult<i16> { fn match_imm16(&mut self, err_msg: &str) -> ParseResult<i16> {
if let Some(Token::Integer(text)) = self.token() { if let Some(Token::Integer(text)) = self.token() {
@@ -695,27 +738,32 @@ impl<'a> Parser<'a> {
} else { } else {
text text
}; };
let mut value;
// Lexer just gives us raw text that looks like an integer. // Parse the text value; the lexer gives us raw text that looks like an integer.
if text.starts_with("0x") { let value = if text.starts_with("0x") {
// Skip underscores. // Skip underscores.
let text = text.replace("_", ""); let text = text.replace("_", "");
// Parse it as a i16 in hexadecimal form. // Parse it as a i16 in hexadecimal form.
value = u16::from_str_radix(&text[2..], 16) u16::from_str_radix(&text[2..], 16)
.map_err(|_| self.error("unable to parse i16 as a hexadecimal immediate"))?; .map_err(|_| self.error("unable to parse i16 as a hexadecimal immediate"))?
} else { } else {
// Parse it as a i16 to check for overflow and other issues. // Parse it as a i16 to check for overflow and other issues.
value = text text.parse()
.parse() .map_err(|_| self.error("expected i16 decimal immediate"))?
.map_err(|_| self.error("expected i16 decimal immediate"))?; };
}
if negative { // Apply sign if necessary.
value = Ok(value.wrapping_neg())?; let signed = if negative {
if value as i16 > 0 { let value = value.wrapping_neg() as i16;
if value > 0 {
return Err(self.error("negative number too small")); return Err(self.error("negative number too small"));
} }
} value
Ok(value as i16) } else {
value as i16
};
Ok(signed)
} else { } else {
err!(self.loc, err_msg) err!(self.loc, err_msg)
} }
@@ -734,27 +782,32 @@ impl<'a> Parser<'a> {
} else { } else {
text text
}; };
let mut value;
// Lexer just gives us raw text that looks like an integer. // Parse the text value; the lexer gives us raw text that looks like an integer.
if text.starts_with("0x") { let value = if text.starts_with("0x") {
// Skip underscores. // Skip underscores.
let text = text.replace("_", ""); let text = text.replace("_", "");
// Parse it as a i32 in hexadecimal form. // Parse it as a i32 in hexadecimal form.
value = u32::from_str_radix(&text[2..], 16) u32::from_str_radix(&text[2..], 16)
.map_err(|_| self.error("unable to parse i32 as a hexadecimal immediate"))?; .map_err(|_| self.error("unable to parse i32 as a hexadecimal immediate"))?
} else { } else {
// Parse it as a i32 to check for overflow and other issues. // Parse it as a i32 to check for overflow and other issues.
value = text text.parse()
.parse() .map_err(|_| self.error("expected i32 decimal immediate"))?
.map_err(|_| self.error("expected i32 decimal immediate"))?; };
}
if negative { // Apply sign if necessary.
value = Ok(value.wrapping_neg())?; let signed = if negative {
if value as i32 > 0 { let value = value.wrapping_neg() as i32;
if value > 0 {
return Err(self.error("negative number too small")); return Err(self.error("negative number too small"));
} }
} value
Ok(value as i32) } else {
value as i32
};
Ok(signed)
} else { } else {
err!(self.loc, err_msg) err!(self.loc, err_msg)
} }