wright/parser/decl/
import.rs1use crate::{
4 ast::{decl::import::ImportDecl, identifier::Identifier, path::Path},
5 lexer::token::{Token, TokenTy},
6 parser::{
7 Parser,
8 error::{ParserError, ParserErrorKind},
9 whitespace,
10 },
11 source_tracking::fragment::Fragment,
12};
13
14impl ImportDecl {
15 pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
20 let use_kw: Token = parser.next_if_is(TokenTy::KwUse).ok_or(
21 ParserErrorKind::ExpectedImportDeclaration.at(parser.peek_fragment_or_rest_cloned()),
22 )?;
23
24 whitespace::require_whitespace(parser)?;
26 let path: Path = Path::parse(parser)?;
28
29 let imported_as = match parser.next_if_is(TokenTy::Whitespace) {
33 None => None,
35
36 Some(_) => {
38 whitespace::optional_whitespace(parser);
40
41 match parser.next_if_is(TokenTy::KwAs) {
44 None => None,
46
47 Some(_) => {
49 whitespace::require_whitespace(parser).map_err(|e| {
50 e.with_help("whitespace needed between \"as\" and binding.")
51 })?;
52
53 let imported_as = Identifier::parse(parser).map_err(|e| {
54 e.with_help("expected binding in \"use ... as\" declaration.")
55 })?;
56
57 Some(imported_as)
58 }
59 }
60 }
61 };
62
63 whitespace::optional_whitespace(parser);
64
65 if let Some(semi) = parser.next_if_is(TokenTy::Semi) {
66 Ok(ImportDecl {
67 matching_source: Fragment::cover(&use_kw.fragment, &semi.fragment),
68 imported_item: path,
69 imported_as,
70 })
71 } else {
72 Err(ParserErrorKind::ImportMustEndWithSemicolon
73 .at(parser.peek_fragment_or_rest_cloned()))
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use crate::{ast::decl::import::ImportDecl, lexer::Lexer, parser::Parser};
81
82 #[test]
83 fn test_import() {
84 let mut parser = Parser::new(Lexer::new_test("use wright::util;"));
85 let import_decl = ImportDecl::parse(&mut parser).unwrap();
86 assert!(parser.lexer.remaining.is_empty());
87 assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
88 assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
89 }
90
91 #[test]
92 fn test_import_with_whitespace() {
93 let mut parser = Parser::new(Lexer::new_test("use wright :: util ;"));
94 let import_decl = ImportDecl::parse(&mut parser).unwrap();
95 assert!(parser.lexer.remaining.is_empty());
96 assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
97 assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
98 }
99
100 #[test]
101 fn test_import_as() {
102 let mut parser = Parser::new(Lexer::new_test("use wright::util as u;"));
103 let import_decl = ImportDecl::parse(&mut parser).unwrap();
104 assert!(parser.lexer.remaining.is_empty());
105 assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
106 assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
107 assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
108 }
109
110 #[test]
111 fn test_import_as_with_comment() {
112 let mut parser = Parser::new(Lexer::new_test("use wright::util as /* old_name */ u;"));
113 let import_decl = ImportDecl::parse(&mut parser).unwrap();
114 assert!(parser.lexer.remaining.is_empty());
115 assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
116 assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
117 assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
118 }
119
120 #[test]
121 fn test_import_as_with_preceding_comment() {
122 let mut parser = Parser::new(Lexer::new_test("use wright::util /* as old_name */ as u;"));
123 let import_decl = ImportDecl::parse(&mut parser).unwrap();
124 assert!(parser.lexer.remaining.is_empty());
125 assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
126 assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
127 assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
128 }
129}