yog_script_analyze/parser/
decl.rs1use super::{PResult, Parser};
6use crate::ast::{Attribute, Decl, DeclKind, File, Modifier};
7use crate::source::token::{Punct, Tok};
8use crate::words::{ALL, Role};
9
10impl Parser<'_, '_, '_> {
11 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 pub(crate) fn body(&mut self) -> PResult<Vec<Decl>> {
22 self.need(Punct::LBrace)?;
23 self.braces(Self::decls_to_brace)
24 }
25
26 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 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 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 ALL.iter().filter(|w| self.at_word(w)).find_map(|w| {
93 w.role(|r| match r {
94 Role::Modifier(m) => Some(*m),
95 _ => None,
96 })
97 })
98 }
99
100 fn decl_kind(&mut self) -> PResult<DeclKind> {
101 if matches!(self.tok(), Tok::Ident(_)) && self.nth_is(1, Punct::Eq) {
103 return self.prop().map(DeclKind::Prop);
104 }
105 for word in ALL {
106 for role in word.roles {
107 if let Role::Decl { starts, parse } = role
108 && self.starts(word, *starts)
109 {
110 return parse(self);
111 }
112 }
113 }
114 self.member()
115 }
116}