Skip to main content

luaur_ast/methods/
parser_parser.rs

1use crate::records::allocator::Allocator;
2use crate::records::ast_name::AstName;
3use crate::records::ast_name_table::AstNameTable;
4use crate::records::function::Function;
5use crate::records::lexeme::{Lexeme, Type};
6use crate::records::lexer::Lexer;
7use crate::records::location::Location;
8use crate::records::parse_options::ParseOptions;
9use crate::records::parser::Parser;
10use crate::records::position::Position;
11use luaur_common::macros::luau_assert::LUAU_ASSERT;
12use luaur_common::records::dense_hash_map::DenseHashMap;
13use luaur_common::records::dense_hash_set::DenseHashSet;
14
15// C++ `kParseNameError = "%error-id%"` (ParseResult.h). The port used "(error)".
16const K_PARSE_NAME_ERROR: &str = "%error-id%";
17
18impl Parser {
19    pub fn new(
20        buffer: &str,
21        names: &mut AstNameTable,
22        allocator: *mut Allocator,
23        options: ParseOptions,
24    ) -> Self {
25        let resume_position = options
26            .parse_fragment
27            .as_ref()
28            .map(|f| f.resume_position)
29            .unwrap_or(Position { line: 0, column: 0 });
30
31        let mut parser = Parser {
32            options: options.clone(),
33            lexer: Lexer::new(
34                buffer.as_ptr() as *const core::ffi::c_char,
35                buffer.len(),
36                names,
37                resume_position,
38            ),
39            allocator,
40            comment_locations: alloc::vec::Vec::new(),
41            hotcomments: alloc::vec::Vec::new(),
42            hotcomment_header: true,
43            recursion_counter: 0,
44            name_self: AstName::default(),
45            name_number: AstName::default(),
46            name_error: AstName::default(),
47            name_nil: AstName::default(),
48            end_mismatch_suspect: None,
49            function_stack: alloc::vec::Vec::with_capacity(8),
50            type_function_depth: 0,
51            local_map: DenseHashMap::new(AstName::default()),
52            local_stack: alloc::vec::Vec::with_capacity(16),
53            classes_within_module: DenseHashSet::new(AstName::default()),
54            parse_errors: alloc::vec::Vec::new(),
55            // C++ sizes this `[unsigned(Lexeme::Type::Reserved_END)]`; 256 only
56            // covered char tokens and overflowed on reserved-keyword types
57            // (ReservedEnd=296 indexed into a len-256 vec).
58            match_recovery_stop_on_token: alloc::vec![0; Type::Reserved_END.0 as usize],
59            declared_export_bindings: DenseHashMap::new(AstName::default()),
60            has_module_return: false,
61            scratch_attr: alloc::vec::Vec::new(),
62            scratch_stat: alloc::vec::Vec::with_capacity(16),
63            scratch_string: alloc::vec::Vec::new(),
64            scratch_string_2: alloc::vec::Vec::new(),
65            scratch_expr: alloc::vec::Vec::with_capacity(16),
66            scratch_expr_aux: alloc::vec::Vec::new(),
67            scratch_name: alloc::vec::Vec::new(),
68            scratch_pack_name: alloc::vec::Vec::new(),
69            scratch_binding: alloc::vec::Vec::with_capacity(16),
70            scratch_local: alloc::vec::Vec::with_capacity(16),
71            scratch_table_type_props: alloc::vec::Vec::new(),
72            scratch_cst_table_type_props: alloc::vec::Vec::new(),
73            scratch_type: alloc::vec::Vec::new(),
74            scratch_type_or_pack: alloc::vec::Vec::new(),
75            scratch_declared_class_props: alloc::vec::Vec::new(),
76            scratch_class_declarations: alloc::vec::Vec::new(),
77            scratch_item: alloc::vec::Vec::new(),
78            scratch_cst_item: alloc::vec::Vec::new(),
79            scratch_arg_name: alloc::vec::Vec::new(),
80            scratch_generic_types: alloc::vec::Vec::new(),
81            scratch_generic_type_packs: alloc::vec::Vec::new(),
82            scratch_opt_arg_name: alloc::vec::Vec::new(),
83            scratch_position: alloc::vec::Vec::new(),
84            scratch_position_2: alloc::vec::Vec::new(),
85            scratch_data: alloc::string::String::new(),
86            cst_node_map: DenseHashMap::new(core::ptr::null_mut()),
87        };
88
89        let mut top = Function {
90            vararg: true,
91            loop_depth: 0,
92        };
93        parser.function_stack.push(top);
94
95        parser.name_self = names.get_or_add_c_str(c"self".as_ptr());
96        parser.name_number = names.get_or_add_c_str(c"number".as_ptr());
97        parser.name_error = names.get_or_add_c_str(c"%error-id%".as_ptr());
98        parser.name_nil = names.get_or_add_c_str(c"nil".as_ptr());
99
100        parser.match_recovery_stop_on_token[Type::ReservedEnd.0 as usize] = 0;
101        parser.match_recovery_stop_on_token[Type::Eof.0 as usize] = 1;
102
103        parser.lexer.set_skip_comments(true);
104
105        LUAU_ASSERT!(parser.hotcomment_header);
106        parser.next_lexeme();
107
108        parser.hotcomment_header = false;
109
110        if let Some(fragment) = &options.parse_fragment {
111            parser.local_map = fragment.local_map.clone();
112            parser.local_stack = fragment.local_stack.clone();
113        }
114
115        parser
116    }
117}