Skip to main content

luaur_ast/methods/
parser_parse.rs

1use crate::records::allocator::Allocator;
2use crate::records::ast_name_table::AstNameTable;
3use crate::records::ast_stat_block::AstStatBlock;
4use crate::records::lexeme::Type;
5use crate::records::parse_error::ParseError;
6use crate::records::parse_options::ParseOptions;
7use crate::records::parse_result::ParseResult;
8use crate::records::parser::Parser;
9use luaur_common::macros::luau_timetrace_scope::LUAU_TIMETRACE_SCOPE;
10use luaur_common::records::dense_hash_map::DenseHashMap;
11
12impl Parser {
13    pub fn parse(
14        buffer: &str,
15        buffer_size: usize,
16        names: &mut AstNameTable,
17        allocator: &mut Allocator,
18        options: ParseOptions,
19    ) -> ParseResult {
20        LUAU_TIMETRACE_SCOPE!("Parser::parse", "Parser");
21
22        // Silence the default panic-hook noise for the parser's exception-
23        // emulation unwinds (a caught `ParseError` is a normal syntax/limit
24        // error, not a crash).
25        crate::functions::install_parse_error_panic_hook::install_parse_error_panic_hook();
26
27        let mut p = Parser::new(buffer, names, allocator as *mut Allocator, options);
28
29        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
30            let root = p.parse_chunk();
31            let current_lexeme = p.lexer.current();
32            let mut line_count = current_lexeme.location.end.line;
33            if buffer_size > 0 && buffer.as_bytes()[buffer_size - 1] != b'\n' {
34                line_count += 1;
35            }
36            let lines = line_count as usize;
37
38            ParseResult {
39                root,
40                lines,
41                hotcomments: std::mem::take(&mut p.hotcomments),
42                errors: std::mem::take(&mut p.parse_errors),
43                comment_locations: std::mem::take(&mut p.comment_locations),
44                cst_node_map: core::mem::replace(
45                    &mut p.cst_node_map,
46                    DenseHashMap::new(core::ptr::null_mut()),
47                ),
48            }
49        }));
50
51        match result {
52            Ok(res) => res,
53            Err(payload) => {
54                if let Some(err) = payload.downcast_ref::<ParseError>() {
55                    p.parse_errors.push(err.clone());
56
57                    ParseResult {
58                        root: core::ptr::null_mut(),
59                        lines: 0,
60                        hotcomments: Vec::new(),
61                        errors: std::mem::take(&mut p.parse_errors),
62                        comment_locations: Vec::new(),
63                        cst_node_map: core::mem::replace(
64                            &mut p.cst_node_map,
65                            DenseHashMap::new(core::ptr::null_mut()),
66                        ),
67                    }
68                } else {
69                    std::panic::resume_unwind(payload);
70                }
71            }
72        }
73    }
74}