wac_parser/ast/
export.rs

1use super::{expr::Expr, parse_token, DocComment, ExternName, Lookahead, Parse, ParseResult, Peek};
2use crate::lexer::{Lexer, Token};
3use miette::SourceSpan;
4use serde::Serialize;
5
6/// Represents an export statement in the AST.
7#[derive(Debug, Clone, Serialize)]
8#[serde(rename_all = "camelCase")]
9pub struct ExportStatement<'a> {
10    /// The doc comments for the statement.
11    pub docs: Vec<DocComment<'a>>,
12    /// The expression that is being exported.
13    pub expr: Expr<'a>,
14    /// The options for the export statement.
15    pub options: ExportOptions<'a>,
16}
17
18impl<'a> Parse<'a> for ExportStatement<'a> {
19    fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
20        let docs = Parse::parse(lexer)?;
21        parse_token(lexer, Token::ExportKeyword)?;
22        let expr = Parse::parse(lexer)?;
23        let options = Parse::parse(lexer)?;
24        parse_token(lexer, Token::Semicolon)?;
25        Ok(Self {
26            docs,
27            expr,
28            options,
29        })
30    }
31}
32
33impl Peek for ExportStatement<'_> {
34    fn peek(lookahead: &mut Lookahead) -> bool {
35        lookahead.peek(Token::ExportKeyword)
36    }
37}
38
39/// Represents an item being exported in the AST.
40#[derive(Debug, Clone, Serialize)]
41#[serde(rename_all = "camelCase")]
42pub enum ExportOptions<'a> {
43    /// No options for the export.
44    None,
45    /// Spread export the exports of an instance.
46    Spread(SourceSpan),
47    /// Exporting with the provided name.
48    Rename(ExternName<'a>),
49}
50
51impl<'a> Parse<'a> for ExportOptions<'a> {
52    fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
53        if let Some((Ok(Token::Ellipsis), _)) = lexer.peek() {
54            // This is a spread export
55            let span = parse_token(lexer, Token::Ellipsis)?;
56            return Ok(Self::Spread(span));
57        }
58
59        if let Some((Ok(Token::AsKeyword), _)) = lexer.peek() {
60            // This is a renamed export
61            parse_token(lexer, Token::AsKeyword)?;
62            return Ok(Self::Rename(Parse::parse(lexer)?));
63        }
64
65        Ok(Self::None)
66    }
67}
68
69#[cfg(test)]
70mod test {
71    use crate::ast::test::roundtrip;
72
73    #[test]
74    fn export_statement_roundtrip() {
75        roundtrip(
76            "package foo:bar; export y;",
77            "package foo:bar;\n\nexport y;\n",
78        )
79        .unwrap();
80        roundtrip(
81            "package foo:bar; export foo.%with as \"foo\";",
82            "package foo:bar;\n\nexport foo.%with as \"foo\";\n",
83        )
84        .unwrap();
85        roundtrip(
86            "package foo:bar; export y.x.z;",
87            "package foo:bar;\n\nexport y.x.z;\n",
88        )
89        .unwrap();
90        roundtrip(
91            "package foo:bar; export y.x.z as \"baz\";",
92            "package foo:bar;\n\nexport y.x.z as \"baz\";\n",
93        )
94        .unwrap();
95        roundtrip(
96            "package foo:bar; export y[\"x\"][\"z\"];",
97            "package foo:bar;\n\nexport y[\"x\"][\"z\"];\n",
98        )
99        .unwrap();
100        roundtrip(
101            "package foo:bar; export y[\"x\"][\"z\"]  as    \"x\";",
102            "package foo:bar;\n\nexport y[\"x\"][\"z\"] as \"x\";\n",
103        )
104        .unwrap();
105        roundtrip(
106            "package foo:bar; export foo[\"bar\"].baz[\"qux\"];",
107            "package foo:bar;\n\nexport foo[\"bar\"].baz[\"qux\"];\n",
108        )
109        .unwrap();
110        roundtrip(
111            "package foo:bar; export foo[\"bar\"].baz[\"qux\"] as \"qux\";",
112            "package foo:bar;\n\nexport foo[\"bar\"].baz[\"qux\"] as \"qux\";\n",
113        )
114        .unwrap();
115
116        roundtrip(
117            "package foo:bar; export (y);",
118            "package foo:bar;\n\nexport (y);\n",
119        )
120        .unwrap();
121
122        roundtrip(
123            "package foo:bar; export new foo:bar {};",
124            "package foo:bar;\n\nexport new foo:bar {};\n",
125        )
126        .unwrap();
127
128        roundtrip(
129            "package foo:bar; export new foo:bar {}  /* foo */ as     \"foo\";",
130            "package foo:bar;\n\nexport new foo:bar {} as \"foo\";\n",
131        )
132        .unwrap();
133
134        roundtrip(
135            "package foo:bar; export new foo:bar { foo, \"bar\": (new baz:qux {a, ...}), \"baz\": foo[\"baz\"].qux };",
136            "package foo:bar;\n\nexport new foo:bar {\n    foo,\n    \"bar\": (new baz:qux {\n        a,\n        ...\n    }),\n    \"baz\": foo[\"baz\"].qux,\n};\n",
137        )
138        .unwrap();
139
140        roundtrip(
141            "package foo:bar; export i...;",
142            "package foo:bar;\n\nexport i...;\n",
143        )
144        .unwrap();
145    }
146}