solar_parse/parser/
item.rs

1use super::{ExpectedToken, SeqSep};
2use crate::{PResult, Parser};
3use itertools::Itertools;
4use smallvec::SmallVec;
5use solar_ast::{token::*, *};
6use solar_interface::{diagnostics::DiagMsg, error_code, kw, sym, Ident, Span};
7
8impl<'sess, 'ast> Parser<'sess, 'ast> {
9    /// Parses a source unit.
10    #[instrument(level = "debug", skip_all)]
11    pub fn parse_file(&mut self) -> PResult<'sess, SourceUnit<'ast>> {
12        self.parse_items(TokenKind::Eof).map(SourceUnit::new)
13    }
14
15    /// Parses a list of items until the given token is encountered.
16    fn parse_items(&mut self, end: TokenKind) -> PResult<'sess, Box<'ast, [Item<'ast>]>> {
17        let get_msg_note = |this: &mut Self| {
18            let (prefix, list, link);
19            if this.in_contract {
20                prefix = "contract";
21                list = "function, variable, struct, or modifier definition";
22                link = "contractBodyElement";
23            } else {
24                prefix = "global";
25                list = "pragma, import directive, contract, interface, library, struct, enum, constant, function, modifier, or error definition";
26                link = "sourceUnit";
27            }
28            let msg =
29                format!("expected {prefix} item ({list}), found {}", this.token.full_description());
30            let note = format!("for a full list of valid {prefix} items, see <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.{link}>");
31            (msg, note)
32        };
33
34        let mut items = Vec::new();
35        while let Some(item) = self.parse_item()? {
36            if self.in_contract && !item.is_allowed_in_contract() {
37                let msg = format!("{}s are not allowed in contracts", item.description());
38                let (_, note) = get_msg_note(self);
39                self.dcx().err(msg).span(item.span).note(note).emit();
40            } else {
41                items.push(item);
42            }
43        }
44        if !self.eat(end) {
45            let (msg, note) = get_msg_note(self);
46            return Err(self.dcx().err(msg).span(self.token.span).note(note));
47        }
48        Ok(self.alloc_vec(items))
49    }
50
51    /// Parses an item.
52    #[instrument(level = "debug", skip_all)]
53    pub fn parse_item(&mut self) -> PResult<'sess, Option<Item<'ast>>> {
54        let docs = self.parse_doc_comments();
55        self.parse_spanned(Self::parse_item_kind)
56            .map(|(span, kind)| kind.map(|kind| Item { docs, span, kind }))
57    }
58
59    fn parse_item_kind(&mut self) -> PResult<'sess, Option<ItemKind<'ast>>> {
60        let kind = if self.is_function_like() {
61            self.parse_function().map(ItemKind::Function)
62        } else if self.eat_keyword(kw::Struct) {
63            self.parse_struct().map(ItemKind::Struct)
64        } else if self.eat_keyword(kw::Event) {
65            self.parse_event().map(ItemKind::Event)
66        } else if self.is_contract_like() {
67            self.parse_contract().map(ItemKind::Contract)
68        } else if self.eat_keyword(kw::Enum) {
69            self.parse_enum().map(ItemKind::Enum)
70        } else if self.eat_keyword(kw::Type) {
71            self.parse_udvt().map(ItemKind::Udvt)
72        } else if self.eat_keyword(kw::Pragma) {
73            self.parse_pragma().map(ItemKind::Pragma)
74        } else if self.eat_keyword(kw::Import) {
75            self.parse_import().map(ItemKind::Import)
76        } else if self.eat_keyword(kw::Using) {
77            self.parse_using().map(ItemKind::Using)
78        } else if self.check_keyword(sym::error)
79            && self.look_ahead(1).is_ident()
80            && self.look_ahead(2).is_open_delim(Delimiter::Parenthesis)
81        {
82            self.bump(); // `error`
83            self.parse_error().map(ItemKind::Error)
84        } else if self.is_variable_declaration() {
85            let flags = if self.in_contract { VarFlags::STATE_VAR } else { VarFlags::CONSTANT_VAR };
86            self.parse_variable_definition(flags).map(ItemKind::Variable)
87        } else {
88            return Ok(None);
89        };
90        kind.map(Some)
91    }
92
93    /// Returns `true` if the current token is the start of a function definition.
94    fn is_function_like(&self) -> bool {
95        (self.token.is_keyword(kw::Function)
96            && !self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
97            || self.token.is_keyword_any(&[
98                kw::Constructor,
99                kw::Fallback,
100                kw::Receive,
101                kw::Modifier,
102            ])
103    }
104
105    /// Returns `true` if the current token is the start of a contract definition.
106    fn is_contract_like(&self) -> bool {
107        self.token.is_keyword_any(&[kw::Abstract, kw::Contract, kw::Interface, kw::Library])
108    }
109
110    /// Returns `true` if the current token is the start of a variable declaration.
111    pub(super) fn is_variable_declaration(&self) -> bool {
112        // https://github.com/ethereum/solidity/blob/194b114664c7daebc2ff68af3c573272f5d28913/libsolidity/parsing/Parser.cpp#L2451
113        self.token.is_non_reserved_ident(false) || self.is_non_custom_variable_declaration()
114    }
115
116    pub(super) fn is_non_custom_variable_declaration(&self) -> bool {
117        self.token.is_keyword(kw::Mapping)
118            || (self.token.is_keyword(kw::Function)
119                && self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
120            || self.token.is_elementary_type()
121    }
122
123    /* ----------------------------------------- Items ----------------------------------------- */
124    // These functions expect that the keyword has already been eaten unless otherwise noted.
125
126    /// Parses a function definition.
127    ///
128    /// Expects the current token to be a function-like keyword.
129    fn parse_function(&mut self) -> PResult<'sess, ItemFunction<'ast>> {
130        let Token { span: lo, kind: TokenKind::Ident(kw) } = self.token else {
131            unreachable!("parse_function called without function-like keyword");
132        };
133        self.bump(); // kw
134
135        let kind = match kw {
136            kw::Constructor => FunctionKind::Constructor,
137            kw::Function => FunctionKind::Function,
138            kw::Fallback => FunctionKind::Fallback,
139            kw::Receive => FunctionKind::Receive,
140            kw::Modifier => FunctionKind::Modifier,
141            _ => unreachable!("parse_function called without function-like keyword"),
142        };
143        let flags = FunctionFlags::from_kind(kind);
144        let header = self.parse_function_header(flags)?;
145        let (body_span, body) = self.parse_spanned(|this| {
146            Ok(if !flags.contains(FunctionFlags::ONLY_BLOCK) && this.eat(TokenKind::Semi) {
147                None
148            } else {
149                Some(this.parse_block()?)
150            })
151        })?;
152
153        if !self.in_contract && !kind.allowed_in_global() {
154            let msg = format!("{kind}s are not allowed in the global scope");
155            self.dcx().err(msg).span(lo.to(self.prev_token.span)).emit();
156        }
157        // All function kinds are allowed in contracts.
158
159        Ok(ItemFunction { kind, header, body, body_span })
160    }
161
162    /// Parses a function a header.
163    pub(super) fn parse_function_header(
164        &mut self,
165        flags: FunctionFlags,
166    ) -> PResult<'sess, FunctionHeader<'ast>> {
167        let lo = self.prev_token.span; // the header span includes the "function" kw
168
169        let mut header = FunctionHeader::default();
170        let var_flags = if flags.contains(FunctionFlags::PARAM_NAME) {
171            VarFlags::FUNCTION_TY
172        } else {
173            VarFlags::FUNCTION
174        };
175
176        if flags.contains(FunctionFlags::NAME) {
177            // Allow and warn on `function fallback` or `function receive`.
178            let ident;
179            if flags == FunctionFlags::FUNCTION
180                && self.token.is_keyword_any(&[kw::Fallback, kw::Receive])
181            {
182                let kw_span = self.prev_token.span;
183                ident = self.parse_ident_any()?;
184                let msg = format!("function named `{ident}`");
185                let mut warn = self.dcx().warn(msg).span(ident.span).code(error_code!(3445));
186                if self.in_contract {
187                    let help = format!("remove the `function` keyword if you intend this to be a contract's {ident} function");
188                    warn = warn.span_help(kw_span, help);
189                }
190                warn.emit();
191            } else {
192                ident = self.parse_ident()?;
193            }
194            header.name = Some(ident);
195        } else if self.token.is_non_reserved_ident(false) {
196            let msg = "function names are not allowed here";
197            self.dcx().err(msg).span(self.token.span).emit();
198            self.bump();
199        }
200
201        if flags.contains(FunctionFlags::NO_PARENS)
202            && !self.token.is_open_delim(Delimiter::Parenthesis)
203        {
204            // Omitted parens.
205        } else {
206            header.parameters = self.parse_parameter_list(true, var_flags)?;
207        }
208
209        let mut modifiers = Vec::new();
210        loop {
211            // This is needed to skip parsing surrounding variable's visibility in function types.
212            // E.g. in `function(uint) external internal e;` the `internal` is the surrounding
213            // variable's visibility, not the function's.
214            // HACK: Ugly way to add an extra guard to `if let` without the unstable `let-chains`.
215            // Ideally this would be `if let Some(_) = _ && guard { ... }`.
216            let vis_guard = (!(flags == FunctionFlags::FUNCTION_TY && header.visibility.is_some()))
217                .then_some(());
218            if let Some(visibility) = vis_guard.and_then(|()| self.parse_visibility()) {
219                if header.visibility.is_some() {
220                    let msg = "visibility already specified";
221                    self.dcx().err(msg).span(self.prev_token.span).emit();
222                } else {
223                    header.visibility =
224                        if !flags.contains(FunctionFlags::from_visibility(visibility)) {
225                            let msg = visibility_error(visibility, flags.visibilities());
226                            self.dcx().err(msg).span(self.prev_token.span).emit();
227                            flags.visibilities().into_iter().flatten().next()
228                        } else {
229                            Some(visibility)
230                        };
231                }
232            } else if let Some(state_mutability) = self.parse_state_mutability() {
233                if !header.state_mutability.is_non_payable() {
234                    let msg = "state mutability already specified";
235                    self.dcx().err(msg).span(self.prev_token.span).emit();
236                } else {
237                    header.state_mutability = if !flags
238                        .contains(FunctionFlags::from_state_mutability(state_mutability))
239                    {
240                        let msg =
241                            state_mutability_error(state_mutability, flags.state_mutabilities());
242                        self.dcx().err(msg).span(self.prev_token.span).emit();
243                        flags.state_mutabilities().into_iter().flatten().next().unwrap_or_default()
244                    } else {
245                        state_mutability
246                    }
247                }
248            } else if self.eat_keyword(kw::Virtual) {
249                if !flags.contains(FunctionFlags::VIRTUAL) {
250                    let msg = "`virtual` is not allowed here";
251                    self.dcx().err(msg).span(self.prev_token.span).emit();
252                } else if header.virtual_ {
253                    let msg = "virtual already specified";
254                    self.dcx().err(msg).span(self.prev_token.span).emit();
255                } else {
256                    header.virtual_ = true;
257                }
258            } else if self.eat_keyword(kw::Override) {
259                let o = self.parse_override()?;
260                if !flags.contains(FunctionFlags::OVERRIDE) {
261                    let msg = "`override` is not allowed here";
262                    self.dcx().err(msg).span(self.prev_token.span).emit();
263                } else if header.override_.is_some() {
264                    let msg = "override already specified";
265                    self.dcx().err(msg).span(self.prev_token.span).emit();
266                } else {
267                    header.override_ = Some(o);
268                }
269            } else if flags.contains(FunctionFlags::MODIFIERS)
270                && self.token.is_non_reserved_ident(false)
271            {
272                modifiers.push(self.parse_modifier()?);
273            } else {
274                break;
275            }
276        }
277
278        header.modifiers = self.alloc_vec(modifiers);
279
280        if flags.contains(FunctionFlags::RETURNS) && self.eat_keyword(kw::Returns) {
281            header.returns = self.parse_parameter_list(false, var_flags)?;
282        }
283
284        header.span = lo.to(self.prev_token.span);
285
286        Ok(header)
287    }
288
289    /// Parses a struct definition.
290    fn parse_struct(&mut self) -> PResult<'sess, ItemStruct<'ast>> {
291        let name = self.parse_ident()?;
292        let fields = self.parse_delim_seq(
293            Delimiter::Brace,
294            SeqSep::trailing_enforced(TokenKind::Semi),
295            true,
296            |this| this.parse_variable_definition(VarFlags::STRUCT),
297        )?;
298        Ok(ItemStruct { name, fields })
299    }
300
301    /// Parses an event definition.
302    fn parse_event(&mut self) -> PResult<'sess, ItemEvent<'ast>> {
303        let name = self.parse_ident()?;
304        let parameters = self.parse_parameter_list(true, VarFlags::EVENT)?;
305        let anonymous = self.eat_keyword(kw::Anonymous);
306        self.expect_semi()?;
307        Ok(ItemEvent { name, parameters, anonymous })
308    }
309
310    /// Parses an error definition.
311    fn parse_error(&mut self) -> PResult<'sess, ItemError<'ast>> {
312        let name = self.parse_ident()?;
313        let parameters = self.parse_parameter_list(true, VarFlags::ERROR)?;
314        self.expect_semi()?;
315        Ok(ItemError { name, parameters })
316    }
317
318    /// Parses a contract definition.
319    ///
320    /// Expects the current token to be a contract-like keyword.
321    fn parse_contract(&mut self) -> PResult<'sess, ItemContract<'ast>> {
322        let TokenKind::Ident(kw) = self.token.kind else {
323            unreachable!("parse_contract called without contract-like keyword");
324        };
325        self.bump(); // kw
326
327        let kind = match kw {
328            kw::Abstract => {
329                self.expect_keyword(kw::Contract)?;
330                ContractKind::AbstractContract
331            }
332            kw::Contract => ContractKind::Contract,
333            kw::Interface => ContractKind::Interface,
334            kw::Library => ContractKind::Library,
335            _ => unreachable!("parse_contract called without contract-like keyword"),
336        };
337        let name = self.parse_ident()?;
338
339        let mut bases = None::<Box<'_, [Modifier<'_>]>>;
340        let mut layout = None::<StorageLayoutSpecifier<'_>>;
341        loop {
342            if self.eat_keyword(kw::Is) {
343                let new_bases = self.parse_inheritance()?;
344                if let Some(prev) = &bases {
345                    let msg = "base contracts already specified";
346                    let span = |bases: &[Modifier<'_>]| {
347                        Span::join_first_last(bases.iter().map(|m| m.span()))
348                    };
349                    self.dcx()
350                        .err(msg)
351                        .span(span(new_bases))
352                        .span_note(span(prev), "previous definition")
353                        .emit();
354                } else if !new_bases.is_empty() {
355                    bases = Some(new_bases);
356                }
357            } else if self.check_keyword(sym::layout) {
358                let new_layout = self.parse_storage_layout_specifier()?;
359                if let Some(prev) = &layout {
360                    let msg = "storage layout already specified";
361                    self.dcx()
362                        .err(msg)
363                        .span(new_layout.span)
364                        .span_note(prev.span, "previous definition")
365                        .emit();
366                } else {
367                    layout = Some(new_layout);
368                }
369            } else {
370                break;
371            }
372        }
373
374        if let Some(layout) = &layout {
375            if !kind.is_contract() {
376                let msg = "storage layout is only allowed for contracts";
377                self.dcx().err(msg).span(layout.span).emit();
378            }
379        }
380
381        self.expect(TokenKind::OpenDelim(Delimiter::Brace))?;
382        let body =
383            self.in_contract(|this| this.parse_items(TokenKind::CloseDelim(Delimiter::Brace)))?;
384
385        Ok(ItemContract { kind, name, layout, bases: bases.unwrap_or_default(), body })
386    }
387
388    /// Parses an enum definition.
389    fn parse_enum(&mut self) -> PResult<'sess, ItemEnum<'ast>> {
390        let name = self.parse_ident()?;
391        let variants = self.parse_delim_comma_seq(Delimiter::Brace, true, Self::parse_ident)?;
392        Ok(ItemEnum { name, variants })
393    }
394
395    /// Parses a user-defined value type.
396    fn parse_udvt(&mut self) -> PResult<'sess, ItemUdvt<'ast>> {
397        let name = self.parse_ident()?;
398        self.expect_keyword(kw::Is)?;
399        let ty = self.parse_type()?;
400        self.expect_semi()?;
401        Ok(ItemUdvt { name, ty })
402    }
403
404    /// Parses a pragma directive.
405    fn parse_pragma(&mut self) -> PResult<'sess, PragmaDirective<'ast>> {
406        let is_ident_or_strlit = |t: Token| t.is_ident() || t.is_str_lit();
407
408        let tokens = if self.check_keyword(sym::solidity)
409            || (self.token.is_ident()
410                && self.look_ahead_with(1, |t| t.is_op() || t.is_rational_lit()))
411        {
412            // `pragma <ident> <req>;`
413            let ident = self.parse_ident_any()?;
414            let req = self.parse_semver_req()?;
415            PragmaTokens::Version(ident, req)
416        } else if (is_ident_or_strlit(self.token) && self.look_ahead(1).kind == TokenKind::Semi)
417            || (is_ident_or_strlit(self.token)
418                && self.look_ahead_with(1, is_ident_or_strlit)
419                && self.look_ahead(2).kind == TokenKind::Semi)
420        {
421            // `pragma <k>;`
422            // `pragma <k> <v>;`
423            let k = self.parse_ident_or_strlit()?;
424            let v = if self.token.is_ident() || self.token.is_str_lit() {
425                Some(self.parse_ident_or_strlit()?)
426            } else {
427                None
428            };
429            PragmaTokens::Custom(k, v)
430        } else {
431            let mut tokens = Vec::new();
432            while !matches!(self.token.kind, TokenKind::Semi | TokenKind::Eof) {
433                tokens.push(self.token);
434                self.bump();
435            }
436            if !self.token.is_eof() && tokens.is_empty() {
437                let msg = "expected at least one token in pragma directive";
438                self.dcx().err(msg).span(self.prev_token.span).emit();
439            }
440            PragmaTokens::Verbatim(self.alloc_vec(tokens))
441        };
442        self.expect_semi()?;
443        Ok(PragmaDirective { tokens })
444    }
445
446    fn parse_ident_or_strlit(&mut self) -> PResult<'sess, IdentOrStrLit> {
447        if self.check_ident() {
448            self.parse_ident().map(IdentOrStrLit::Ident)
449        } else if self.check_str_lit() {
450            self.parse_str_lit().map(IdentOrStrLit::StrLit)
451        } else {
452            self.unexpected()
453        }
454    }
455
456    /// Parses a SemVer version requirement.
457    ///
458    /// See `crates/ast/src/ast/semver.rs` for more details on the implementation.
459    pub fn parse_semver_req(&mut self) -> PResult<'sess, SemverReq<'ast>> {
460        if self.check_noexpect(TokenKind::Semi) || self.check_noexpect(TokenKind::Eof) {
461            let msg = "empty version requirement";
462            let span = self.prev_token.span.to(self.token.span);
463            return Err(self.dcx().err(msg).span(span));
464        }
465        self.parse_semver_req_components_dis().map(|dis| SemverReq { dis })
466    }
467
468    /// `any(c)`
469    fn parse_semver_req_components_dis(
470        &mut self,
471    ) -> PResult<'sess, Box<'ast, [SemverReqCon<'ast>]>> {
472        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L170
473        let mut dis = Vec::new();
474        loop {
475            dis.push(self.parse_semver_req_components_con()?);
476            if self.eat(TokenKind::OrOr) {
477                continue;
478            }
479            if self.check(TokenKind::Semi) || self.check(TokenKind::Eof) {
480                break;
481            }
482            // `parse_semver_req_components_con` parses a single range,
483            // or all the values until `||`.
484            debug_assert!(
485                matches!(
486                    dis.last().map(|x| &x.components),
487                    Some([
488                        ..,
489                        SemverReqComponent { span: _, kind: SemverReqComponentKind::Range(..) }
490                    ])
491                ),
492                "not a range: last={:?}",
493                dis.last()
494            );
495            return Err(self.dcx().err("ranges can only be combined using the || operator"));
496        }
497        Ok(self.alloc_vec(dis))
498    }
499
500    /// `all(c)`
501    fn parse_semver_req_components_con(&mut self) -> PResult<'sess, SemverReqCon<'ast>> {
502        // component - component (range)
503        // or component component* (conjunction)
504
505        let mut components = Vec::new();
506        let lo = self.token.span;
507        let (op, v) = self.parse_semver_component()?;
508        if self.eat(TokenKind::BinOp(BinOpToken::Minus)) {
509            // range
510            // Ops are parsed and overwritten: https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L210
511            let _ = op;
512            let (_second_op, right) = self.parse_semver_component()?;
513            let kind = SemverReqComponentKind::Range(v, right);
514            let span = lo.to(self.prev_token.span);
515            components.push(SemverReqComponent { span, kind });
516        } else {
517            // conjunction; first is already parsed
518            let span = lo.to(self.prev_token.span);
519            let kind = SemverReqComponentKind::Op(op, v);
520            components.push(SemverReqComponent { span, kind });
521            // others
522            while !matches!(self.token.kind, TokenKind::OrOr | TokenKind::Eof | TokenKind::Semi) {
523                let (span, (op, v)) = self.parse_spanned(Self::parse_semver_component)?;
524                let kind = SemverReqComponentKind::Op(op, v);
525                components.push(SemverReqComponent { span, kind });
526            }
527        }
528        let span = lo.to(self.prev_token.span);
529        let components = self.alloc_vec(components);
530        Ok(SemverReqCon { span, components })
531    }
532
533    fn parse_semver_component(&mut self) -> PResult<'sess, (Option<SemverOp>, SemverVersion)> {
534        let op = self.parse_semver_op();
535        let v = self.parse_semver_version()?;
536        Ok((op, v))
537    }
538
539    fn parse_semver_op(&mut self) -> Option<SemverOp> {
540        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L227
541        let op = match self.token.kind {
542            TokenKind::Eq => SemverOp::Exact,
543            TokenKind::Gt => SemverOp::Greater,
544            TokenKind::Ge => SemverOp::GreaterEq,
545            TokenKind::Lt => SemverOp::Less,
546            TokenKind::Le => SemverOp::LessEq,
547            TokenKind::Tilde => SemverOp::Tilde,
548            TokenKind::BinOp(BinOpToken::Caret) => SemverOp::Caret,
549            _ => return None,
550        };
551        self.bump();
552        Some(op)
553    }
554
555    fn parse_semver_version(&mut self) -> PResult<'sess, SemverVersion> {
556        Ok(SemverVersionParser::new(self).parse())
557    }
558
559    /// Parses an import directive.
560    fn parse_import(&mut self) -> PResult<'sess, ImportDirective<'ast>> {
561        let path;
562        let items = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
563            // * as alias from ""
564            let alias = self.parse_as_alias()?;
565            self.expect_keyword(sym::from)?;
566            path = self.parse_str_lit()?;
567            ImportItems::Glob(alias)
568        } else if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
569            // { x as y, ... } from ""
570            let list = self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
571                let name = this.parse_ident()?;
572                let alias = this.parse_as_alias_opt()?;
573                Ok((name, alias))
574            })?;
575            self.expect_keyword(sym::from)?;
576            path = self.parse_str_lit()?;
577            ImportItems::Aliases(list)
578        } else {
579            // "" as alias
580            path = self.parse_str_lit()?;
581            let alias = self.parse_as_alias_opt()?;
582            ImportItems::Plain(alias)
583        };
584        if path.value.as_str().is_empty() {
585            let msg = "import path cannot be empty";
586            self.dcx().err(msg).span(path.span).emit();
587        }
588        self.expect_semi()?;
589        Ok(ImportDirective { path, items })
590    }
591
592    /// Parses an optional `as` alias identifier.
593    fn parse_as_alias_opt(&mut self) -> PResult<'sess, Option<Ident>> {
594        if self.eat_keyword(kw::As) {
595            self.parse_ident().map(Some)
596        } else {
597            Ok(None)
598        }
599    }
600
601    /// Parses an `as` alias identifier.
602    fn parse_as_alias(&mut self) -> PResult<'sess, Ident> {
603        self.expect_keyword(kw::As)?;
604        self.parse_ident()
605    }
606
607    /// Parses a using directive.
608    fn parse_using(&mut self) -> PResult<'sess, UsingDirective<'ast>> {
609        let list = self.parse_using_list()?;
610        self.expect_keyword(kw::For)?;
611        let ty = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
612            None
613        } else {
614            Some(self.parse_type()?)
615        };
616        let global = self.eat_keyword(sym::global);
617        self.expect_semi()?;
618        Ok(UsingDirective { list, ty, global })
619    }
620
621    fn parse_using_list(&mut self) -> PResult<'sess, UsingList<'ast>> {
622        if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
623            self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
624                let path = this.parse_path()?;
625                let op = if this.eat_keyword(kw::As) {
626                    Some(this.parse_user_definable_operator()?)
627                } else {
628                    None
629                };
630                Ok((path, op))
631            })
632            .map(UsingList::Multiple)
633        } else {
634            self.parse_path().map(UsingList::Single)
635        }
636    }
637
638    fn parse_user_definable_operator(&mut self) -> PResult<'sess, UserDefinableOperator> {
639        use BinOpToken::*;
640        use TokenKind::*;
641        use UserDefinableOperator as Op;
642        macro_rules! user_op {
643            ($($tok1:tt $(($tok2:tt))? => $op:expr),* $(,)?) => {
644                match self.token.kind {
645                    $($tok1 $(($tok2))? => $op,)*
646                    _ => {
647                        self.expected_tokens.extend_from_slice(&[$(ExpectedToken::Token($tok1 $(($tok2))?)),*]);
648                        return self.unexpected();
649                    }
650                }
651            };
652        }
653        let op = user_op! {
654            BinOp(And) => Op::BitAnd,
655            Tilde => Op::BitNot,
656            BinOp(Or) => Op::BitOr,
657            BinOp(Caret) => Op::BitXor,
658            BinOp(Plus) => Op::Add,
659            BinOp(Slash) => Op::Div,
660            BinOp(Percent) => Op::Rem,
661            BinOp(Star) => Op::Mul,
662            BinOp(Minus) => Op::Sub,
663            EqEq => Op::Eq,
664            Ge => Op::Ge,
665            Gt => Op::Gt,
666            Le => Op::Le,
667            Lt => Op::Lt,
668            Ne => Op::Ne,
669        };
670        self.bump();
671        Ok(op)
672    }
673
674    /* ----------------------------------------- Common ----------------------------------------- */
675
676    /// Parses a variable declaration/definition.
677    ///
678    /// `state-variable-declaration`, `constant-variable-declaration`, `variable-declaration`,
679    /// `variable-declaration-statement`, and more.
680    pub(super) fn parse_variable_definition(
681        &mut self,
682        flags: VarFlags,
683    ) -> PResult<'sess, VariableDefinition<'ast>> {
684        self.parse_variable_definition_with(flags, None)
685    }
686
687    pub(super) fn parse_variable_definition_with(
688        &mut self,
689        flags: VarFlags,
690        ty: Option<Type<'ast>>,
691    ) -> PResult<'sess, VariableDefinition<'ast>> {
692        let mut lo = self.token.span;
693        let ty = match ty {
694            Some(ty) => {
695                lo = lo.with_lo(ty.span.lo());
696                ty
697            }
698            None => self.parse_type()?,
699        };
700
701        if ty.is_function()
702            && flags == VarFlags::STATE_VAR
703            && self.check_noexpect(TokenKind::OpenDelim(Delimiter::Brace))
704        {
705            let msg = "expected a state variable declaration";
706            let note = "this style of fallback function has been removed; use the `fallback` or `receive` keywords instead";
707            self.dcx().err(msg).span(self.token.span).note(note).emit();
708            let _ = self.parse_block()?;
709            return Ok(VariableDefinition {
710                span: lo.to(self.prev_token.span),
711                ty,
712                visibility: None,
713                mutability: None,
714                data_location: None,
715                override_: None,
716                indexed: false,
717                name: None,
718                initializer: None,
719            });
720        }
721
722        let mut data_location = None;
723        let mut visibility = None;
724        let mut mutability = None;
725        let mut override_ = None;
726        let mut indexed = false;
727        loop {
728            if let Some(s) = self.parse_data_location() {
729                if !flags.contains(VarFlags::DATALOC) {
730                    let msg = "data locations are not allowed here";
731                    self.dcx().err(msg).span(self.prev_token.span).emit();
732                } else if data_location.is_some() {
733                    let msg = "data location already specified";
734                    self.dcx().err(msg).span(self.prev_token.span).emit();
735                } else {
736                    data_location = Some(s);
737                }
738            } else if let Some(v) = self.parse_visibility() {
739                if !flags.contains(VarFlags::from_visibility(v)) {
740                    let msg = visibility_error(v, flags.visibilities());
741                    self.dcx().err(msg).span(self.prev_token.span).emit();
742                } else if visibility.is_some() {
743                    let msg = "visibility already specified";
744                    self.dcx().err(msg).span(self.prev_token.span).emit();
745                } else {
746                    visibility = Some(v);
747                }
748            } else if let Some(m) = self.parse_variable_mutability() {
749                // `CONSTANT_VAR` is special cased later.
750                if flags != VarFlags::CONSTANT_VAR && !flags.contains(VarFlags::from_varmut(m)) {
751                    let msg = varmut_error(m, flags.varmuts());
752                    self.dcx().err(msg).span(self.prev_token.span).emit();
753                } else if mutability.is_some() {
754                    let msg = "mutability already specified";
755                    self.dcx().err(msg).span(self.prev_token.span).emit();
756                } else {
757                    mutability = Some(m);
758                }
759            } else if self.eat_keyword(kw::Indexed) {
760                if !flags.contains(VarFlags::INDEXED) {
761                    let msg = "`indexed` is not allowed here";
762                    self.dcx().err(msg).span(self.prev_token.span).emit();
763                } else if indexed {
764                    let msg = "`indexed` already specified";
765                    self.dcx().err(msg).span(self.prev_token.span).emit();
766                } else {
767                    indexed = true;
768                }
769            } else if self.eat_keyword(kw::Virtual) {
770                let msg = "`virtual` is not allowed here";
771                self.dcx().err(msg).span(self.prev_token.span).emit();
772            } else if self.eat_keyword(kw::Override) {
773                let o = self.parse_override()?;
774                if !flags.contains(VarFlags::OVERRIDE) {
775                    let msg = "`override` is not allowed here";
776                    self.dcx().err(msg).span(self.prev_token.span).emit();
777                } else if override_.is_some() {
778                    let msg = "override already specified";
779                    self.dcx().err(msg).span(self.prev_token.span).emit();
780                } else {
781                    override_ = Some(o);
782                }
783            } else {
784                break;
785            }
786        }
787
788        let name = if flags.contains(VarFlags::NAME) {
789            self.parse_ident().map(Some)
790        } else {
791            self.parse_ident_opt()
792        }?;
793        if let Some(name) = &name {
794            if flags.contains(VarFlags::NAME_WARN) {
795                debug_assert!(!flags.contains(VarFlags::NAME));
796                let msg = "named function type parameters are deprecated";
797                self.dcx().warn(msg).code(error_code!(6162)).span(name.span).emit();
798            }
799        }
800
801        let initializer = if flags.contains(VarFlags::INITIALIZER) && self.eat(TokenKind::Eq) {
802            Some(self.parse_expr()?)
803        } else {
804            None
805        };
806
807        if flags.contains(VarFlags::SEMI) {
808            self.expect_semi()?;
809        }
810
811        let span = lo.to(self.prev_token.span);
812
813        if mutability == Some(VarMut::Constant) && initializer.is_none() {
814            let msg = "constant variable must be initialized";
815            self.dcx().err(msg).span(span).emit();
816        }
817        if flags == VarFlags::CONSTANT_VAR && mutability != Some(VarMut::Constant) {
818            let msg = "only constant variables are allowed at file level";
819            self.dcx().err(msg).span(span).emit();
820        }
821
822        Ok(VariableDefinition {
823            span,
824            ty,
825            data_location,
826            visibility,
827            mutability,
828            override_,
829            indexed,
830            name,
831            initializer,
832        })
833    }
834
835    /// Parses mutability of a variable: `constant | immutable`.
836    fn parse_variable_mutability(&mut self) -> Option<VarMut> {
837        if self.eat_keyword(kw::Constant) {
838            Some(VarMut::Constant)
839        } else if self.eat_keyword(kw::Immutable) {
840            Some(VarMut::Immutable)
841        } else {
842            None
843        }
844    }
845
846    /// Parses a parameter list: `($(vardecl),*)`.
847    pub(super) fn parse_parameter_list(
848        &mut self,
849        allow_empty: bool,
850        flags: VarFlags,
851    ) -> PResult<'sess, ParameterList<'ast>> {
852        self.parse_paren_comma_seq(allow_empty, |this| this.parse_variable_definition(flags))
853    }
854
855    /// Parses a list of inheritance specifiers.
856    fn parse_inheritance(&mut self) -> PResult<'sess, Box<'ast, [Modifier<'ast>]>> {
857        let mut list = SmallVec::<[_; 8]>::new();
858        loop {
859            list.push(self.parse_modifier()?);
860            if !self.eat(TokenKind::Comma) {
861                break;
862            }
863        }
864        Ok(self.alloc_smallvec(list))
865    }
866
867    /// Parses a storage layout specifier.
868    fn parse_storage_layout_specifier(&mut self) -> PResult<'sess, StorageLayoutSpecifier<'ast>> {
869        let lo = self.token.span;
870        self.expect_keyword(sym::layout)?;
871        self.expect_keyword(sym::at)?;
872        let slot = self.parse_expr()?;
873        Ok(StorageLayoutSpecifier { span: lo.to(self.prev_token.span), slot })
874    }
875
876    /// Parses a single modifier invocation.
877    fn parse_modifier(&mut self) -> PResult<'sess, Modifier<'ast>> {
878        let name = self.parse_path()?;
879        let arguments = if self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis) {
880            self.parse_call_args()?
881        } else {
882            CallArgs::empty(name.span().shrink_to_hi())
883        };
884        Ok(Modifier { name, arguments })
885    }
886
887    /// Parses a single function override.
888    ///
889    /// Expects the `override` to have already been eaten.
890    fn parse_override(&mut self) -> PResult<'sess, Override<'ast>> {
891        debug_assert!(self.prev_token.is_keyword(kw::Override));
892        let lo = self.prev_token.span;
893        let paths = if self.token.is_open_delim(Delimiter::Parenthesis) {
894            self.parse_paren_comma_seq(false, Self::parse_path)?
895        } else {
896            Default::default()
897        };
898        let span = lo.to(self.prev_token.span);
899        Ok(Override { span, paths })
900    }
901
902    /// Parses a single string literal. This is only used in import paths and statements, not
903    /// expressions.
904    pub(super) fn parse_str_lit(&mut self) -> PResult<'sess, StrLit> {
905        match self.parse_str_lit_opt() {
906            Some(lit) => Ok(lit),
907            None => self.unexpected(),
908        }
909    }
910
911    /// Parses a single optional string literal. This is only used in import paths and statements,
912    /// not expressions.
913    pub(super) fn parse_str_lit_opt(&mut self) -> Option<StrLit> {
914        if !self.check_str_lit() {
915            return None;
916        }
917        let Token { kind: TokenKind::Literal(TokenLitKind::Str, symbol), span } = self.token else {
918            unreachable!()
919        };
920        self.bump();
921        Some(StrLit { span, value: symbol })
922    }
923
924    /// Parses a storage location: `storage | memory | calldata | transient`.
925    fn parse_data_location(&mut self) -> Option<DataLocation> {
926        if self.eat_keyword(kw::Storage) {
927            Some(DataLocation::Storage)
928        } else if self.eat_keyword(kw::Memory) {
929            Some(DataLocation::Memory)
930        } else if self.eat_keyword(kw::Calldata) {
931            Some(DataLocation::Calldata)
932        } else if self.check_keyword(sym::transient)
933            && !matches!(
934                self.look_ahead(1).kind,
935                TokenKind::Eq | TokenKind::Semi | TokenKind::CloseDelim(_) | TokenKind::Comma
936            )
937        {
938            self.bump(); // `transient`
939            Some(DataLocation::Transient)
940        } else {
941            None
942        }
943    }
944
945    /// Parses a visibility: `public | private | internal | external`.
946    pub(super) fn parse_visibility(&mut self) -> Option<Visibility> {
947        if self.eat_keyword(kw::Public) {
948            Some(Visibility::Public)
949        } else if self.eat_keyword(kw::Private) {
950            Some(Visibility::Private)
951        } else if self.eat_keyword(kw::Internal) {
952            Some(Visibility::Internal)
953        } else if self.eat_keyword(kw::External) {
954            Some(Visibility::External)
955        } else {
956            None
957        }
958    }
959
960    /// Parses state mutability: `payable | pure | view`.
961    pub(super) fn parse_state_mutability(&mut self) -> Option<StateMutability> {
962        if self.eat_keyword(kw::Payable) {
963            Some(StateMutability::Payable)
964        } else if self.eat_keyword(kw::Pure) {
965            Some(StateMutability::Pure)
966        } else if self.eat_keyword(kw::View) {
967            Some(StateMutability::View)
968        } else {
969            None
970        }
971    }
972}
973
974struct SemverVersionParser<'p, 'sess, 'ast> {
975    p: &'p mut Parser<'sess, 'ast>,
976    bumps: u32,
977    pos_inside: u32,
978}
979
980impl<'p, 'sess, 'ast> SemverVersionParser<'p, 'sess, 'ast> {
981    fn new(p: &'p mut Parser<'sess, 'ast>) -> Self {
982        Self { p, bumps: 0, pos_inside: 0 }
983    }
984
985    fn emit_err(&self, msg: impl Into<DiagMsg>) {
986        self.p.dcx().err(msg).span(self.current_span()).emit();
987    }
988
989    fn parse(mut self) -> SemverVersion {
990        let lo = self.current_span();
991        let major = self.parse_version_part();
992        let mut minor = None;
993        let mut patch = None;
994        if self.eat_dot() {
995            minor = Some(self.parse_version_part());
996            if self.eat_dot() {
997                patch = Some(self.parse_version_part());
998            }
999        }
1000        if self.pos_inside > 0 || self.bumps == 0 {
1001            self.emit_err("unexpected trailing characters");
1002            self.bump_token();
1003        }
1004        SemverVersion { span: lo.to(self.current_span()), major, minor, patch }
1005    }
1006
1007    fn eat_dot(&mut self) -> bool {
1008        let r = self.current_char() == Some('.');
1009        if r {
1010            self.bump_char();
1011        }
1012        r
1013    }
1014
1015    fn parse_version_part(&mut self) -> SemverVersionNumber {
1016        match self.current_char() {
1017            Some('*' | 'x' | 'X') => {
1018                self.bump_char();
1019                SemverVersionNumber::Wildcard
1020            }
1021            Some('0'..='9') => {
1022                let s = self.current_str().unwrap();
1023                let len = s.bytes().take_while(u8::is_ascii_digit).count();
1024                let result = s[..len].parse();
1025                self.bump_chars(len as u32);
1026                let Ok(n) = result else {
1027                    self.emit_err("version number too large");
1028                    return SemverVersionNumber::Wildcard;
1029                };
1030                SemverVersionNumber::Number(n)
1031            }
1032            _ => {
1033                self.emit_err("expected version number");
1034                self.bump_char();
1035                SemverVersionNumber::Wildcard
1036            }
1037        }
1038    }
1039
1040    fn current_char(&self) -> Option<char> {
1041        self.current_str()?.chars().next()
1042    }
1043
1044    fn current_str(&self) -> Option<&str> {
1045        self.current_token_str()?.get(self.pos_inside as usize..)
1046    }
1047
1048    fn current_token_str(&self) -> Option<&str> {
1049        Some(match &self.current_token().kind {
1050            TokenKind::Dot => ".",
1051            TokenKind::BinOp(BinOpToken::Star) => "*",
1052            TokenKind::Ident(s) | TokenKind::Literal(_, s) => s.as_str(),
1053            _ => return None,
1054        })
1055    }
1056
1057    fn current_token(&self) -> &Token {
1058        &self.p.token
1059    }
1060
1061    fn current_span(&self) -> Span {
1062        let mut s = self.current_token().span;
1063        if self.pos_inside > 0 {
1064            s = s.with_lo(s.lo() + self.pos_inside);
1065        }
1066        s
1067    }
1068
1069    fn bump_char(&mut self) {
1070        self.bump_chars(1);
1071    }
1072
1073    fn bump_chars(&mut self, n: u32) {
1074        if let Some(s) = self.current_token_str() {
1075            if self.pos_inside + n >= s.len() as u32 {
1076                self.bump_token();
1077            } else {
1078                self.pos_inside += n;
1079            }
1080        }
1081    }
1082
1083    fn bump_token(&mut self) {
1084        self.p.bump();
1085        self.bumps += 1;
1086        self.pos_inside = 0;
1087    }
1088}
1089
1090bitflags::bitflags! {
1091    /// Flags for parsing variable declarations.
1092    #[derive(Clone, Copy, PartialEq, Eq)]
1093    pub(super) struct VarFlags: u16 {
1094        // `ty` is always required. `name` is always optional, unless `NAME` is specified.
1095
1096        const DATALOC     = 1 << 1;
1097        const INDEXED     = 1 << 2;
1098
1099        const PRIVATE     = 1 << 3;
1100        const INTERNAL    = 1 << 4;
1101        const PUBLIC      = 1 << 5;
1102        const EXTERNAL    = 1 << 6; // Never accepted, just for error messages.
1103        const VISIBILITY  = Self::PRIVATE.bits()
1104                          | Self::INTERNAL.bits()
1105                          | Self::PUBLIC.bits()
1106                          | Self::EXTERNAL.bits();
1107
1108        const CONSTANT    = 1 << 7;
1109        const IMMUTABLE   = 1 << 8;
1110
1111        const OVERRIDE    = 1 << 9;
1112
1113        const NAME        = 1 << 10;
1114        const NAME_WARN   = 1 << 11;
1115
1116        const INITIALIZER = 1 << 12;
1117        const SEMI        = 1 << 13;
1118
1119        const STRUCT       = Self::NAME.bits();
1120        const ERROR        = 0;
1121        const EVENT        = Self::INDEXED.bits();
1122        const FUNCTION     = Self::DATALOC.bits();
1123        const FUNCTION_TY  = Self::DATALOC.bits() | Self::NAME_WARN.bits();
1124
1125        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration
1126        const STATE_VAR    = Self::DATALOC.bits()
1127                           | Self::PRIVATE.bits()
1128                           | Self::INTERNAL.bits()
1129                           | Self::PUBLIC.bits()
1130                           | Self::CONSTANT.bits()
1131                           | Self::IMMUTABLE.bits()
1132                           | Self::OVERRIDE.bits()
1133                           | Self::NAME.bits()
1134                           | Self::INITIALIZER.bits()
1135                           | Self::SEMI.bits();
1136
1137        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constantVariableDeclaration
1138        const CONSTANT_VAR = Self::CONSTANT.bits()
1139                           | Self::NAME.bits()
1140                           | Self::INITIALIZER.bits()
1141                           | Self::SEMI.bits();
1142
1143        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.variableDeclarationStatement
1144        const VAR = Self::DATALOC.bits() | Self::INITIALIZER.bits();
1145    }
1146
1147    /// Flags for parsing function headers.
1148    #[derive(Clone, Copy, PartialEq, Eq)]
1149    pub(super) struct FunctionFlags: u16 {
1150        /// Name is required.
1151        const NAME             = 1 << 0;
1152        /// Function type: parameter names are parsed, but issue a warning.
1153        const PARAM_NAME       = 1 << 1;
1154        /// Parens can be omitted.
1155        const NO_PARENS        = 1 << 2;
1156
1157        // Visibility
1158        const PRIVATE          = 1 << 3;
1159        const INTERNAL         = 1 << 4;
1160        const PUBLIC           = 1 << 5;
1161        const EXTERNAL         = 1 << 6;
1162        const VISIBILITY       = Self::PRIVATE.bits()
1163                               | Self::INTERNAL.bits()
1164                               | Self::PUBLIC.bits()
1165                               | Self::EXTERNAL.bits();
1166
1167        // StateMutability
1168        const PURE             = 1 << 7;
1169        const VIEW             = 1 << 8;
1170        const PAYABLE          = 1 << 9;
1171        const STATE_MUTABILITY = Self::PURE.bits()
1172                               | Self::VIEW.bits()
1173                               | Self::PAYABLE.bits();
1174
1175        const MODIFIERS        = 1 << 10;
1176        const VIRTUAL          = 1 << 11;
1177        const OVERRIDE         = 1 << 12;
1178
1179        const RETURNS          = 1 << 13;
1180        /// Must be implemented, meaning it must end in a `{}` implementation block.
1181        const ONLY_BLOCK       = 1 << 14;
1182
1183        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constructorDefinition
1184        const CONSTRUCTOR = Self::MODIFIERS.bits()
1185                          | Self::PAYABLE.bits()
1186                          | Self::INTERNAL.bits()
1187                          | Self::PUBLIC.bits()
1188                          | Self::ONLY_BLOCK.bits();
1189
1190        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionDefinition
1191        const FUNCTION    = Self::NAME.bits()
1192                          | Self::VISIBILITY.bits()
1193                          | Self::STATE_MUTABILITY.bits()
1194                          | Self::MODIFIERS.bits()
1195                          | Self::VIRTUAL.bits()
1196                          | Self::OVERRIDE.bits()
1197                          | Self::RETURNS.bits();
1198
1199        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.modifierDefinition
1200        const MODIFIER    = Self::NAME.bits()
1201                          | Self::NO_PARENS.bits()
1202                          | Self::VIRTUAL.bits()
1203                          | Self::OVERRIDE.bits();
1204
1205        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.fallbackFunctionDefinition
1206        const FALLBACK    = Self::EXTERNAL.bits()
1207                          | Self::STATE_MUTABILITY.bits()
1208                          | Self::MODIFIERS.bits()
1209                          | Self::VIRTUAL.bits()
1210                          | Self::OVERRIDE.bits()
1211                          | Self::RETURNS.bits();
1212
1213        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.receiveFunctionDefinition
1214        const RECEIVE     = Self::EXTERNAL.bits()
1215                          | Self::PAYABLE.bits()
1216                          | Self::MODIFIERS.bits()
1217                          | Self::VIRTUAL.bits()
1218                          | Self::OVERRIDE.bits();
1219
1220        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionTypeName
1221        const FUNCTION_TY = Self::PARAM_NAME.bits()
1222                          | Self::VISIBILITY.bits()
1223                          | Self::STATE_MUTABILITY.bits()
1224                          | Self::RETURNS.bits();
1225    }
1226}
1227
1228impl VarFlags {
1229    fn from_visibility(v: Visibility) -> Self {
1230        match v {
1231            Visibility::Private => Self::PRIVATE,
1232            Visibility::Internal => Self::INTERNAL,
1233            Visibility::Public => Self::PUBLIC,
1234            Visibility::External => Self::EXTERNAL,
1235        }
1236    }
1237
1238    fn into_visibility(self) -> Option<Visibility> {
1239        match self {
1240            Self::PRIVATE => Some(Visibility::Private),
1241            Self::INTERNAL => Some(Visibility::Internal),
1242            Self::PUBLIC => Some(Visibility::Public),
1243            Self::EXTERNAL => Some(Visibility::External),
1244            _ => None,
1245        }
1246    }
1247
1248    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1249        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1250    }
1251
1252    fn from_varmut(v: VarMut) -> Self {
1253        match v {
1254            VarMut::Constant => Self::CONSTANT,
1255            VarMut::Immutable => Self::IMMUTABLE,
1256        }
1257    }
1258
1259    fn into_varmut(self) -> Option<VarMut> {
1260        match self {
1261            Self::CONSTANT => Some(VarMut::Constant),
1262            Self::IMMUTABLE => Some(VarMut::Immutable),
1263            _ => None,
1264        }
1265    }
1266
1267    fn varmuts(self) -> Option<impl Iterator<Item = VarMut>> {
1268        self.supported(Self::CONSTANT | Self::IMMUTABLE)
1269            .map(|iter| iter.map(|x| x.into_varmut().unwrap()))
1270    }
1271
1272    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1273        let s = self.intersection(what);
1274        if s.is_empty() {
1275            None
1276        } else {
1277            Some(s.iter())
1278        }
1279    }
1280}
1281
1282impl FunctionFlags {
1283    fn from_kind(kind: FunctionKind) -> Self {
1284        match kind {
1285            FunctionKind::Constructor => Self::CONSTRUCTOR,
1286            FunctionKind::Function => Self::FUNCTION,
1287            FunctionKind::Modifier => Self::MODIFIER,
1288            FunctionKind::Receive => Self::RECEIVE,
1289            FunctionKind::Fallback => Self::FALLBACK,
1290        }
1291    }
1292
1293    fn from_visibility(visibility: Visibility) -> Self {
1294        match visibility {
1295            Visibility::Private => Self::PRIVATE,
1296            Visibility::Internal => Self::INTERNAL,
1297            Visibility::Public => Self::PUBLIC,
1298            Visibility::External => Self::EXTERNAL,
1299        }
1300    }
1301
1302    fn into_visibility(self) -> Option<Visibility> {
1303        match self {
1304            Self::PRIVATE => Some(Visibility::Private),
1305            Self::INTERNAL => Some(Visibility::Internal),
1306            Self::PUBLIC => Some(Visibility::Public),
1307            Self::EXTERNAL => Some(Visibility::External),
1308            _ => None,
1309        }
1310    }
1311
1312    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1313        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1314    }
1315
1316    fn from_state_mutability(state_mutability: StateMutability) -> Self {
1317        match state_mutability {
1318            StateMutability::Pure => Self::PURE,
1319            StateMutability::View => Self::VIEW,
1320            StateMutability::Payable => Self::PAYABLE,
1321            StateMutability::NonPayable => unreachable!(),
1322        }
1323    }
1324
1325    fn into_state_mutability(self) -> Option<StateMutability> {
1326        match self {
1327            Self::PURE => Some(StateMutability::Pure),
1328            Self::VIEW => Some(StateMutability::View),
1329            Self::PAYABLE => Some(StateMutability::Payable),
1330            _ => None,
1331        }
1332    }
1333
1334    fn state_mutabilities(self) -> Option<impl Iterator<Item = StateMutability>> {
1335        self.supported(Self::STATE_MUTABILITY)
1336            .map(|iter| iter.map(|x| x.into_state_mutability().unwrap()))
1337    }
1338
1339    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1340        let s = self.intersection(what);
1341        if s.is_empty() {
1342            None
1343        } else {
1344            Some(s.iter())
1345        }
1346    }
1347}
1348
1349fn visibility_error(v: Visibility, iter: Option<impl Iterator<Item = Visibility>>) -> String {
1350    common_flags_error(v, "visibility", iter)
1351}
1352
1353fn varmut_error(m: VarMut, iter: Option<impl Iterator<Item = VarMut>>) -> String {
1354    common_flags_error(m, "mutability", iter)
1355}
1356
1357fn state_mutability_error(
1358    m: StateMutability,
1359    iter: Option<impl Iterator<Item = StateMutability>>,
1360) -> String {
1361    common_flags_error(m, "state mutability", iter)
1362}
1363
1364fn common_flags_error<T: std::fmt::Display>(
1365    t: T,
1366    desc: &str,
1367    iter: Option<impl Iterator<Item = T>>,
1368) -> String {
1369    match iter {
1370        Some(iter) => format!("`{t}` not allowed here; allowed values: {}", iter.format(", ")),
1371        None => format!("{desc} is not allowed here"),
1372    }
1373}
1374
1375#[cfg(test)]
1376mod tests {
1377    use super::*;
1378    use solar_interface::{source_map::FileName, Result, Session};
1379
1380    fn assert_version_matches(tests: &[(&str, &str, bool)]) {
1381        let sess = Session::builder().with_test_emitter().build();
1382        sess.enter(|| -> Result {
1383            for (i, &(v, req_s, res)) in tests.iter().enumerate() {
1384                let name = i.to_string();
1385                let src = format!("{v} {req_s}");
1386                let arena = Arena::new();
1387                let mut parser =
1388                    Parser::from_source_code(&sess, &arena, FileName::Custom(name), src)?;
1389
1390                let version = parser.parse_semver_version().map_err(|e| e.emit()).unwrap();
1391                assert_eq!(version.to_string(), v);
1392                let req: SemverReq<'_> = parser.parse_semver_req().map_err(|e| e.emit()).unwrap();
1393                sess.dcx.has_errors().unwrap();
1394                assert_eq!(req.matches(&version), res, "v={v:?}, req={req_s:?}");
1395            }
1396            Ok(())
1397        })
1398        .unwrap();
1399    }
1400
1401    #[test]
1402    fn semver_matches() {
1403        assert_version_matches(&[
1404            // none = eq
1405            ("0.8.1", "0", true),
1406            ("0.8.1", "1", false),
1407            ("0.8.1", "1.0", false),
1408            ("0.8.1", "1.0.0", false),
1409            ("0.8.1", "0.7", false),
1410            ("0.8.1", "0.7.0", false),
1411            ("0.8.1", "0.7.1", false),
1412            ("0.8.1", "0.7.2", false),
1413            ("0.8.1", "0.8", true),
1414            ("0.8.1", "0.8.0", false),
1415            ("0.8.1", "0.8.1", true),
1416            ("0.8.1", "0.8.2", false),
1417            ("0.8.1", "0.9", false),
1418            ("0.8.1", "0.9.0", false),
1419            ("0.8.1", "0.9.1", false),
1420            ("0.8.1", "0.9.2", false),
1421            // eq
1422            ("0.8.1", "=0", true),
1423            ("0.8.1", "=1", false),
1424            ("0.8.1", "=1.0", false),
1425            ("0.8.1", "=1.0.0", false),
1426            ("0.8.1", "=0.7", false),
1427            ("0.8.1", "=0.7.0", false),
1428            ("0.8.1", "=0.7.1", false),
1429            ("0.8.1", "=0.7.2", false),
1430            ("0.8.1", "=0.8", true),
1431            ("0.8.1", "=0.8.0", false),
1432            ("0.8.1", "=0.8.1", true),
1433            ("0.8.1", "=0.8.2", false),
1434            ("0.8.1", "=0.9", false),
1435            ("0.8.1", "=0.9.0", false),
1436            ("0.8.1", "=0.9.1", false),
1437            ("0.8.1", "=0.9.2", false),
1438            // gt
1439            ("0.8.1", ">0", false),
1440            ("0.8.1", ">1", false),
1441            ("0.8.1", ">1.0", false),
1442            ("0.8.1", ">1.0.0", false),
1443            ("0.8.1", ">0.7", true),
1444            ("0.8.1", ">0.7.0", true),
1445            ("0.8.1", ">0.7.1", true),
1446            ("0.8.1", ">0.7.2", true),
1447            ("0.8.1", ">0.8", false),
1448            ("0.8.1", ">0.8.0", true),
1449            ("0.8.1", ">0.8.1", false),
1450            ("0.8.1", ">0.8.2", false),
1451            ("0.8.1", ">0.9", false),
1452            ("0.8.1", ">0.9.0", false),
1453            ("0.8.1", ">0.9.1", false),
1454            ("0.8.1", ">0.9.2", false),
1455            // ge
1456            ("0.8.1", ">=0", true),
1457            ("0.8.1", ">=1", false),
1458            ("0.8.1", ">=1.0", false),
1459            ("0.8.1", ">=1.0.0", false),
1460            ("0.8.1", ">=0.7", true),
1461            ("0.8.1", ">=0.7.0", true),
1462            ("0.8.1", ">=0.7.1", true),
1463            ("0.8.1", ">=0.7.2", true),
1464            ("0.8.1", ">=0.8", true),
1465            ("0.8.1", ">=0.8.0", true),
1466            ("0.8.1", ">=0.8.1", true),
1467            ("0.8.1", ">=0.8.2", false),
1468            ("0.8.1", ">=0.9", false),
1469            ("0.8.1", ">=0.9.0", false),
1470            ("0.8.1", ">=0.9.1", false),
1471            ("0.8.1", ">=0.9.2", false),
1472            // lt
1473            ("0.8.1", "<0", false),
1474            ("0.8.1", "<1", true),
1475            ("0.8.1", "<1.0", true),
1476            ("0.8.1", "<1.0.0", true),
1477            ("0.8.1", "<0.7", false),
1478            ("0.8.1", "<0.7.0", false),
1479            ("0.8.1", "<0.7.1", false),
1480            ("0.8.1", "<0.7.2", false),
1481            ("0.8.1", "<0.8", false),
1482            ("0.8.1", "<0.8.0", false),
1483            ("0.8.1", "<0.8.1", false),
1484            ("0.8.1", "<0.8.2", true),
1485            ("0.8.1", "<0.9", true),
1486            ("0.8.1", "<0.9.0", true),
1487            ("0.8.1", "<0.9.1", true),
1488            ("0.8.1", "<0.9.2", true),
1489            // le
1490            ("0.8.1", "<=0", true),
1491            ("0.8.1", "<=1", true),
1492            ("0.8.1", "<=1.0", true),
1493            ("0.8.1", "<=1.0.0", true),
1494            ("0.8.1", "<=0.7", false),
1495            ("0.8.1", "<=0.7.0", false),
1496            ("0.8.1", "<=0.7.1", false),
1497            ("0.8.1", "<=0.7.2", false),
1498            ("0.8.1", "<=0.8", true),
1499            ("0.8.1", "<=0.8.0", false),
1500            ("0.8.1", "<=0.8.1", true),
1501            ("0.8.1", "<=0.8.2", true),
1502            ("0.8.1", "<=0.9.0", true),
1503            ("0.8.1", "<=0.9.1", true),
1504            ("0.8.1", "<=0.9.2", true),
1505            // tilde
1506            ("0.8.1", "~0", true),
1507            ("0.8.1", "~1", false),
1508            ("0.8.1", "~1.0", false),
1509            ("0.8.1", "~1.0.0", false),
1510            ("0.8.1", "~0.7", false),
1511            ("0.8.1", "~0.7.0", false),
1512            ("0.8.1", "~0.7.1", false),
1513            ("0.8.1", "~0.7.2", false),
1514            ("0.8.1", "~0.8", true),
1515            ("0.8.1", "~0.8.0", true),
1516            ("0.8.1", "~0.8.1", true),
1517            ("0.8.1", "~0.8.2", false),
1518            ("0.8.1", "~0.9.0", false),
1519            ("0.8.1", "~0.9.1", false),
1520            ("0.8.1", "~0.9.2", false),
1521            // caret
1522            ("0.8.1", "^0", true),
1523            ("0.8.1", "^1", false),
1524            ("0.8.1", "^1.0", false),
1525            ("0.8.1", "^1.0.0", false),
1526            ("0.8.1", "^0.7", false),
1527            ("0.8.1", "^0.7.0", false),
1528            ("0.8.1", "^0.7.1", false),
1529            ("0.8.1", "^0.7.2", false),
1530            ("0.8.1", "^0.8", true),
1531            ("0.8.1", "^0.8.0", true),
1532            ("0.8.1", "^0.8.1", true),
1533            ("0.8.1", "^0.8.2", false),
1534            ("0.8.1", "^0.9.0", false),
1535            ("0.8.1", "^0.9.1", false),
1536            ("0.8.1", "^0.9.2", false),
1537            // ranges
1538            ("0.8.1", "0 - 1", true),
1539            ("0.8.1", "0.1 - 1.1", true),
1540            ("0.8.1", "0.1.1 - 1.1.1", true),
1541            ("0.8.1", "0 - 0.8.1", true),
1542            ("0.8.1", "0 - 0.8.2", true),
1543            ("0.8.1", "0.7 - 0.8.1", true),
1544            ("0.8.1", "0.7 - 0.8.2", true),
1545            ("0.8.1", "0.8 - 0.8.1", true),
1546            ("0.8.1", "0.8 - 0.8.2", true),
1547            ("0.8.1", "0.8.0 - 0.8.1", true),
1548            ("0.8.1", "0.8.0 - 0.8.2", true),
1549            ("0.8.1", "0.8.0 - 0.9.0", true),
1550            ("0.8.1", "0.8.0 - 1.0.0", true),
1551            ("0.8.1", "0.8.1 - 0.8.1", true),
1552            ("0.8.1", "0.8.1 - 0.8.2", true),
1553            ("0.8.1", "0.8.1 - 0.9.0", true),
1554            ("0.8.1", "0.8.1 - 1.0.0", true),
1555            ("0.8.1", "0.7 - 0.8", true),
1556            ("0.8.1", "0.7.0 - 0.8", true),
1557            ("0.8.1", "0.8 - 0.8", true),
1558            ("0.8.1", "0.8.0 - 0.8", true),
1559            ("0.8.1", "0.8 - 0.8.0", false),
1560            ("0.8.1", "0.8 - 0.8.1", true),
1561            // or
1562            ("0.8.1", "0 || 0", true),
1563            ("0.8.1", "0 || 1", true),
1564            ("0.8.1", "1 || 0", true),
1565            ("0.8.1", "0.0 || 0.0", false),
1566            ("0.8.1", "0.0 || 1.0", false),
1567            ("0.8.1", "1.0 || 0.0", false),
1568            ("0.8.1", "0.7 || 0.8", true),
1569            ("0.8.1", "0.8 || 0.8", true),
1570            ("0.8.1", "0.8 || 0.8.1", true),
1571            ("0.8.1", "0.8 || 0.8.2", true),
1572            ("0.8.1", "0.8 || 0.9", true),
1573        ]);
1574    }
1575
1576    #[test]
1577    /// Test if the span of a function header is correct (should start at the function-like kw and
1578    /// end at the last token)
1579    fn function_header_span() {
1580        let test_functions = [
1581            "function foo(uint256 a) public view returns (uint256) {
1582}",
1583            "modifier foo() {
1584    _;
1585}",
1586            "receive() external payable {
1587}",
1588            "fallback() external payable {
1589}",
1590            "constructor() {
1591}",
1592        ];
1593
1594        let test_function_headers = [
1595            "function foo(uint256 a) public view returns (uint256)",
1596            "modifier foo()",
1597            "receive() external payable",
1598            "fallback() external payable",
1599            "constructor()",
1600        ];
1601
1602        for (idx, src) in test_functions.iter().enumerate() {
1603            let sess = Session::builder().with_test_emitter().build();
1604            sess.enter(|| -> Result {
1605                let arena = Arena::new();
1606                let mut parser = Parser::from_source_code(
1607                    &sess,
1608                    &arena,
1609                    FileName::Custom(String::from("test")),
1610                    *src,
1611                )?;
1612
1613                parser.in_contract = true; // Silence the wrong scope error
1614
1615                let header_span = parser.parse_function().unwrap().header.span;
1616
1617                assert_eq!(
1618                    header_span,
1619                    Span::new(
1620                        solar_interface::BytePos(0),
1621                        solar_interface::BytePos(test_function_headers[idx].len() as u32,),
1622                    ),
1623                );
1624
1625                Ok(())
1626            })
1627            .unwrap();
1628        }
1629    }
1630}