Skip to main content

luaur_ast/methods/
parser_parse_attribute_stat.rs

1use crate::enums::type_lexer::Type;
2use crate::records::ast_attr::AstAttr;
3use crate::records::ast_expr::AstExpr;
4use crate::records::ast_name::AstName;
5use crate::records::ast_stat::AstStat;
6use crate::records::ast_stat_error::AstStatError;
7use crate::records::ast_stat_function::AstStatFunction;
8use crate::records::location::Location;
9use crate::records::parser::Parser;
10
11impl Parser {
12    pub fn parse_attribute_stat(&mut self) -> *mut AstStat {
13        let attributes = self.parse_attributes();
14        let current_type = self.lexer.current().r#type;
15
16        match current_type {
17            Type::ReservedFunction => self.parse_function_stat(&attributes) as *mut AstStat,
18            Type::ReservedLocal => {
19                if luaur_common::FFlag::LuauConst2.get() {
20                    let attr_loc = if attributes.size > 0 {
21                        unsafe { (**attributes.data.add(0)).base.location }
22                    } else {
23                        self.lexer.current().location
24                    };
25
26                    self.parse_local(
27                        attr_loc,
28                        self.lexer.current().location.begin,
29                        &attributes,
30                        false,
31                    ) as *mut AstStat
32                } else {
33                    self.parseLocal_DEPRECATED(&attributes) as *mut AstStat
34                }
35            }
36            Type::Name => {
37                let current = self.lexer.current();
38                let current_name = unsafe { current.data.name };
39
40                if luaur_common::FFlag::LuauExportValueSyntax.get()
41                    && luaur_common::FFlag::LuauConst2.get()
42                    && unsafe {
43                        AstName::operator_eq_c_char(
44                            &AstName {
45                                value: current_name,
46                            },
47                            c"export".as_ptr(),
48                        )
49                    }
50                {
51                    let keyword_loc = current.location;
52                    self.next_lexeme();
53
54                    let attr_loc = if attributes.size > 0 {
55                        unsafe { (**attributes.data.add(0)).base.location }
56                    } else {
57                        keyword_loc
58                    };
59
60                    self.parse_export_value(&attr_loc, keyword_loc.begin, &attributes)
61                        as *mut AstStat
62                } else if luaur_common::FFlag::LuauConst2.get()
63                    && unsafe {
64                        AstName::operator_eq_c_char(
65                            &AstName {
66                                value: current_name,
67                            },
68                            c"const".as_ptr(),
69                        )
70                    }
71                {
72                    let keyword_loc = current.location;
73                    self.next_lexeme();
74
75                    let attr_loc = if attributes.size > 0 {
76                        unsafe { (**attributes.data.add(0)).base.location }
77                    } else {
78                        keyword_loc
79                    };
80
81                    self.parse_local(attr_loc, keyword_loc.begin, &attributes, true) as *mut AstStat
82                } else if self.options.allow_declaration_syntax
83                    && unsafe {
84                        AstName::operator_eq_c_char(
85                            &AstName {
86                                value: current_name,
87                            },
88                            c"declare".as_ptr(),
89                        )
90                    }
91                {
92                    let expr = self.parse_primary_expr(true);
93                    self.parse_declaration(&unsafe { (*expr).base.location }, &attributes)
94                        as *mut AstStat
95                } else {
96                    self.parse_attribute_stat_fallthrough_to_error(&attributes) as *mut AstStat
97                }
98            }
99            _ => self.parse_attribute_stat_fallthrough_to_error(&attributes) as *mut AstStat,
100        }
101    }
102
103    fn parse_attribute_stat_fallthrough_to_error(
104        &mut self,
105        _attributes: &crate::records::ast_array::AstArray<*mut AstAttr>,
106    ) -> *mut AstStatError {
107        let current = self.lexer.current();
108        let loc = current.location;
109
110        if luaur_common::FFlag::LuauConst2.get() {
111            self.report_stat_error(
112                loc,
113                crate::records::ast_array::AstArray {
114                    data: core::ptr::null_mut(),
115                    size: 0,
116                },
117                crate::records::ast_array::AstArray {
118                    data: core::ptr::null_mut(),
119                    size: 0,
120                },
121                format_args!(
122                    "Expected 'function', 'local function', 'const function', 'declare function' or a function type declaration after attribute, but got {} instead",
123                    current.to_string()
124                ),
125            )
126        } else {
127            self.report_stat_error(
128                loc,
129                crate::records::ast_array::AstArray {
130                    data: core::ptr::null_mut(),
131                    size: 0,
132                },
133                crate::records::ast_array::AstArray {
134                    data: core::ptr::null_mut(),
135                    size: 0,
136                },
137                format_args!(
138                    "Expected 'function', 'local function', 'declare function' or a function type declaration after attribute, but got {} instead",
139                    current.to_string()
140                ),
141            )
142        }
143    }
144}