java_lang/tree/parser/
import.rs

1use super::{super::ImportDeclaration, identifier};
2use crate::{ts, Token, TokenStream};
3use nom::{
4    bytes::tag,
5    combinator::{complete, opt},
6    error::Error,
7    multi::{many0, separated_list1},
8    IResult, Parser,
9};
10use std::borrow::Cow;
11
12/// 解析导入声明
13///
14/// 该函数解析一个导入声明,并返回解析后的导入声明和剩余的标记流。
15///
16/// # 参数
17///
18/// * `tokens` - 标记流,包含待解析的标记。
19///
20/// # 返回值
21///
22/// 返回一个 `IResult`,其中包含解析后剩余的标记流和导入声明。
23///
24/// # 示例
25///
26/// ```rust
27/// fn main() -> anyhow::Result<()> {
28/// use java_lang::{TokenStream,import_declaration};
29/// let (_, tokens) = TokenStream::from_str("import java.util.List;")?;
30/// let (_, import_declaration) = import_declaration(tokens)?;
31/// Ok(())
32/// }
33/// ```
34///
35/// # 错误处理
36///
37/// 如果解析过程中出现错误,将返回一个解析错误。
38pub fn import_declaration<'a>(tokens: TokenStream) -> IResult<TokenStream, ImportDeclaration<'a>> {
39    let (tokens, _) = tag(ts![Import]).parse(tokens)?;
40    let (tokens, r#static) = opt(tag(ts![Static])).parse(tokens)?;
41    let (tokens, idents) = separated_list1(complete(tag(ts![Dot])), identifier).parse(tokens)?;
42    let name = idents
43        .into_iter()
44        .map(|i| i.to_string())
45        .collect::<Vec<_>>()
46        .join(Token::DOT);
47
48    let Ok((tokens, _)) = tag::<_, _, Error<TokenStream>>(ts![Dot, Star]).parse(tokens.clone())
49    else {
50        let (tokens, _) = tag(ts![SemiColon]).parse(tokens)?;
51        let import_declaration = if r#static.is_none() {
52            ImportDeclaration::SimpleType(Cow::Owned(name))
53        } else {
54            ImportDeclaration::SingleStatic(Cow::Owned(name))
55        };
56        return Ok((tokens, import_declaration));
57    };
58
59    let (tokens, _) = tag(ts![SemiColon]).parse(tokens)?;
60    let import_declaration = if r#static.is_none() {
61        ImportDeclaration::TypeOnDemand(Cow::Owned(name))
62    } else {
63        ImportDeclaration::StaticOnDemand(Cow::Owned(name))
64    };
65    Ok((tokens, import_declaration))
66}
67
68/// 解析导入声明列表
69///
70/// 该函数解析一个导入声明列表,并返回解析后的导入声明列表和剩余的标记流。
71///
72/// # 参数
73///
74/// * `tokens` - 标记流,包含待解析的标记。
75///
76/// # 返回值
77///
78/// 返回一个 `IResult`,其中包含解析后剩余的标记流和导入声明列表。
79///
80/// # 示例
81///
82/// ```rust
83/// fn main() -> anyhow::Result<()> {
84/// use java_lang::{TokenStream,import_declarations};
85/// let (_, tokens) = TokenStream::from_str("import java.util.List;")?;
86/// let (_, import_declarations) = import_declarations(tokens)?;
87/// Ok(())
88/// }
89/// ```
90///
91/// # 错误处理
92///
93/// 如果解析过程中出现错误,将返回一个解析错误。
94pub fn import_declarations<'a>(
95    tokens: TokenStream,
96) -> IResult<TokenStream, Vec<ImportDeclaration<'a>>> {
97    many0(complete(import_declaration)).parse(tokens)
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    const IMPORTS: &str = "
105    import java.util.List;
106    import java.io.*;
107    import static java.util.Collections.emptyList;
108    import static java.util.Collections.*;
109    ";
110
111    #[test]
112    fn test_import_declaration() -> anyhow::Result<()> {
113        let (_, tokens) = TokenStream::from_str(IMPORTS)?;
114        assert!(!tokens.is_empty());
115
116        let (tokens, import) = import_declaration(tokens)?;
117        assert!(matches!(import, ImportDeclaration::SimpleType(_)));
118
119        let (tokens, import) = import_declaration(tokens)?;
120        assert!(matches!(import, ImportDeclaration::TypeOnDemand(_)));
121
122        let (tokens, import) = import_declaration(tokens)?;
123        assert!(matches!(import, ImportDeclaration::SingleStatic(_)));
124
125        let (tokens, import) = import_declaration(tokens)?;
126        assert!(matches!(import, ImportDeclaration::StaticOnDemand(_)));
127
128        assert!(tokens.is_empty());
129
130        Ok(())
131    }
132
133    #[test]
134    fn test_import_declarations() -> anyhow::Result<()> {
135        let (_, tokens) = TokenStream::from_str(IMPORTS)?;
136        assert!(!tokens.is_empty());
137
138        let (tokens, imports) = import_declarations(tokens)?;
139        assert_eq!(imports.len(), 4);
140
141        assert!(tokens.is_empty());
142
143        Ok(())
144    }
145}