Skip to main content

yog_script_analyze/parser/
decl.rs

1//! Declarations: a file's, a body's — attributes, documentation and
2//! modifiers taken, then the first word whose form starts here parses it,
3//! else a member written type first.
4
5use super::{PResult, Parser};
6use crate::ast::{Attribute, Decl, DeclKind, File, Modifier};
7use crate::source::token::{Punct, Tok};
8use crate::words::{ALL, Role, r#ref, r#struct};
9
10impl Parser<'_, '_, '_> {
11    /// The whole source.
12    pub fn file(&mut self) -> File {
13        let mut decls = Vec::new();
14        while *self.tok() != Tok::Eof {
15            self.decl_into(&mut decls);
16        }
17        File { decls }
18    }
19
20    /// `{ decls }`.
21    pub(crate) fn body(&mut self) -> PResult<Vec<Decl>> {
22        self.need(Punct::LBrace)?;
23        self.braces(Self::decls_to_brace)
24    }
25
26    /// Declarations up to and with the `}` closing them.
27    pub(crate) fn decls_to_brace(&mut self) -> PResult<Vec<Decl>> {
28        let mut decls = Vec::new();
29        loop {
30            if self.eat(Punct::RBrace) {
31                return Ok(decls);
32            }
33            if *self.tok() == Tok::Eof {
34                return Err(self.expected("`}`"));
35            }
36            self.decl_into(&mut decls);
37        }
38    }
39
40    /// One declaration, or past it when it fails.
41    fn decl_into(&mut self, decls: &mut Vec<Decl>) {
42        match self.decl() {
43            Ok(d) => decls.push(d),
44            Err(_) => self.recover(),
45        }
46    }
47
48    pub(crate) fn decl(&mut self) -> PResult<Decl> {
49        let start = self.span();
50        let mut doc = Vec::new();
51        let mut attributes = Vec::new();
52        loop {
53            match self.tok() {
54                Tok::Doc(line) => {
55                    doc.push(line.clone());
56                    self.bump();
57                }
58                Tok::Punct(Punct::LBracket) => attributes.extend(self.attributes()?),
59                _ => break,
60            }
61        }
62        let mut modifiers = Vec::new();
63        while let Some(m) = self.modifier_here() {
64            modifiers.push(m);
65            self.bump();
66        }
67        let kind = self.decl_kind()?;
68        Ok(Decl {
69            attributes,
70            doc,
71            modifiers,
72            kind,
73            span: start.to(self.prev()),
74        })
75    }
76
77    /// `[A, B(…)]`.
78    fn attributes(&mut self) -> PResult<Vec<Attribute>> {
79        self.need(Punct::LBracket)?;
80        self.list(Punct::RBracket, |p| {
81            let path = p.path("an attribute")?;
82            let args = if p.at(Punct::LParen) {
83                p.args()?
84            } else {
85                Vec::new()
86            };
87            Ok(Attribute { path, args })
88        })
89    }
90
91    fn modifier_here(&self) -> Option<Modifier> {
92        // `ref` marks a type only as `ref struct`; elsewhere it's a borrow.
93        if self.at_word(&r#ref::WORD) && !self.nth_word(1, &r#struct::WORD) {
94            return None;
95        }
96        ALL.iter().filter(|w| self.at_word(w)).find_map(|w| {
97            w.role(|r| match r {
98                Role::Modifier(m) => Some(*m),
99                _ => None,
100            })
101        })
102    }
103
104    fn decl_kind(&mut self) -> PResult<DeclKind> {
105        // `Name = value;` is a property, whatever word the name is.
106        if matches!(self.tok(), Tok::Ident(_)) && self.nth_is(1, Punct::Eq) {
107            return self.prop().map(DeclKind::Prop);
108        }
109        for word in ALL {
110            for role in word.roles {
111                if let Role::Decl { starts, parse } = role
112                    && self.starts(word, *starts)
113                {
114                    return parse(self);
115                }
116            }
117        }
118        self.member()
119    }
120}