1use anyhow::Ok;
2
3use super::helpers::error;
4use super::{
5 lexing::{Token, TokenValue},
6 ParserState,
7};
8use crate::ast::*;
9
10impl<'a> ParserState<'a> {
11 pub(super) fn parse_module(&mut self) -> anyhow::Result<Module> {
12 let mut this_module = Module::new();
13 let module_name = if self.is_next(TokenValue::Module)? {
14 let modid = self.parse_module_name()?;
15 if let TokenValue::LeftParen = self.peek_next_token()?.value {
16 let exports = self.parse_paren_list(&mut Self::parse_export)?;
17 this_module.exports = Some(exports);
18 }
19 self.expect(TokenValue::Where)?;
20 modid
21 } else {
22 module("Main")
23 };
24 this_module.name = module_name;
25 self.parse_body(&mut this_module)?;
26 Ok(this_module)
27 }
28
29 fn parse_body(&mut self, module: &mut Module) -> anyhow::Result<()> {
30 let brace = self.get_next_token()?;
31 let is_virtual = match brace.value {
32 TokenValue::LeftBrace => false,
33 TokenValue::VirtualLeftBrace => true,
34 _ => return error("Missing brace at start of body", brace.location),
35 };
36 let tok = self.peek_next_token()?;
37 let imports = match tok.value {
38 TokenValue::Import => self.parse_import_declarations()?,
39 _ => Vec::new(),
40 };
41 let decls = self.parse_top_declarations()?;
42 if is_virtual {
43 self.expect(TokenValue::VirtualRightBrace)?;
44 } else {
45 self.expect(TokenValue::RightBrace)?;
46 }
47 module.declarations = decls;
48 module.imports = imports;
49 Ok(())
50 }
51
52 fn parse_export(&mut self) -> anyhow::Result<Export> {
53 let tok = self.get_next_token()?;
54 match tok.value {
55 TokenValue::QVarId(_, _) | TokenValue::VarId(_) => {
56 Ok(Export::Var(Identifier::try_from(tok)?))
57 }
58 TokenValue::QConId(_, _) | TokenValue::ConId(_) => {
59 let id = Identifier::try_from(tok)?;
60 let spec = self.parse_exposed_spec()?;
61 Ok(Export::TypeOrClass(id, spec))
62 }
63 TokenValue::Module => {
64 let tok = self.get_next_token()?;
65 let modid = Identifier::try_from(tok)?;
66 Ok(Export::Module(modid))
67 }
68 _ => error("Invalid export", tok.location),
69 }
70 }
71
72 fn parse_import_declarations(&mut self) -> anyhow::Result<Vec<ImportDecl>> {
73 let mut imports = Vec::new();
74 loop {
75 if self.is_next(TokenValue::Import)? {
76 imports.push(self.parse_import_decl()?);
77 let tok = self.peek_next_token()?;
78 match tok.value {
79 TokenValue::Semicolon => {
80 self.get_next_token()?;
81 }
82 TokenValue::RightBrace | TokenValue::VirtualRightBrace => break,
83 _ => return error("expected semicolon or right brace", tok.location),
84 }
85 } else {
86 break;
87 }
88 }
89 Ok(imports)
90 }
91
92 fn parse_import_decl(&mut self) -> anyhow::Result<ImportDecl> {
93 let qualified = self.is_next(Token::varid("qualified").value)?;
94 let modid = self.parse_module_name()?;
95 let mut import = self.new_import_decl(modid);
96 import.qualified = qualified;
97 if self.is_next(Token::varid("as").value)? {
98 let alias = self.parse_module_name()?;
99 import.alias = Some(alias);
100 }
101 let hiding = self.is_next(Token::varid("hiding").value)?;
102 if self.peek_next(TokenValue::LeftParen)? {
103 let impspec = self.parse_paren_list(&mut Self::parse_import)?;
104 if hiding {
105 import.hidden = Some(impspec);
106 } else {
107 import.specific = Some(impspec);
108 }
109 } else if hiding {
110 return error("No list after `hiding`", self.get_next_token()?.location);
111 }
112 Ok(import)
113 }
114
115 fn parse_import(&mut self) -> anyhow::Result<Import> {
116 let tok = self.get_next_token()?;
117 match tok.value {
118 TokenValue::QVarId(_, _) | TokenValue::VarId(_) => {
119 Ok(Import::Var(Identifier::try_from(tok)?))
120 }
121 TokenValue::QConId(_, _) | TokenValue::ConId(_) => {
122 let id = Identifier::try_from(tok)?;
123 let spec = self.parse_exposed_spec()?;
124 Ok(Import::TypeOrClass(id, spec))
125 }
126 _ => error("Invalid import", tok.location),
127 }
128 }
129
130 fn parse_module_name(&mut self) -> anyhow::Result<Identifier> {
131 let mod_tok = self.get_next_token()?;
132 match mod_tok.value {
133 TokenValue::ConId(s) => Ok(module(&s)),
134 TokenValue::QConId(m, s) => {
135 let mut mid = m.clone();
136 mid.push('.');
137 mid.push_str(&s);
138 Ok(module(&mid))
139 }
140 _ => error(
141 &format!("Invalid module name token {:?}", mod_tok),
142 mod_tok.location,
143 ),
144 }
145 }
146
147 fn parse_exposed_spec(&mut self) -> anyhow::Result<ExposedSpec> {
148 if self.is_next(TokenValue::LeftParen)? {
149 let tok = self.peek_next_token()?;
150 match tok.value {
151 TokenValue::DotDot => {
152 self.get_next_token()?;
153 self.expect(TokenValue::RightParen)?;
154 Ok(ExposedSpec::All)
155 }
156 _ => {
157 self.rewind_lexer(1);
158 let cons = self.parse_paren_list(&mut Self::parse_cname)?;
159 Ok(ExposedSpec::List(cons))
160 }
161 }
162 } else {
163 Ok(ExposedSpec::None)
164 }
165 }
166}