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, 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 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 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 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}