luaur_ast/methods/
parser_parse_interp_string.rs1use crate::records::ast_array::AstArray;
2use crate::records::ast_expr::AstExpr;
3use crate::records::ast_expr_interp_string::AstExprInterpString;
4use crate::records::cst_expr_interp_string::CstExprInterpString;
5use crate::records::lexer::Lexer;
6use crate::records::location::Location;
7use crate::records::parser::Parser;
8use crate::records::position::Position;
9use core::ffi::c_char;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl Parser {
13 pub fn parse_interp_string(&mut self) -> *mut AstExpr {
14 let mut strings = crate::records::temp_vector::TempVector::new(&mut self.scratch_string);
15 let mut source_strings =
16 crate::records::temp_vector::TempVector::new(&mut self.scratch_string_2);
17 let mut string_positions =
18 crate::records::temp_vector::TempVector::new(&mut self.scratch_position);
19 let mut expressions = crate::records::temp_vector::TempVector::new(&mut self.scratch_expr);
20
21 let start_location = self.lexer.current().location;
22 let mut end_location = start_location;
23
24 loop {
25 let current_lexeme = *self.lexer.current();
26 LUAU_ASSERT!(
27 current_lexeme.r#type == crate::records::lexeme::Type::InterpStringBegin
28 || current_lexeme.r#type == crate::records::lexeme::Type::InterpStringMid
29 || current_lexeme.r#type == crate::records::lexeme::Type::InterpStringEnd
30 || current_lexeme.r#type == crate::records::lexeme::Type::InterpStringSimple
31 );
32
33 end_location = current_lexeme.location;
34
35 let length = current_lexeme.get_length() as usize;
36 let data_ptr = unsafe { current_lexeme.data.data } as *const c_char;
37 let bytes = unsafe { core::slice::from_raw_parts(data_ptr as *const u8, length) };
38
39 if self.options.store_cst_data {
40 let source_string = self.copy_bytes(bytes);
41 source_strings.push_back(source_string);
42 string_positions.push_back(current_lexeme.location.begin);
43 }
44
45 let mut data = bytes.to_vec();
46 if !Lexer::fixup_quoted_bytes(&mut data) {
47 self.next_lexeme();
48 return self.report_expr_error(
49 Location::new(start_location.begin, end_location.end),
50 AstArray {
51 data: core::ptr::null_mut(),
52 size: 0,
53 },
54 format_args!("Interpolated string literal contains malformed escape sequence"),
55 ) as *mut AstExpr;
56 }
57
58 let chars = self.copy_bytes(&data);
59 self.next_lexeme();
60 strings.push_back(chars);
61
62 if current_lexeme.r#type == crate::records::lexeme::Type::InterpStringEnd
63 || current_lexeme.r#type == crate::records::lexeme::Type::InterpStringSimple
64 {
65 break;
66 }
67
68 let mut error_while_checking = false;
69
70 match self.lexer.current().r#type {
71 crate::records::lexeme::Type::InterpStringMid
72 | crate::records::lexeme::Type::InterpStringEnd => {
73 error_while_checking = true;
74 self.next_lexeme();
75 expressions.push_back(self.report_expr_error(
76 end_location,
77 AstArray {
78 data: core::ptr::null_mut(),
79 size: 0,
80 },
81 format_args!(
82 "Malformed interpolated string, expected expression inside '{{}}'"
83 ),
84 ) as *mut AstExpr);
85 }
86 crate::records::lexeme::Type::BrokenString => {
87 error_while_checking = true;
88 self.next_lexeme();
89 expressions.push_back(self.report_expr_error(
90 end_location,
91 AstArray {
92 data: core::ptr::null_mut(),
93 size: 0,
94 },
95 format_args!("Malformed interpolated string; did you forget to add a '`'?"),
96 ) as *mut AstExpr);
97 }
98 _ => {
99 expressions.push_back(self.parse_expr_i32(0));
100 }
101 }
102
103 if error_while_checking {
104 break;
105 }
106
107 match self.lexer.current().r#type {
108 crate::records::lexeme::Type::InterpStringBegin
109 | crate::records::lexeme::Type::InterpStringMid
110 | crate::records::lexeme::Type::InterpStringEnd => {}
111 crate::records::lexeme::Type::BrokenInterpDoubleBrace => {
112 self.next_lexeme();
113 return self.report_expr_error(
114 end_location,
115 AstArray {
116 data: core::ptr::null_mut(),
117 size: 0,
118 },
119 format_args!("Double braces are not permitted within interpolated strings; did you mean '\\{{'?"),
120 ) as *mut AstExpr;
121 }
122 crate::records::lexeme::Type::BrokenString | crate::records::lexeme::Type::Eof => {
123 if self.lexer.current().r#type == crate::records::lexeme::Type::BrokenString {
124 self.next_lexeme();
125 }
126 let strings_array = self.copy_temp_vector_t(&strings);
127 let expressions_array = self.copy_temp_vector_t(&expressions);
128 let node = unsafe {
129 (*self.allocator).alloc(AstExprInterpString::new(
130 Location::new(start_location.begin, self.lexer.previous_location().end),
131 strings_array,
132 expressions_array,
133 ))
134 };
135
136 if self.options.store_cst_data {
137 let source_strings_array = self.copy_temp_vector_t(&source_strings);
138 let string_positions_array = self.copy_temp_vector_t(&string_positions);
139 let cst_node = unsafe {
140 (*self.allocator).alloc(CstExprInterpString::new(
141 source_strings_array,
142 string_positions_array,
143 ))
144 };
145 self.cst_node_map.try_insert(
146 node as *mut crate::records::ast_node::AstNode,
147 cst_node as *mut crate::records::cst_node::CstNode,
148 );
149 }
150
151 if let Some(top) = self.lexer.peek_brace_stack_top() {
152 if top == crate::enums::brace_type::BraceType::InterpolatedString {
153 self.report_location_c_char_item(
154 *self.lexer.previous_location(),
155 format_args!(
156 "Malformed interpolated string; did you forget to add a '}}'?"
157 ),
158 );
159 }
160 } else {
161 self.report_location_c_char_item(
162 *self.lexer.previous_location(),
163 format_args!(
164 "Malformed interpolated string; did you forget to add a '`'?"
165 ),
166 );
167 }
168
169 return node as *mut AstExpr;
170 }
171 _ => {
172 return self.report_expr_error(
173 end_location,
174 AstArray {
175 data: core::ptr::null_mut(),
176 size: 0,
177 },
178 format_args!(
179 "Malformed interpolated string, got {}",
180 self.lexer.current().to_string()
181 ),
182 ) as *mut AstExpr;
183 }
184 }
185 }
186
187 let strings_array = self.copy_temp_vector_t(&strings);
188 let expressions_array = self.copy_temp_vector_t(&expressions);
189 let node = unsafe {
190 (*self.allocator).alloc(AstExprInterpString::new(
191 Location::new(start_location.begin, end_location.end),
192 strings_array,
193 expressions_array,
194 ))
195 };
196
197 if self.options.store_cst_data {
198 let source_strings_array = self.copy_temp_vector_t(&source_strings);
199 let string_positions_array = self.copy_temp_vector_t(&string_positions);
200 let cst_node = unsafe {
201 (*self.allocator).alloc(CstExprInterpString::new(
202 source_strings_array,
203 string_positions_array,
204 ))
205 };
206 self.cst_node_map.try_insert(
207 node as *mut crate::records::ast_node::AstNode,
208 cst_node as *mut crate::records::cst_node::CstNode,
209 );
210 }
211
212 node as *mut AstExpr
213 }
214}