Merge pull request #1686 from AleoHQ/improve-parser-tests

Improve parser tests
This commit is contained in:
Collin Chin 2022-03-16 13:36:52 -07:00 committed by GitHub
commit 6ca9a4d870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 4295 additions and 583 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
/tmp/ /tmp/
**.idea/ **.idea/
*.DS_Store *.DS_Store
.vscode
**/process.yml **/process.yml

View File

@ -442,7 +442,7 @@ impl Canonicalizer {
match &console_function_call.function { match &console_function_call.function {
ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args), ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args),
ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args), ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args),
_ => unimplemented!(), // impossible _ => unimplemented!(),
} }
} }
}; };

View File

@ -48,8 +48,8 @@ fn main() -> Result<(), String> {
let input_tree = create_session_if_not_set_then(|_| { let input_tree = create_session_if_not_set_then(|_| {
Handler::with(|handler| { Handler::with(|handler| {
let input = let input =
leo_parser::parse_program_inputs(&handler, input_string.clone(), opt.input_path.to_str().unwrap())?; leo_parser::parse_program_inputs(handler, input_string.clone(), opt.input_path.to_str().unwrap())?;
Ok(input.to_json_string()?) input.to_json_string()
}) })
.map_err(|e| e.to_string()) .map_err(|e| e.to_string())
})?; })?;

View File

@ -47,7 +47,7 @@ fn main() -> Result<(), String> {
// Parses the Leo file constructing an ast which is then serialized. // Parses the Leo file constructing an ast which is then serialized.
let serialized_leo_tree = create_session_if_not_set_then(|_| { let serialized_leo_tree = create_session_if_not_set_then(|_| {
Handler::with(|h| { Handler::with(|h| {
let ast = leo_parser::parse_ast(&h, opt.input_path.to_str().unwrap(), &code)?; let ast = leo_parser::parse_ast(h, opt.input_path.to_str().unwrap(), &code)?;
let json = Ast::to_json_string(&ast)?; let json = Ast::to_json_string(&ast)?;
println!("{}", json); println!("{}", json);
Ok(json) Ok(json)

View File

@ -166,21 +166,15 @@ impl<'a> ParserContext<'a> {
/// the next token is not a [`GroupCoordinate`]. /// the next token is not a [`GroupCoordinate`].
/// ///
fn peek_group_coordinate(&self, i: &mut usize) -> Option<GroupCoordinate> { fn peek_group_coordinate(&self, i: &mut usize) -> Option<GroupCoordinate> {
if *i < 1 { *i = i.checked_sub(1)?;
return None; let token = self.tokens.get(*i)?;
}
let token = self.tokens.get(*i - 1)?;
*i -= 1;
Some(match &token.token { Some(match &token.token {
Token::Add => GroupCoordinate::SignHigh, Token::Add => GroupCoordinate::SignHigh,
Token::Minus if *i > 0 => match self.tokens.get(*i - 1) { Token::Minus => match self.tokens.get(i.checked_sub(1)?) {
Some(SpannedToken { Some(SpannedToken {
token: Token::Int(value), token: Token::Int(value),
span, span,
}) => { }) => {
if *i < 1 {
return None;
}
*i -= 1; *i -= 1;
GroupCoordinate::Number(format_tendril!("-{}", value), span.clone()) GroupCoordinate::Number(format_tendril!("-{}", value), span.clone())
} }
@ -213,57 +207,41 @@ impl<'a> ParserContext<'a> {
/// ///
pub fn eat_group_partial(&mut self) -> Option<Result<(GroupCoordinate, GroupCoordinate, Span)>> { pub fn eat_group_partial(&mut self) -> Option<Result<(GroupCoordinate, GroupCoordinate, Span)>> {
let mut i = self.tokens.len(); let mut i = self.tokens.len();
if i < 1 { let start_span = self.tokens.get(i.checked_sub(1)?)?.span.clone();
return None;
}
let start_span = self.tokens.get(i - 1)?.span.clone();
let first = self.peek_group_coordinate(&mut i)?; let first = self.peek_group_coordinate(&mut i)?;
if i < 1 { i = i.checked_sub(1)?;
if !matches!(
self.tokens.get(i),
Some(SpannedToken {
token: Token::Comma,
..
})
) {
return None; return None;
} }
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Comma, ..
}) => {
i -= 1;
}
_ => {
return None;
}
}
let second = self.peek_group_coordinate(&mut i)?; let second = self.peek_group_coordinate(&mut i)?;
if i < 1 { i = i.checked_sub(1)?;
let right_paren_span = if let Some(SpannedToken {
token: Token::RightParen,
span,
}) = self.tokens.get(i)
{
span.clone()
} else {
return None; return None;
} };
let right_paren_span;
match self.tokens.get(i - 1) { i = i.checked_sub(1)?;
Some(SpannedToken { let end_span = if let Some(SpannedToken {
token: Token::RightParen, token: Token::Group,
span, span,
}) => { }) = self.tokens.get(i)
right_paren_span = span.clone(); {
i -= 1; span.clone()
} } else {
_ => {
return None;
}
}
if i < 1 {
return None; return None;
} };
let end_span;
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Group,
span,
}) => {
end_span = span.clone();
i -= 1;
}
_ => {
return None;
}
}
self.tokens.drain(i..); self.tokens.drain(i..);
if let Err(e) = assert_no_whitespace( if let Err(e) = assert_no_whitespace(

View File

@ -32,7 +32,7 @@ fn eat(input: &[u8], wanted: &str) -> Option<usize> {
if input.len() < wanted.len() { if input.len() < wanted.len() {
return None; return None;
} }
if &input[0..wanted.len()] == wanted { if &input[..wanted.len()] == wanted {
return Some(wanted.len()); return Some(wanted.len());
} }
None None
@ -43,18 +43,15 @@ fn eat(input: &[u8], wanted: &str) -> Option<usize> {
/// An identifier can be eaten if its bytes are at the front of the given `input_tendril` string. /// An identifier can be eaten if its bytes are at the front of the given `input_tendril` string.
/// ///
fn eat_identifier(input_tendril: &StrTendril) -> Option<StrTendril> { fn eat_identifier(input_tendril: &StrTendril) -> Option<StrTendril> {
if input_tendril.is_empty() {
return None;
}
let input = input_tendril.as_bytes(); let input = input_tendril.as_bytes();
if !input[0].is_ascii_alphabetic() { if !input.get(0)?.is_ascii_alphabetic() {
return None; return None;
} }
let mut i = 1usize; let mut i = 1usize;
while i < input.len() { while i < input.len() {
if !input[i].is_ascii_alphanumeric() && input[i] != b'_' { if !input.get(i)?.is_ascii_alphanumeric() && *input.get(i)? != b'_' {
break; break;
} }
i += 1; i += 1;
@ -77,9 +74,7 @@ impl Token {
if escaped.len() != 1 { if escaped.len() != 1 {
return Err(ParserError::lexer_escaped_char_incorrect_length(escaped).into()); return Err(ParserError::lexer_escaped_char_incorrect_length(escaped).into());
} } else if let Some(character) = escaped.chars().next() {
if let Some(character) = escaped.chars().next() {
return match character { return match character {
'0' => Ok(Char::Scalar(0 as char)), '0' => Ok(Char::Scalar(0 as char)),
't' => Ok(Char::Scalar(9 as char)), 't' => Ok(Char::Scalar(9 as char)),
@ -101,15 +96,13 @@ impl Token {
if hex_string.len() != 2 { if hex_string.len() != 2 {
return Err(ParserError::lexer_escaped_hex_incorrect_length(hex_string).into()); return Err(ParserError::lexer_escaped_hex_incorrect_length(hex_string).into());
} } else if let Ok(ascii_number) = u8::from_str_radix(hex_string, 16) {
if let Ok(ascii_number) = u8::from_str_radix(hex_string, 16) {
// According to RFC, we allow only values less than 128. // According to RFC, we allow only values less than 128.
if ascii_number > 127 { if ascii_number > 127 {
return Err(ParserError::lexer_expected_valid_hex_char(ascii_number).into()); return Err(ParserError::lexer_expected_valid_hex_char(ascii_number).into());
} else {
return Ok(Char::Scalar(ascii_number as char));
} }
return Ok(Char::Scalar(ascii_number as char));
} }
} }
@ -125,9 +118,7 @@ impl Token {
let len = unicode_number.len(); let len = unicode_number.len();
if !(1..=6).contains(&len) { if !(1..=6).contains(&len) {
return Err(ParserError::lexer_invalid_escaped_unicode_length(unicode_number).into()); return Err(ParserError::lexer_invalid_escaped_unicode_length(unicode_number).into());
} } else if let Ok(hex) = u32::from_str_radix(unicode_number, 16) {
if let Ok(hex) = u32::from_str_radix(unicode_number, 16) {
if let Some(character) = std::char::from_u32(hex) { if let Some(character) = std::char::from_u32(hex) {
// scalar // scalar
return Ok(Char::Scalar(character)); return Ok(Char::Scalar(character));
@ -141,7 +132,7 @@ impl Token {
if input_tendril.to_string().chars().count() != 1 { if input_tendril.to_string().chars().count() != 1 {
// If char doesn't close. // If char doesn't close.
return Err(ParserError::lexer_char_not_closed(&input_tendril[0..]).into()); return Err(ParserError::lexer_char_not_closed(&input_tendril).into());
} else if let Some(character) = input_tendril.to_string().chars().next() { } else if let Some(character) = input_tendril.to_string().chars().next() {
// If its a simple char. // If its a simple char.
return Ok(Char::Scalar(character)); return Ok(Char::Scalar(character));
@ -167,7 +158,7 @@ impl Token {
while i < input.len() { while i < input.len() {
if i == 1 && input[0] == b'0' && input[i] == b'x' { if i == 1 && input[0] == b'0' && input[i] == b'x' {
return Err(ParserError::lexer_hex_number_provided( return Err(ParserError::lexer_hex_number_provided(
&input_tendril[0..input_tendril.find('\n').unwrap_or(i) + 1], &input_tendril[..input_tendril.find('\n').unwrap_or(i) + 1],
) )
.into()); .into());
} }
@ -291,7 +282,7 @@ impl Token {
} }
if i == input.len() || !end { if i == input.len() || !end {
return Err(ParserError::lexer_string_not_closed(String::from_utf8_lossy(&input[0..i])).into()); return Err(ParserError::lexer_string_not_closed(String::from_utf8_lossy(&input[..i])).into());
} }
return Ok((i + 1, Token::StringLit(string))); return Ok((i + 1, Token::StringLit(string)));
@ -312,7 +303,7 @@ impl Token {
continue; continue;
} else if input[i] & 0x80 > 0 && unicode_char { } else if input[i] & 0x80 > 0 && unicode_char {
i += Self::utf8_byte_count(input[i]); i += Self::utf8_byte_count(input[i]);
return Err(ParserError::lexer_invalid_char(&input_tendril[0..i]).into()); return Err(ParserError::lexer_invalid_char(&input_tendril[..i]).into());
} else if !in_escape || unicode_char { } else if !in_escape || unicode_char {
if input[i] == b'\'' { if input[i] == b'\'' {
end = true; end = true;
@ -321,7 +312,7 @@ impl Token {
return Err(ParserError::lexer_invalid_char( return Err(ParserError::lexer_invalid_char(
// grab the contents of everything between the '' if possible. // grab the contents of everything between the '' if possible.
// else just show the character right before stuff went wrong. // else just show the character right before stuff went wrong.
&input_tendril[0..input_tendril[1..].find('\'').unwrap_or(i - 1) + 1], &input_tendril[..input_tendril[1..].find('\'').unwrap_or(i - 1) + 1],
) )
.into()); .into());
} else if input[i] == b'\\' { } else if input[i] == b'\\' {
@ -350,7 +341,7 @@ impl Token {
} }
if !end { if !end {
return Err(ParserError::lexer_char_not_closed(String::from_utf8_lossy(&input[0..i])).into()); return Err(ParserError::lexer_char_not_closed(String::from_utf8_lossy(&input[..i])).into());
} }
let character = Self::eat_char( let character = Self::eat_char(
@ -422,15 +413,12 @@ impl Token {
let len = if let Some(eol) = eol { eol + 1 } else { input.len() }; let len = if let Some(eol) = eol { eol + 1 } else { input.len() };
return Ok((len, Token::CommentLine(input_tendril.subtendril(0, len as u32)))); return Ok((len, Token::CommentLine(input_tendril.subtendril(0, len as u32))));
} else if eat(input, "/*").is_some() { } else if eat(input, "/*").is_some() {
if input.is_empty() {
return Err(ParserError::lexer_empty_block_comment().into());
}
let eol = input.windows(2).skip(2).position(|x| x[0] == b'*' && x[1] == b'/'); let eol = input.windows(2).skip(2).position(|x| x[0] == b'*' && x[1] == b'/');
let len = if let Some(eol) = eol { let len = if let Some(eol) = eol {
eol + 4 eol + 4
} else { } else {
return Err(ParserError::lexer_block_comment_does_not_close_before_eof( return Err(ParserError::lexer_block_comment_does_not_close_before_eof(
String::from_utf8_lossy(&input[0..]), String::from_utf8_lossy(input),
) )
.into()); .into());
}; };
@ -523,7 +511,7 @@ impl Token {
)); ));
} }
Err(ParserError::could_not_lex(String::from_utf8_lossy(&input[0..])).into()) Err(ParserError::could_not_lex(String::from_utf8_lossy(input)).into())
} }
} }

View File

@ -195,7 +195,7 @@ impl TryFrom<&Path> for Manifest {
if line.starts_with("remote") { if line.starts_with("remote") {
let remote = line let remote = line
.split('=') // Split the line as 'remote' = '"{author}/{package_name}"' .split('=') // Split the line as 'remote' = '"{author}/{package_name}"'
.collect::<Vec<&str>>()[1]; // Fetch just '"{author}/{package_name}"' .nth(1).unwrap(); // Fetch just '"{author}/{package_name}"'
old_remote_format = Some(remote); old_remote_format = Some(remote);
// Retain the old remote format if the `manifest_refactor_remote` is not enabled // Retain the old remote format if the `manifest_refactor_remote` is not enabled
@ -238,8 +238,8 @@ impl TryFrom<&Path> for Manifest {
// Fetch the author from the old remote. // Fetch the author from the old remote.
let remote_author = old_remote let remote_author = old_remote
.split('/') // Split the old remote as '"{author}' and '{package_name}"' .split('/') // Split the old remote as '"{author}' and '{package_name}"'
.collect::<Vec<&str>>()[0] // Fetch just the '"{author}' .next().unwrap() // Fetch just the '"{author}'
.replace(&['\"', ' '][..], ""); // Remove the quotes from the author string .replace(&['\"', ' '], ""); // Remove the quotes from the author string
// Construct the new remote section. // Construct the new remote section.
let new_remote = format!( let new_remote = format!(

View File

@ -90,7 +90,7 @@ impl Serialize for Span {
} else { } else {
state.serialize_field("path", "")?; state.serialize_field("path", "")?;
} }
state.serialize_field("content", &self.content[..])?; state.serialize_field("content", self.content.as_ref())?;
state.end() state.end()
} }
} }

View File

@ -21,7 +21,7 @@ use tendril::StrTendril;
/// Serialization for the StrTendril type. /// Serialization for the StrTendril type.
pub fn serialize<S: Serializer>(tendril: &StrTendril, serializer: S) -> Result<S::Ok, S::Error> { pub fn serialize<S: Serializer>(tendril: &StrTendril, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&tendril[..]) serializer.serialize_str(tendril)
} }
/// Deserialization for the StrTendril type. /// Deserialization for the StrTendril type.

View File

@ -5,6 +5,7 @@ outputs:
- "'a' @ 1:1-4" - "'a' @ 1:1-4"
- "'Z' @ 1:1-4" - "'Z' @ 1:1-4"
- "'\"' @ 1:1-5" - "'\"' @ 1:1-5"
- "''' @ 1:1-5"
- "'' @ 1:1-5" - "'' @ 1:1-5"
- "'' @ 1:1-5" - "'' @ 1:1-5"
- "'\u0000' @ 1:1-5" - "'\u0000' @ 1:1-5"
@ -14,6 +15,7 @@ outputs:
- "'å' @ 1:1-5" - "'å' @ 1:1-5"
- "'Ӡ' @ 1:1-10" - "'Ӡ' @ 1:1-10"
- "'Ӡ' @ 1:1-5" - "'Ӡ' @ 1:1-5"
- "'55296' @ 1:1-11"
- "'❤' @ 1:1-11" - "'❤' @ 1:1-11"
- "'❤' @ 1:1-6" - "'❤' @ 1:1-6"
- "'😢' @ 1:1-12" - "'😢' @ 1:1-12"

View File

@ -3,12 +3,15 @@ namespace: Token
expectation: Fail expectation: Fail
outputs: outputs:
- "Error [EPAR0370028]: Expected a closed char but found `'\\'`." - "Error [EPAR0370028]: Expected a closed char but found `'\\'`."
- "Error [EPAR0370032]: Could not lex the following content: `\\`."
- "Error [EPAR0370028]: Expected a closed char but found `'\\`."
- "Error [EPAR0370032]: Could not lex the following content: `\\n`."
- "Error [EPAR0370028]: Expected a closed char but found `'a`." - "Error [EPAR0370028]: Expected a closed char but found `'a`."
- "Error [EPAR0370024]: Expected more characters to lex but found none." - "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370036]: Expected a valid hex character but found `154`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `7`." - "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `7`."
- "Error [EPAR0370028]: Expected a closed char but found `\\x7g`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `z`." - "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `z`."
- "Error [EPAR0370036]: Expected a valid hex character but found `154`."
- "Error [EPAR0370028]: Expected a closed char but found `\\x7g`."
- "Error [EPAR0370036]: Expected a valid hex character but found `128`." - "Error [EPAR0370036]: Expected a valid hex character but found `128`."
- "Error [EPAR0370036]: Expected a valid hex character but found `193`." - "Error [EPAR0370036]: Expected a valid hex character but found `193`."
- "Error [EPAR0370036]: Expected a valid hex character but found `194`." - "Error [EPAR0370036]: Expected a valid hex character but found `194`."
@ -17,7 +20,6 @@ outputs:
- "Error [EPAR0370036]: Expected a valid hex character but found `224`." - "Error [EPAR0370036]: Expected a valid hex character but found `224`."
- "Error [EPAR0370036]: Expected a valid hex character but found `159`." - "Error [EPAR0370036]: Expected a valid hex character but found `159`."
- "Error [EPAR0370028]: Expected a closed char but found `abcdefg`." - "Error [EPAR0370028]: Expected a closed char but found `abcdefg`."
- "Error [EPAR0370033]: Could not lex the following escaped char due to being given more than one char: `t\\t`."
- "Error [EPAR0370026]: Expected a valid escape character but found `a`." - "Error [EPAR0370026]: Expected a valid escape character but found `a`."
- "Error [EPAR0370026]: Expected a valid escape character but found `z`." - "Error [EPAR0370026]: Expected a valid escape character but found `z`."
- "Error [EPAR0370026]: Expected a valid escape character but found `A`." - "Error [EPAR0370026]: Expected a valid escape character but found `A`."
@ -27,18 +29,20 @@ outputs:
- "Error [EPAR0370026]: Expected a valid escape character but found `*`." - "Error [EPAR0370026]: Expected a valid escape character but found `*`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: ``." - "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: ``."
- "Error [EPAR0370026]: Expected a valid escape character but found `39`." - "Error [EPAR0370026]: Expected a valid escape character but found `39`."
- "Error [EPAR0370038]: The escaped unicode char `bbbbb}\\u{aaaa` is not within valid length of [1, 6]." - "Error [EPAR0370033]: Could not lex the following escaped char due to being given more than one char: `t\\t`."
- "Error [EPAR0370026]: Expected a valid escape character but found `122`." - "Error [EPAR0370026]: Expected a valid escape character but found `122`."
- "Error [EPAR0370026]: Expected a valid escape character but found `49`." - "Error [EPAR0370026]: Expected a valid escape character but found `49`."
- "Error [EPAR0370026]: Expected a valid escape character but found `125`."
- "Error [EPAR0370029]: Expected valid character but found `'🦀\\n`."
- "Error [EPAR0370026]: Expected a valid escape character but found `49`." - "Error [EPAR0370026]: Expected a valid escape character but found `49`."
- "Error [EPAR0370029]: Expected valid character but found `'🦀1🦀`."
- "Error [EPAR0370026]: Expected a valid escape character but found `54`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{af🦀`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{2764z`." - "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{2764z`."
- "Error [EPAR0370028]: Expected a closed char but found `\\u{276g}`." - "Error [EPAR0370028]: Expected a closed char but found `\\u{276g}`."
- "Error [EPAR0370026]: Expected a valid escape character but found `48`."
- "Error [EPAR0370026]: Expected a valid escape character but found `48`."
- "Error [EPAR0370026]: Expected a valid escape character but found `57`." - "Error [EPAR0370026]: Expected a valid escape character but found `57`."
- "Error [EPAR0370026]: Expected a valid escape character but found `48`."
- "Error [EPAR0370026]: Expected a valid escape character but found `48`."
- "Error [EPAR0370039]: The escaped unicode char `110000` is greater than 0x10FFFF." - "Error [EPAR0370039]: The escaped unicode char `110000` is greater than 0x10FFFF."
- "Error [EPAR0370026]: Expected a valid escape character but found `125`." - "Error [EPAR0370038]: The escaped unicode char `bbbbb}\\u{aaaa` is not within valid length of [1, 6]."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{af🦀`."
- "Error [EPAR0370029]: Expected valid character but found `'🦀\\n`."
- "Error [EPAR0370029]: Expected valid character but found `'🦀1🦀`."
- "Error [EPAR0370029]: Expected valid character but found `'😭😂`." - "Error [EPAR0370029]: Expected valid character but found `'😭😂`."

View File

@ -0,0 +1,15 @@
---
namespace: ParseExpression
expectation: Fail
outputs:
- "Error [EPAR0370031]: Block comment does not close with content: `/*`."
- "Error [EPAR0370031]: Block comment does not close with content: `/* test`."
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '/'\n --> test:1:1\n |\n 1 | / /\n | ^"
- "Error [EPAR0370031]: Block comment does not close with content: `/*/`."
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '*'\n --> test:1:1\n |\n 1 | */\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀**/`."
- "Error [EPAR0370032]: Could not lex the following content: `🦀*/`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*🦀/`."
- "Error [EPAR0370031]: Block comment does not close with content: `/**🦀`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*🦀`."
- "Error [EPAR0370031]: Block comment does not close with content: `/*/*`."

View File

@ -680,3 +680,35 @@ outputs:
col_stop: 16 col_stop: 16
path: "" path: ""
content: "(123, 456)group" content: "(123, 456)group"
- Value:
Group:
Single:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: 1group
- Unary:
inner:
Value:
Group:
Single:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 2
col_stop: 8
path: ""
content: "-1group"
op: Negate
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "-1group"

View File

@ -10,3 +10,7 @@ outputs:
- "did not consume all input: 'group' @ 1:6-11\n" - "did not consume all input: 'group' @ 1:6-11\n"
- "did not consume all input: 'group' @ 1:12-17\n" - "did not consume all input: 'group' @ 1:12-17\n"
- "did not consume all input: 'group' @ 1:15-20\n" - "did not consume all input: 'group' @ 1:15-20\n"
- "Error [EPAR0370004]: Unexpected white space between terms (123,456) and group\n --> test:1:10\n |\n 1 | (123, 456) group\n | ^"
- "did not consume all input: 'group' @ 1:8-13\n"
- "did not consume all input: 'group' @ 1:16-21\n"
- "did not consume all input: 'bool' @ 1:11-15\n"

View File

@ -0,0 +1,7 @@
---
namespace: Token
expectation: Fail
outputs:
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0x..` was provided but hex is not allowed."

View File

@ -32,6 +32,16 @@ outputs:
col_stop: 9 col_stop: 9
path: "" path: ""
content: 456field content: 456field
- Value:
Implicit:
- ""
- span:
line_start: 0
line_stop: 0
col_start: 0
col_stop: 0
path: ""
content: ""
- Value: - Value:
Field: Field:
- "87377802873778028737780287377802873778028737780287377802873778028737780287377802" - "87377802873778028737780287377802873778028737780287377802873778028737780287377802"

View File

@ -2,7 +2,6 @@
namespace: Token namespace: Token
expectation: Pass expectation: Pass
outputs: outputs:
- "'\"\"' @ 1:1-3"
- "'\"string\"' @ 1:1-9" - "'\"string\"' @ 1:1-9"
- "'\"another { } string\"' @ 1:1-21" - "'\"another { } string\"' @ 1:1-21"
- "'\"{ ] [ ; a\"' @ 1:1-12" - "'\"{ ] [ ; a\"' @ 1:1-12"
@ -14,6 +13,19 @@ outputs:
- "'\"\n\"' @ 1:1-8" - "'\"\n\"' @ 1:1-8"
- "'\"\n\"' @ 1:1-7" - "'\"\n\"' @ 1:1-7"
- "'\"\u007f\"' @ 1:1-7" - "'\"\u007f\"' @ 1:1-7"
- "'\"aa \\ \" \n aa \t \r \u0000\"' @ 1:1-28" - "'\"aa \\ \" ' \n aa \t \r \u0000\"' @ 1:1-30"
- "'\"test \"' @ 1:1-15" - "'\"test \"' @ 1:1-15"
- "'\"\"' @ 1:1-15" - "'\"\"' @ 1:1-15"
- "'\"\"' @ 1:1-10"
- "'\"\"' @ 1:1-7"
- "'\"\"' @ 1:1-6"
- "'\"\"' @ 1:1-12"
- "'\"\"' @ 1:1-17"
- "'\"ヽಠ\"' @ 1:1-26"
- "'\"(╯\"' @ 1:1-33"
- "'\"┬ノ ゜゜\"' @ 1:1-29"
- "'\"( ͜͡͡\"' @ 1:1-20"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"ᕙ(▀̿ĺ̯▀̿ ̿)ᕗ\"' @ 1:5-69"
- "'\"♥-_-]\"' @ 1:1-20"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"(⑅∫°ਊ°)∫\"' @ 1:5-62"
- "'\"b\"' @ 1:1-4,'// TODO reenabe once #1682 is closed \"🦀°1\"' @ 1:5-51"

View File

@ -4,6 +4,7 @@ expectation: Fail
outputs: outputs:
- "Error [EPAR0370027]: Expected a closed string but found `\"Hello world!`." - "Error [EPAR0370027]: Expected a closed string but found `\"Hello world!`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\\"`." - "Error [EPAR0370027]: Expected a closed string but found `\"\\\"`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\`."
- "Error [EPAR0370026]: Expected a valid escape character but found `l`." - "Error [EPAR0370026]: Expected a valid escape character but found `l`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\uaaa\"`." - "Error [EPAR0370027]: Expected a closed string but found `\"\\uaaa\"`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\u\"`." - "Error [EPAR0370027]: Expected a closed string but found `\"\\u\"`."
@ -11,3 +12,5 @@ outputs:
- "Error [EPAR0370027]: Expected a closed string but found `\"\\x\"`." - "Error [EPAR0370027]: Expected a closed string but found `\"\\x\"`."
- "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `\\u}`." - "Error [EPAR0370042]: There was no opening `{` after starting an escaped unicode `\\u}`."
- "Error [EPAR0370043]: There was an emoji found in the escaped unicode character: `\"\\u6🦀`." - "Error [EPAR0370043]: There was an emoji found in the escaped unicode character: `\"\\u6🦀`."
- "Error [EPAR0370043]: There was an emoji found in the escaped unicode character: `\"\\u{af🦀`."
- "Error [EPAR0370032]: Could not lex the following content: `⭇😍;`."

View File

@ -122,3 +122,24 @@ outputs:
col_stop: 4 col_stop: 4
path: "" path: ""
content: "-!x" content: "-!x"
- Value:
Implicit:
- "-5"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 3
path: ""
content: "-5"
- Value:
Integer:
- I8
- "-5"
- span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "-5i8"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370003]: unexpected EOF\n --> test:3:1\n |\n 3 | const\n | ^^^^^"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370032]: Could not lex the following content: `\\`."

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x::y = y;\n | ^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | 5 = y;\n | ^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x + x = y;\n | ^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | -x = y;\n | ^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | !x = y;\n | ^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | a? x : x = y;\n | ^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x as u32 = y;\n | ^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | [x, x, x] = y;\n | ^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | [x; 3] = y;\n | ^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | (x, x, x) = y;\n | ^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x {x: y, y: z} = y;\n | ^^^^^^^^^^^^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x() = y;\n | ^^^"
- "Error [EPAR0370011]: invalid assignment target\n --> test:1:1\n |\n 1 | x.y() = y;\n | ^^^^^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀 = y;`."

View File

@ -0,0 +1,6 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'formatted string', got '1'\n --> test:1:13\n |\n 1 | console.log(1);\n | ^"
- "Error [EPAR0370007]: unexpected identifier: expected 'assert', 'error', 'log' -- got 'test'\n --> test:1:9\n |\n 1 | console.test();\n | ^^^^"

View File

@ -1540,3 +1540,132 @@ outputs:
col_stop: 37 col_stop: 37
path: "" path: ""
content: "let x: [[u8; 2]; 2] = [[0,0], [0,0]];" content: "let x: [[u8; 2]; 2] = [[0,0], [0,0]];"
- Definition:
declaration_type: Let
variable_names:
- mutable: true
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"let x: [u8; (2, 2)] = [[0,0], [0,0]];\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
type_:
Array:
- IntegerType: U8
- - value: "2"
- value: "2"
value:
ArrayInline:
elements:
- Expression:
ArrayInline:
elements:
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 25
col_stop: 26
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 27
col_stop: 28
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 24
col_stop: 29
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
ArrayInline:
elements:
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 32
col_stop: 33
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Expression:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 34
col_stop: 35
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 31
col_stop: 36
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 23
col_stop: 37
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 37
path: ""
content: "let x: [u8; (2, 2)] = [[0,0], [0,0]];"
- Definition:
declaration_type: Let
variable_names:
- mutable: true
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"
type_: Address
value:
Value:
Address:
- aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53
- span:
line_start: 1
line_stop: 1
col_start: 18
col_stop: 81
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 81
path: ""
content: "let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;"

View File

@ -25,5 +25,24 @@ outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:10\n |\n 1 | let (x,y,,) = ();\n | ^" - "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:10\n |\n 1 | let (x,y,,) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:6\n |\n 1 | let (,x,y) = ();\n | ^" - "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:6\n |\n 1 | let (,x,y) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:8\n |\n 1 | let (x,,y) = ();\n | ^" - "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:8\n |\n 1 | let (x,,y) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'int', got ','\n --> test:1:16\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^\nError [EPAR0370045]: do not put parens around single dimension array size\n --> test:1:13\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^^^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'const'\n --> test:1:8\n |\n 1 | let x: const = expr;\n | ^^^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'let'\n --> test:1:10\n |\n 1 | const x: let = expr;\n | ^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got 'mut'\n --> test:1:8\n |\n 1 | let x: mut = expr;\n | ^^^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:1\n |\n 1 | let\n | ^^^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:5\n |\n 1 | let x\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:6\n |\n 1 | let x:\n | ^"
- "Error [EPAR0370005]: expected ) -- got ']'\n --> test:1:14\n |\n 1 | let x = (a, y]);\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '='\n --> test:1:5\n |\n 1 | let = 1u8;\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ';'\n --> test:1:4\n |\n 1 | let;\n | ^"
- "Error [EPAR0370005]: expected = -- got '1'\n --> test:1:7\n |\n 1 | let x 1u8;\n | ^"
- "Error [EPAR0370005]: expected = -- got ';'\n --> test:1:10\n |\n 1 | let x: u8;\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:8\n |\n 1 | let x: u8\n | ^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool', 'char' -- got '='\n --> test:1:8\n |\n 1 | let x: = 1;\n | ^"
- "Error [EPAR0370005]: expected ; -- got ']'\n --> test:1:11\n |\n 1 | let x: [u8] = 1;\n | ^"
- "Error [EPAR0370003]: unexpected EOF\n --> test:1:11\n |\n 1 | let x: [u8;\n | ^"
- "Error [EPAR0370005]: expected ] -- got 'u8'\n --> test:1:14\n |\n 1 | let x: [u8; 1u8] = [1,\n | ^^"
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ']'\n --> test:1:15\n |\n 1 | let dbg: u8 = ];\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `🦀: u8 = 0;`."
- "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:11\n |\n 1 | let (x) = ...;\n | ^^^" - "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:11\n |\n 1 | let (x) = ...;\n | ^^^"
- "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x,) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:12\n |\n 1 | let (x,) = ...;\n | ^^^" - "Error [EPAR0370044]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x,) = ...;\n | ^\nError [EPAR0370009]: unexpected string: expected 'expression', got '...'\n --> test:1:12\n |\n 1 | let (x,) = ...;\n | ^^^"

View File

@ -0,0 +1,10 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ']'\n --> test:1:2\n |\n 1 | (];\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ')'\n --> test:1:2\n |\n 1 | [);\n | ^"
- "Error [EPAR0370032]: Could not lex the following content: `\\y;`."
- "Error [EPAR0370032]: Could not lex the following content: `|;`."
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '}'\n --> test:1:3\n |\n 1 | x[};\n | ^"
- "Error [EPAR0370005]: expected ) -- got ']'\n --> test:1:6\n |\n 1 | (x, y];\n | ^"

View File

@ -11,4 +11,4 @@ x[x][y][z]
x[0]() x[0]()
x()[0] x()[0]
x(y)::y(x) x(y)::y(x)
x[x].0[x] x[x].0[x]

View File

@ -6,6 +6,7 @@ expectation: Pass
'a' 'a'
'Z' 'Z'
'\"' '\"'
'\''
'\t' '\t'
'\r' '\r'
'\0' '\0'
@ -15,6 +16,7 @@ expectation: Pass
'å' 'å'
'\u{4e0}' '\u{4e0}'
'Ӡ' 'Ӡ'
'\u{d800}'
'\u{2764}' '\u{2764}'
'❤' '❤'
'\u{1F622}' '\u{1F622}'

View File

@ -4,15 +4,18 @@ expectation: Fail
*/ */
'\' '\'
\
'\
\n
'a 'a
'' ''
'\x9A'
'\x7' '\x7'
'\x7g'
'\xz' '\xz'
'\x9A'
'\x7g'
'\x80' '\x80'
'\xc1' '\xc1'
'\xc2' '\xc2'
@ -23,7 +26,6 @@ expectation: Fail
'abcdefg' 'abcdefg'
'\t\t'
'\a' '\a'
'\z' '\z'
'\A' '\A'
@ -33,20 +35,22 @@ expectation: Fail
'\*' '\*'
'\x' '\x'
'\u' '\u'
'\t\t'
'\u{bbbbb}\u{aaaa}'
'\uz' '\uz'
'\u1' '\u1'
'\u};
'🦀\n'
'\u123' '\u123'
'🦀1🦀'
'\u6🦀}'
'\u{af🦀'
'\u{2764z' '\u{2764z'
'\u{276g}' '\u{276g}'
'\u9999999'
'\u00000000' '\u00000000'
'\u01000000' '\u01000000'
'\u9999999'
'\u{110000}' '\u{110000}'
'\u}' '\u{bbbbb}\u{aaaa}'
'\u{af🦀'
'🦀\n'
'🦀1🦀'
'😭😂😘' '😭😂😘'

View File

@ -0,0 +1,26 @@
/*
namespace: ParseExpression
expectation: Fail
*/
/*
/* test
/ /
/*/
*/
🦀**/
/🦀*/
/*🦀/
/**🦀
/*🦀
/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

View File

@ -66,3 +66,7 @@ expectation: Pass
(123, 456)group (123, 456)group
(123, 456)group (123, 456)group
1group
-1group

View File

@ -18,3 +18,11 @@ expectation: Fail
(123,456u8)group (123,456u8)group
(123,456field)group (123,456field)group
(123, 456) group
(123, )group
(123, 456, 789)group
(123, 456)bool

View File

@ -0,0 +1,8 @@
/*
namespace: Token
expectation: Fail
*/
0xb
0x
0xbfield

View File

@ -8,6 +8,8 @@ expectation: Pass
123 123
456field 456field
// 0xbfield
87377802873778028737780287377802873778028737780287377802873778028737780287377802field 87377802873778028737780287377802873778028737780287377802873778028737780287377802field
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802field 8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802field

View File

@ -3,112 +3,112 @@ namespace: ParseExpression
expectation: Pass expectation: Pass
*/ */
123u8 123u16
123 123
456u8 456u16
87377802873778028737780287377802873778028737780287377802873778028737780287377802u8 87377802873778028737780287377802873778028737780287377802873778028737780287377802u16
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802u8 8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802u16
340130024u8 340130024u16
158951116u8 158951116u16
155529659u8 155529659u16
642023166u8 642023166u16
228481736u8 228481736u16
469712960u8 469712960u16
929437719u8 929437719u16
721072814u8 721072814u16
363254789u8 363254789u16
906732565u8 906732565u16
288246391u8 288246391u16
724940549u8 724940549u16
487101620u8 487101620u16
261373583u8 261373583u16
891163927u8 891163927u16
743967544u8 743967544u16
8372586u8 8372586u16
461793278u8 461793278u16
806307045u8 806307045u16
122764546u8 122764546u16
356336181u8 356336181u16
158370903u8 158370903u16
774460877u8 774460877u16
557174131u8 557174131u16
492401267u8 492401267u16
893445620u8 893445620u16
957757048u8 957757048u16
721540649u8 721540649u16
390746493u8 390746493u16
211251725u8 211251725u16
938266114u8 938266114u16
156985870u8 156985870u16
703831126u8 703831126u16
729964155u8 729964155u16
988151305u8 988151305u16
320872435u8 320872435u16
719287167u8 719287167u16
152289486u8 152289486u16
740067975u8 740067975u16
728627816u8 728627816u16
385008978u8 385008978u16
553967635u8 553967635u16
71980713u8 71980713u16
519444716u8 519444716u16
116499965u8 116499965u16
717422268u8 717422268u16
18966279u8 18966279u16
22458638u8 22458638u16
857282620u8 857282620u16
920675898u8 920675898u16
762235516u8 762235516u16
469018377u8 469018377u16
199986521u8 199986521u16
536679358u8 536679358u16
591399452u8 591399452u16
83083158u8 83083158u16
599449051u8 599449051u16
445442318u8 445442318u16
585486590u8 585486590u16
209278800u8 209278800u16
873568117u8 873568117u16
664470940u8 664470940u16
465262783u8 465262783u16
605652874u8 605652874u16
376803940u8 376803940u16
965247040u8 965247040u16
598474509u8 598474509u16
845119918u8 845119918u16
648159133u8 648159133u16
669051032u8 669051032u16
800600261u8 800600261u16
434689764u8 434689764u16
520060080u8 520060080u16
804659385u8 804659385u16
537828058u8 537828058u16
716600292u8 716600292u16
387020273u8 387020273u16
199375617u8 199375617u16
680337189u8 680337189u16
818479931u8 818479931u16
893693281u8 893693281u16
87377802u8 87377802u16
84699261u8 84699261u16
292826090u8 292826090u16
569171405u8 569171405u16
387436237u8 387436237u16
150682190u8 150682190u16
888770419u8 888770419u16
824696431u8 824696431u16
765659803u8 765659803u16
270163693u8 270163693u16
427940240u8 427940240u16
504997332u8 504997332u16
337808338u8 337808338u16
907200008u8 907200008u16
757177889u8 757177889u16
696697188u8 696697188u16
41376051u8 41376051u16
496293518u8 496293518u16
251218820u8 251218820u16

View File

@ -3,8 +3,6 @@ namespace: Token
expectation: Pass expectation: Pass
*/ */
""
"string" "string"
"another { } string" "another { } string"
@ -22,7 +20,23 @@ expectation: Pass
"\x7F" "\x7F"
"aa \\ \" \n aa \t \r \0" "aa \\ \" \' \n aa \t \r \0"
"test 😒€" "test 😒€"
"😭😂😘" "😭😂😘"
"✋🏿"
"🦀"
"￿"
"<22><><EFBFBD>"
"><)三"
"ヽ༼ ಠ益ಠ ༽ノ"
"(╯°□°)╯︵ ┻━┻"
"┬─┬ ( ゜-゜ノ)"
"( ͡° ͜ʖ ͡°)"
"b" // TODO reenabe once #1682 is closed "ᕙ(▀̿ĺ̯▀̿ ̿)ᕗ"
"♥╣[-_-]╠♥"
"b" // TODO reenabe once #1682 is closed "(⑅∫°ਊ°)∫"
"b" // TODO reenabe once #1682 is closed "🦀°1"

View File

@ -7,6 +7,8 @@ expectation: Fail
"\" "\"
"\
"\l" "\l"
"\uaaa" "\uaaa"
@ -19,4 +21,8 @@ expectation: Fail
"\u}" "\u}"
"\u6🦀}" "\u6🦀}"
"\u{af🦀"
"\" // TODO reenable once #1683 is closed "⭇😍;

View File

@ -1,26 +0,0 @@
/*
namespace: ParseExpression
expectation: Pass
*/
"string"
"another { } string"
"{ ] [ ; a"
"\u{FFA}"
"\u{afafa}"
"\u{afaf}"
"\u{afa}"
"\u{af}"
"\u{a}"
"\x0A"
"\x7F"
"aa \\ \" \n aa \t \r \0"
"test 😒€"
"😭😂😘"

View File

@ -9,3 +9,6 @@ expectation: Pass
-x() -x()
--x --x
-!x -!x
-5
-5i8

View File

@ -0,0 +1,6 @@
/*
namespace: Parse
expectation: Fail
*/
const

View File

@ -0,0 +1,9 @@
/*
namespace: Parse
expectation: Fail
*/
function main() {
let x = 1u8;
}
\

View File

@ -29,3 +29,162 @@ x[2..] = y;
x[..] = y; x[..] = y;
x.0[0][..] = y; x.0[0][..] = y;
x.y = y;
x.0.y[0].1.y[..][0][1..5][0..3] = y;
x += expr;
x += ();
x += x+y;
x += x();
x[0] += y;
x[0u32] += y;
x.0 += y;
x[1..2][0] += y;
x[..2][0] += y;
x[2..][0] += y;
x[..][0] += y;
x.0[0][..][0] += y;
x.y += y;
x.0.y[0].1.y[..][0][1..5][0..3][0] += y;
x -= expr;
x -= ();
x -= x+y;
x -= x();
x[0] -= y;
x[0u32] -= y;
x.0 -= y;
x[1..2][0] -= y;
x[..2][0] -= y;
x[2..][0] -= y;
x[..][0] -= y;
x.0[0][..][0] -= y;
x.y -= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] -= y;
x *= expr;
x *= ();
x *= x+y;
x *= x();
x[0] *= y;
x[0u32] *= y;
x.0 *= y;
x[1..2][0] *= y;
x[..2][0] *= y;
x[2..][0] *= y;
x[..][0] *= y;
x.0[0][..][0] *= y;
x.y *= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] *= y;
x /= expr;
x /= ();
x /= x+y;
x /= x();
x[0] /= y;
x[0u32] /= y;
x.0 /= y;
x[1..2][0] /= y;
x[..2][0] /= y;
x[2..][0] /= y;
x[..][0] /= y;
x.0[0][..][0] /= y;
x.y /= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] /= y;
x **= expr;
x **= ();
x **= x+y;
x **= x();
x[0] *= y;
x[0u32] *= y;
x.0 **= y;
x[1..2][0] **= y;
x[..2][0] **= y;
x[2..][0] **= y;
x[..][0] **= y;
x.0[0][..][0] **= y;
x.y **= y;
x.0.y[0].1.y[..][0][1..5][0..3][0] **= y;

View File

@ -0,0 +1,32 @@
/*
namespace: ParseStatement
expectation: Fail
*/
x::y = y;
5 = y;
x + x = y;
-x = y;
!x = y;
a? x : x = y;
x as u32 = y;
[x, x, x] = y;
[x; 3] = y;
(x, x, x) = y;
x {x: y, y: z} = y;
x() = y;
x.y() = y;
🦀 = y;

View File

@ -0,0 +1,8 @@
/*
namespace: ParseStatement
expectation: Fail
*/
console.log(1);
console.test();

View File

@ -98,3 +98,8 @@ const (x, y): u32 = x();
let (x,y,) = (); let (x,y,) = ();
let x: [[u8; 2]; 2] = [[0,0], [0,0]]; let x: [[u8; 2]; 2] = [[0,0], [0,0]];
let x: [u8; (2, 2)] = [[0,0], [0,0]];
let x: address = aleo15u4r0gzjtqzepkgurgn7p3u5kkhs9p74rx6aun3uh2s5std6759svgmg53;

View File

@ -53,6 +53,45 @@ let (,x,y) = ();
let (x,,y) = (); let (x,,y) = ();
let x: [u8; (2,,)] = [[0,0], [0,0]];
let x: const = expr;
const x: let = expr;
let x: mut = expr;
let
let x
let x:
let x = (a, y]);
let = 1u8;
let;
let x 1u8;
let x: u8;
let x: u8
let x: = 1;
let x: [u8] = 1;
let x: [u8;
let x: [u8; 1u8] = [1,
let dbg: u8 = ];
let 🦀: u8 = 0;
let (x) = ...; let (x) = ...;
let (x,) = ...; let (x,) = ...;

View File

@ -0,0 +1,16 @@
/*
namespace: ParseStatement
expectation: Fail
*/
(];
[);
x\y;
(x,y|;
x[};
(x, y];

View File

@ -27,19 +27,28 @@ pub struct TestFailure {
#[derive(Debug)] #[derive(Debug)]
pub enum TestError { pub enum TestError {
Panicked {
test: String,
index: usize,
error: String,
},
UnexpectedOutput { UnexpectedOutput {
test: String,
index: usize, index: usize,
expected: Value, expected: Value,
output: Value, output: Value,
}, },
PassedAndShouldntHave { PassedAndShouldntHave {
test: String,
index: usize, index: usize,
}, },
FailedAndShouldntHave { FailedAndShouldntHave {
test: String,
index: usize, index: usize,
error: String, error: String,
}, },
UnexpectedError { UnexpectedError {
test: String,
index: usize, index: usize,
expected: String, expected: String,
output: String, output: String,
@ -50,30 +59,64 @@ pub enum TestError {
impl fmt::Display for TestError { impl fmt::Display for TestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let format_test = |test: &str| -> String {
if test.len() > 50 {
String::new()
} else {
format!("\n\n{}\n\n", test)
}
};
match self { match self {
TestError::Panicked { test, index, error } => {
write!(
f,
"test #{}: {}encountered a rust panic:\n{}",
index + 1,
format_test(test),
error
)
}
TestError::UnexpectedOutput { TestError::UnexpectedOutput {
test,
index, index,
expected, expected,
output, output,
} => { } => {
write!( write!(
f, f,
"test #{} expected\n{}\ngot\n{}", "test #{}: {}expected\n{}\ngot\n{}",
index + 1, index + 1,
format_test(test),
serde_yaml::to_string(&expected).expect("serialization failed"), serde_yaml::to_string(&expected).expect("serialization failed"),
serde_yaml::to_string(&output).expect("serialization failed") serde_yaml::to_string(&output).expect("serialization failed")
) )
} }
TestError::PassedAndShouldntHave { index } => write!(f, "test #{} passed and shouldn't have", index + 1), TestError::PassedAndShouldntHave { test, index } => {
TestError::FailedAndShouldntHave { index, error } => { write!(f, "test #{}: {}passed and shouldn't have", index + 1, format_test(test))
write!(f, "test #{} failed and shouldn't have:\n{}", index + 1, error) }
TestError::FailedAndShouldntHave { test, index, error } => {
write!(
f,
"test #{}: {}failed and shouldn't have:\n{}",
index + 1,
format_test(test),
error
)
} }
TestError::UnexpectedError { TestError::UnexpectedError {
test,
expected, expected,
output, output,
index, index,
} => { } => {
write!(f, "test #{} expected error\n{}\ngot\n{}", index + 1, expected, output) write!(
f,
"test #{}: {}expected error\n{}\ngot\n{}",
index + 1,
format_test(test),
expected,
output
)
} }
TestError::MismatchedTestExpectationLength => write!(f, "invalid number of test expectations"), TestError::MismatchedTestExpectationLength => write!(f, "invalid number of test expectations"),
TestError::MissingTestConfig => write!(f, "missing test config"), TestError::MissingTestConfig => write!(f, "missing test config"),
@ -82,18 +125,25 @@ impl fmt::Display for TestError {
} }
pub fn emit_errors( pub fn emit_errors(
output: Result<&Value, &str>, test: &str,
output: &Result<Result<Value, String>, String>,
mode: &TestExpectationMode, mode: &TestExpectationMode,
expected_output: Option<Value>, expected_output: Option<Value>,
test_index: usize, test_index: usize,
) -> Option<TestError> { ) -> Option<TestError> {
match (output, mode) { match (output, mode) {
(Ok(output), TestExpectationMode::Pass) => { (Err(e), _) => Some(TestError::Panicked {
test: test.to_string(),
index: test_index,
error: e.to_string(),
}),
(Ok(Ok(output)), TestExpectationMode::Pass) => {
// passed and should have // passed and should have
if let Some(expected_output) = expected_output.as_ref() { if let Some(expected_output) = expected_output.as_ref() {
if output != expected_output { if output != expected_output {
// invalid output // invalid output
return Some(TestError::UnexpectedOutput { return Some(TestError::UnexpectedOutput {
test: test.to_string(),
index: test_index, index: test_index,
expected: expected_output.clone(), expected: expected_output.clone(),
output: output.clone(), output: output.clone(),
@ -102,18 +152,23 @@ pub fn emit_errors(
} }
None None
} }
(Ok(_tokens), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave { index: test_index }), (Ok(Ok(_tokens)), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave {
(Err(err), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave { test: test.to_string(),
index: test_index,
}),
(Ok(Err(err)), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave {
test: test.to_string(),
error: err.to_string(), error: err.to_string(),
index: test_index, index: test_index,
}), }),
(Err(err), TestExpectationMode::Fail) => { (Ok(Err(err)), TestExpectationMode::Fail) => {
let expected_output: Option<String> = let expected_output: Option<String> =
expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed")); expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed"));
if let Some(expected_output) = expected_output.as_deref() { if let Some(expected_output) = expected_output.as_deref() {
if err != expected_output { if err != expected_output {
// invalid output // invalid output
return Some(TestError::UnexpectedError { return Some(TestError::UnexpectedError {
test: test.to_string(),
expected: expected_output.to_string(), expected: expected_output.to_string(),
output: err.to_string(), output: err.to_string(),
index: test_index, index: test_index,

View File

@ -16,8 +16,12 @@
use serde_yaml::Value; use serde_yaml::Value;
use std::{ use std::{
any::Any,
collections::BTreeMap, collections::BTreeMap,
panic::{self, RefUnwindSafe, UnwindSafe},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, Mutex},
thread,
}; };
use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*}; use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*};
@ -36,7 +40,7 @@ pub struct Test {
pub config: BTreeMap<String, Value>, pub config: BTreeMap<String, Value>,
} }
pub trait Namespace { pub trait Namespace: UnwindSafe + RefUnwindSafe {
fn parse_type(&self) -> ParseType; fn parse_type(&self) -> ParseType;
fn run_test(&self, test: Test) -> Result<Value, String>; fn run_test(&self, test: Test) -> Result<Value, String>;
@ -46,6 +50,30 @@ pub trait Runner {
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>>; fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>>;
} }
fn set_hook() -> Arc<Mutex<Option<String>>> {
let panic_buf = Arc::new(Mutex::new(None));
let thread_id = thread::current().id();
panic::set_hook({
let panic_buf = panic_buf.clone();
Box::new(move |e| {
if thread::current().id() == thread_id {
*panic_buf.lock().unwrap() = Some(e.to_string());
} else {
println!("{}", e)
}
})
});
panic_buf
}
fn take_hook(
output: Result<Result<Value, String>, Box<dyn Any + Send>>,
panic_buf: Arc<Mutex<Option<String>>>,
) -> Result<Result<Value, String>, String> {
let _ = panic::take_hook();
output.map_err(|_| panic_buf.lock().unwrap().take().expect("failed to get panic message"))
}
pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) { pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
std::env::remove_var("LEO_BACKTRACE"); // always remove backtrace so it doesn't clog output files std::env::remove_var("LEO_BACKTRACE"); // always remove backtrace so it doesn't clog output files
std::env::set_var("LEO_TESTFRAMEWORK", "true"); std::env::set_var("LEO_TESTFRAMEWORK", "true");
@ -149,24 +177,24 @@ pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
for (i, test) in tests.into_iter().enumerate() { for (i, test) in tests.into_iter().enumerate() {
let expected_output = expected_output.as_mut().and_then(|x| x.next()).cloned(); let expected_output = expected_output.as_mut().and_then(|x| x.next()).cloned();
println!("running test {} @ '{}'", test_name, path.to_str().unwrap()); println!("running test {} @ '{}'", test_name, path.to_str().unwrap());
let output = namespace.run_test(Test { let panic_buf = set_hook();
name: test_name.clone(), let leo_output = panic::catch_unwind(|| {
content: test.clone(), namespace.run_test(Test {
path: path.into(), name: test_name.clone(),
config: config.extra.clone(), content: test.clone(),
path: path.into(),
config: config.extra.clone(),
})
}); });
if let Some(error) = emit_errors( let output = take_hook(leo_output, panic_buf);
output.as_ref().map_err(|x| &**x), if let Some(error) = emit_errors(&test, &output, &config.expectation, expected_output, i) {
&config.expectation,
expected_output,
i,
) {
fail_tests += 1; fail_tests += 1;
errors.push(error); errors.push(error);
} else { } else {
pass_tests += 1; pass_tests += 1;
new_outputs.push( new_outputs.push(
output output
.unwrap()
.as_ref() .as_ref()
.map(|x| serde_yaml::to_value(x).expect("serialization failed")) .map(|x| serde_yaml::to_value(x).expect("serialization failed"))
.unwrap_or_else(|e| Value::String(e.clone())), .unwrap_or_else(|e| Value::String(e.clone())),