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, new, r#ref, r#struct};
9
10impl Parser<'_, '_, '_> {
11 pub fn file(&mut self) -> File {
13 let mut decls = Vec::new();
14 while *self.tok() != Tok::Eof {
15 let at = self.pos;
16 self.decl_into(&mut decls);
17 if self.pos == at {
19 self.bump();
20 }
21 }
22 File { decls }
23 }
24
25 pub(crate) fn body(&mut self) -> PResult<Vec<Decl>> {
27 self.need(Punct::LBrace)?;
28 self.braces(Self::decls_to_brace)
29 }
30
31 pub(crate) fn decls_to_brace(&mut self) -> PResult<Vec<Decl>> {
33 let mut decls = Vec::new();
34 loop {
35 if self.eat(Punct::RBrace) {
36 return Ok(decls);
37 }
38 if *self.tok() == Tok::Eof {
39 return Err(self.expected("`}`"));
40 }
41 self.decl_into(&mut decls);
42 }
43 }
44
45 fn decl_into(&mut self, decls: &mut Vec<Decl>) {
47 match self.decl() {
48 Ok(d) => decls.push(d),
49 Err(_) => self.recover(),
50 }
51 }
52
53 pub(crate) fn decl(&mut self) -> PResult<Decl> {
54 let start = self.span();
55 let mut doc = Vec::new();
56 let mut attributes = Vec::new();
57 loop {
58 match self.tok() {
59 Tok::Doc(line) => {
60 doc.push(line.clone());
61 self.bump();
62 }
63 Tok::Punct(Punct::LBracket) => attributes.extend(self.attributes()?),
64 _ => break,
65 }
66 }
67 let mut modifiers = Vec::new();
68 while let Some(m) = self.modifier_here() {
69 modifiers.push(m);
70 self.bump();
71 }
72 let kind = self.decl_kind()?;
73 Ok(Decl {
74 attributes,
75 doc,
76 modifiers,
77 kind,
78 span: start.to(self.prev()),
79 })
80 }
81
82 fn attributes(&mut self) -> PResult<Vec<Attribute>> {
84 self.need(Punct::LBracket)?;
85 self.list(Punct::RBracket, |p| {
86 let path = p.path("an attribute")?;
87 let args = if p.at(Punct::LParen) {
88 p.args()?
89 } else {
90 Vec::new()
91 };
92 Ok(Attribute { path, args })
93 })
94 }
95
96 fn modifier_here(&self) -> Option<Modifier> {
97 if self.at_word(&r#ref::WORD) && !self.nth_word(1, &r#struct::WORD) {
99 return None;
100 }
101 if self.at_word(&new::WORD)
104 && !self
105 .type_len(1)
106 .is_some_and(|len| matches!(self.nth(1 + len), Tok::Ident(_)))
107 {
108 return None;
109 }
110 ALL.iter().filter(|w| self.at_word(w)).find_map(|w| {
111 w.role(|r| match r {
112 Role::Modifier(m) => Some(*m),
113 _ => None,
114 })
115 })
116 }
117
118 fn decl_kind(&mut self) -> PResult<DeclKind> {
119 if matches!(self.tok(), Tok::Ident(_)) && self.nth_is(1, Punct::Eq) {
121 return self.prop().map(DeclKind::Prop);
122 }
123 for word in ALL {
124 for role in word.roles {
125 if let Role::Decl { starts, parse } = role
126 && self.starts(word, *starts)
127 {
128 return parse(self);
129 }
130 }
131 }
132 self.member()
133 }
134}