diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index 1c422a8027..ca315d3b58 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -38,6 +38,7 @@ pub enum Token<'a> { JumpTable(u32), // jt2 FuncRef(u32), // fn2 SigRef(u32), // sig2 + UserRef(u32), // u345 Name(&'a str), // %9arbitrary_alphanum, %x3, %0, %function ... HexSequence(&'a str), // #89AF Identifier(&'a str), // Unrecognized identifier (opcode, enumerator, ...) @@ -320,6 +321,7 @@ impl<'a> Lexer<'a> { "jt" => Some(Token::JumpTable(number)), "fn" => Some(Token::FuncRef(number)), "sig" => Some(Token::SigRef(number)), + "u" => Some(Token::UserRef(number)), _ => None, } } @@ -604,4 +606,17 @@ mod tests { assert_eq!(lex.next(), token(Token::Name("ebb11"), 1)); assert_eq!(lex.next(), token(Token::Name("_"), 1)); } + + #[test] + fn lex_userrefs() { + let mut lex = Lexer::new("u0 u1 u234567890 u9:8765"); + + assert_eq!(lex.next(), token(Token::UserRef(0), 1)); + assert_eq!(lex.next(), token(Token::UserRef(1), 1)); + assert_eq!(lex.next(), token(Token::UserRef(234567890), 1)); + assert_eq!(lex.next(), token(Token::UserRef(9), 1)); + assert_eq!(lex.next(), token(Token::Colon, 1)); + assert_eq!(lex.next(), token(Token::Integer("8765"), 1)); + assert_eq!(lex.next(), None); + } } diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 55cf342ad3..03516fa91d 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -890,24 +890,26 @@ impl<'a> Parser<'a> { match self.token() { Some(Token::Name(s)) => { self.consume(); - Ok(ExternalName::new(s)) + Ok(ExternalName::testcase(s)) } - Some(Token::HexSequence(s)) => { - if s.len() % 2 != 0 { - return err!( - self.loc, - "expected binary external name to have length multiple of two" - ); - } - let mut bin_name = Vec::with_capacity(s.len() / 2); - let mut i = 0; - while i + 2 <= s.len() { - let byte = u8::from_str_radix(&s[i..i + 2], 16).unwrap(); - bin_name.push(byte); - i += 2; - } + Some(Token::UserRef(namespace)) => { self.consume(); - Ok(ExternalName::new(bin_name)) + match self.token() { + Some(Token::Colon) => { + self.consume(); + match self.token() { + Some(Token::Integer(index_str)) => { + let index: u32 = u32::from_str_radix(index_str, 10).map_err(|_| { + self.error("the integer given overflows the u32 type") + })?; + self.consume(); + Ok(ExternalName::user(namespace, index)) + } + _ => err!(self.loc, "expected integer"), + } + } + _ => err!(self.loc, "expected colon"), + } } _ => err!(self.loc, "expected external name"), }