use crate::{
ast::{decl::import::ImportDecl, identifier::Identifier, path::Path},
lexer::token::{Token, TokenTy},
parser::{
error::{ParserError, ParserErrorKind},
whitespace, Parser,
},
source_tracking::fragment::Fragment,
};
impl ImportDecl {
pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
let use_kw: Token = parser.next_if_is(TokenTy::KwUse).ok_or(
ParserErrorKind::ExpectedImportDeclaration.at(parser.peek_fragment_or_rest_cloned()),
)?;
whitespace::require_whitespace(parser)?;
let path: Path = Path::parse(parser)?;
let imported_as = if parser.matches(&[TokenTy::Whitespace, TokenTy::KwAs]) {
parser.advance(2);
whitespace::require_whitespace(parser)
.map_err(|e| e.with_help("whitespace needed between \"as\" and binding."))?;
let imported_as = Identifier::parse(parser)
.map_err(|e| e.with_help("expected binding in \"use ... as\" declaration."))?;
Some(imported_as)
} else {
None
};
whitespace::optional_whitespace(parser);
if let Some(semi) = parser.next_if_is(TokenTy::Semi) {
Ok(ImportDecl {
matching_source: Fragment::cover(use_kw.fragment, semi.fragment),
imported_item: path,
imported_as,
})
} else {
Err(ParserErrorKind::ImportMustEndWithSemicolon
.at(parser.peek_fragment_or_rest_cloned()))
}
}
}
#[cfg(test)]
mod tests {
use crate::{ast::decl::import::ImportDecl, lexer::Lexer, parser::Parser};
#[test]
fn test_import() {
let mut parser = Parser::new(Lexer::new_test("use wright::util;"));
let import_decl = ImportDecl::parse(&mut parser).unwrap();
assert!(parser.lexer.remaining.is_empty());
assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
}
#[test]
fn test_import_with_whitespace() {
let mut parser = Parser::new(Lexer::new_test("use wright :: util ;"));
let import_decl = ImportDecl::parse(&mut parser).unwrap();
assert!(parser.lexer.remaining.is_empty());
assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
}
#[test]
fn test_import_as() {
let mut parser = Parser::new(Lexer::new_test("use wright::util as u;"));
let import_decl = ImportDecl::parse(&mut parser).unwrap();
assert!(parser.lexer.remaining.is_empty());
assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
}
#[test]
fn test_import_as_with_comment() {
let mut parser = Parser::new(Lexer::new_test("use wright::util as /* old_name */ u;"));
let import_decl = ImportDecl::parse(&mut parser).unwrap();
assert!(parser.lexer.remaining.is_empty());
assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
}
}