Skip to main content

just_engine/parser/
api.rs

1use crate::parser::ast::StatementType::BreakStatement;
2use crate::parser::ast::{
3    AssignmentOperator, AssignmentPropertyData, AstBuilderValidationErrorType, BinaryOperator,
4    BlockStatementData, CatchClauseData, ClassBodyData, ClassData, DeclarationType,
5    ExpressionOrSpreadElement, ExpressionOrSuper, ExpressionPatternType, ExpressionType,
6    ExtendedNumberLiteralType, FormalParameters, ForIteratorData, FunctionBodyData,
7    FunctionBodyOrExpression, FunctionData, HasMeta, IdentifierData, JsError, JsErrorType,
8    LiteralData, LiteralType, LogicalOperator, MemberExpressionType, Meta, MethodDefinitionData,
9    MethodDefinitionKind, NumberLiteralType, PatternOrExpression, PatternType, ProgramData,
10    PropertyData, PropertyKind, StatementType, SwitchCaseData, TemplateElementData,
11    TemplateLiteralData, UnaryOperator, UpdateOperator, VariableDeclarationData,
12    VariableDeclarationKind, VariableDeclarationOrExpression, VariableDeclarationOrPattern,
13    VariableDeclaratorData,
14};
15use crate::parser::static_semantics::Semantics;
16use crate::parser::util::TAB_WIDTH;
17use pest::iterators::{Pair, Pairs};
18use pest::Parser;
19use pest_derive::Parser;
20use std::borrow::Borrow;
21use std::collections::HashMap;
22use std::rc::Rc;
23use std::time::Instant;
24
25/// JavaScript parser using PEG grammar.
26///
27/// Parses ES6 JavaScript source code into an ESTree-compliant AST.
28/// The parser is built on [Pest](https://pest.rs/) and follows the
29/// [ECMAScript 2015 specification](https://262.ecma-international.org/6.0/).
30///
31/// # Examples
32///
33/// ```
34/// use just::parser::JsParser;
35///
36/// let code = "var x = 5 + 3;";
37/// let ast = JsParser::parse_to_ast_from_str(code).unwrap();
38/// assert_eq!(ast.body.len(), 1);
39/// ```
40#[derive(Parser)]
41#[grammar = "parser/js_grammar.pest"] // relative to src
42pub struct JsParser;
43
44type JsRuleError = JsError<Rule>;
45
46fn pair_to_string(pair: Pair<Rule>, level: usize) -> Vec<String> {
47    let mut tree = vec![];
48    let span = pair.as_span();
49    let rule_name = format!(
50        "{:?} => ({},{}) #{:?}",
51        pair.as_rule(),
52        span.start(),
53        span.end(),
54        span.as_str()
55    );
56    let mut string_pads = String::with_capacity(level * TAB_WIDTH);
57    for _ in 1..level * TAB_WIDTH + 1 {
58        string_pads.push('_');
59    }
60    tree.push(format!("{}{}", string_pads, rule_name));
61    for child_pair in pair.into_inner() {
62        tree.append(pair_to_string(child_pair, level + 1).as_mut());
63    }
64    tree
65}
66
67impl JsParser {
68    /// Parse JavaScript source into a debug token tree.
69    ///
70    /// Returns a formatted string representation of the parse tree,
71    /// useful for debugging the parser grammar.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use just::parser::JsParser;
77    ///
78    /// let code = "var x = 5;";
79    /// let tree = JsParser::parse_to_token_tree(code).unwrap();
80    /// assert!(tree.contains("script"));
81    /// ```
82    pub fn parse_to_token_tree(script: &str) -> Result<String, String> {
83        let mut tree = vec![];
84        let start = Instant::now();
85        let result = Self::parse(Rule::script, script);
86        let end = Instant::now();
87        let total_time = end.saturating_duration_since(start);
88        println!("Actual parse time is {}ms", total_time.as_millis());
89
90        match result {
91            Ok(pairs) => {
92                for pair in pairs {
93                    tree.push(pair_to_string(pair, 0).join("\n"));
94                }
95            }
96            Err(err) => {
97                return Err(format!("Parse error due to {:?}", err));
98            }
99        }
100        Ok(tree.join("\n"))
101    }
102
103    /// Parse JavaScript source into an AST.
104    ///
105    /// Takes an `Rc<String>` to allow efficient sharing of the source text
106    /// across AST nodes for error reporting and formatting.
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// use just::parser::JsParser;
112    /// use std::rc::Rc;
113    ///
114    /// let code = Rc::new("var x = 5 + 3;".to_string());
115    /// let ast = JsParser::parse_to_ast(code).unwrap();
116    /// assert_eq!(ast.body.len(), 1);
117    /// ```
118    pub fn parse_to_ast(script: Rc<String>) -> Result<ProgramData, JsRuleError> {
119        let result = Self::parse(Rule::script, &script);
120        match result {
121            Ok(pairs) => build_ast_from_script(pairs, &script),
122            Err(err) => {
123                return Err(JsRuleError {
124                    kind: JsErrorType::ParserValidation(err.clone()),
125                    message: format!("Parse error due to \n{}", err),
126                });
127            }
128        }
129    }
130
131    /// Parse JavaScript source string into an AST.
132    ///
133    /// Convenience method that wraps the source in an `Rc<String>`.
134    /// This is the most commonly used parsing method.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use just::parser::JsParser;
140    ///
141    /// let code = "function add(a, b) { return a + b; }";
142    /// let ast = JsParser::parse_to_ast_from_str(code).unwrap();
143    /// assert_eq!(ast.body.len(), 1);
144    /// ```
145    pub fn parse_to_ast_from_str(script: &str) -> Result<ProgramData, JsRuleError> {
146        Self::parse_to_ast(Rc::new(script.to_string()))
147    }
148
149    /// Parse JavaScript and return a formatted AST string.
150    ///
151    /// Useful for debugging and visualizing the AST structure.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// use just::parser::JsParser;
157    ///
158    /// let code = "var x = 5;";
159    /// let formatted = JsParser::parse_to_ast_formatted_string(code).unwrap();
160    /// assert!(formatted.contains("VariableDeclaration"));
161    /// ```
162    pub fn parse_to_ast_formatted_string(script: &str) -> Result<String, JsRuleError> {
163        let result = Self::parse_to_ast_from_str(script)?;
164        Ok(result.to_formatted_string(script))
165    }
166
167    /// Parse a numeric literal string.
168    ///
169    /// Supports decimal, hexadecimal (0x), binary (0b), octal (0o),
170    /// floating point, and scientific notation.
171    ///
172    /// # Arguments
173    ///
174    /// * `s` - The numeric string to parse
175    /// * `is_error_on_empty` - Whether to return an error on empty string
176    ///
177    /// # Examples
178    ///
179    /// ```
180    /// use just::parser::JsParser;
181    ///
182    /// let hex = "0xFF".to_string();
183    /// let result = JsParser::parse_numeric_string(&hex, true).unwrap();
184    /// ```
185    pub fn parse_numeric_string(
186        s: &String,
187        is_error_on_empty: bool,
188    ) -> Result<ExtendedNumberLiteralType, JsRuleError> {
189        let result = Self::parse(Rule::string_numeric_literal, s);
190        Ok(match result {
191            Ok(mut pairs) => {
192                if let Some(pair) = pairs.next() {
193                    match pair.as_rule() {
194                        Rule::str_numeric_literal => build_ast_from_str_numeric_literal(pair)?,
195                        _ => return Err(get_unexpected_error("parse_numeric_string", &pair)),
196                    }
197                } else {
198                    if is_error_on_empty {
199                        return Err(JsRuleError {
200                            kind: JsErrorType::ParserGeneralError,
201                            message: "Got empty string".to_string(),
202                        });
203                    } else {
204                        ExtendedNumberLiteralType::Std(NumberLiteralType::IntegerLiteral(0))
205                    }
206                }
207            }
208            Err(err) => {
209                return Err(JsRuleError {
210                    kind: JsErrorType::ParserValidation(err.clone()),
211                    message: format!("Parse error due to \n{}", err),
212                });
213            }
214        })
215    }
216}
217
218fn get_unexpected_error(src: &'static str, pair: &Pair<Rule>) -> JsRuleError {
219    get_unexpected_error_with_rule(src, &pair.as_rule())
220}
221
222fn get_unexpected_error_with_rule(src: &'static str, rule: &Rule) -> JsRuleError {
223    let message = format!("Unexpected state reached in the parser at \"{:?}\". This indicates internal logic error in the parser.", rule);
224    JsRuleError {
225        message,
226        kind: JsErrorType::Unexpected(src),
227    }
228}
229
230fn get_validation_error(
231    error: String,
232    kind: AstBuilderValidationErrorType,
233    pair: &Pair<Rule>,
234    script: &Rc<String>,
235) -> JsRuleError {
236    get_validation_error_with_meta(error, kind, get_meta(pair, script))
237}
238
239fn get_validation_error_with_meta(
240    error: String,
241    kind: AstBuilderValidationErrorType,
242    meta: Meta,
243) -> JsRuleError {
244    let message = format!("Parsing error encountered: {}", error);
245    JsRuleError {
246        message,
247        kind: JsErrorType::AstBuilderValidation(kind, meta),
248    }
249}
250
251fn get_meta(pair: &Pair<Rule>, script: &Rc<String>) -> Meta {
252    Meta {
253        start_index: pair.as_span().start(),
254        end_index: pair.as_span().end(),
255        script: script.clone(),
256    }
257}
258
259/// Helper to safely get the first inner pair with proper error handling.
260/// Use this instead of `.into_inner().next().unwrap()` for safer error propagation.
261fn expect_inner<'a>(
262    pair: Pair<'a, Rule>,
263    context: &str,
264    script: &Rc<String>,
265) -> Result<Pair<'a, Rule>, JsRuleError> {
266    let meta = get_meta(&pair, script);
267    pair.into_inner().next().ok_or_else(|| {
268        get_validation_error_with_meta(
269            format!("Expected inner token in {}", context),
270            AstBuilderValidationErrorType::SyntaxError,
271            meta,
272        )
273    })
274}
275
276fn build_ast_from_script(
277    pairs: Pairs<Rule>,
278    script: &Rc<String>,
279) -> Result<ProgramData, JsRuleError> {
280    let mut instructions = vec![];
281    let mut end: usize = 0;
282    for pair in pairs {
283        let meta = get_meta(&pair, script);
284        if meta.end_index > end {
285            end = meta.end_index;
286        }
287        match pair.as_rule() {
288            Rule::EOI => { /* Do nothing */ }
289            Rule::statement_list => {
290                // There should be only one pair and it should be statement_list (except EOI)
291                let (sl, sl_s) = build_ast_from_statement_list(pair, script)?;
292                if sl_s.contains_unpaired_continue.is_true() {
293                    return Err(get_validation_error_with_meta(
294                        "Invalid 'continue' statement".to_string(),
295                        AstBuilderValidationErrorType::SyntaxError,
296                        meta,
297                    ));
298                }
299                if sl_s.contains_unpaired_break.is_true() {
300                    return Err(get_validation_error_with_meta(
301                        "Invalid 'break' statement".to_string(),
302                        AstBuilderValidationErrorType::SyntaxError,
303                        meta,
304                    ));
305                }
306                validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(&sl_s)?;
307                //sl_s.top_level_lexically_declared_names should be lexically_declared_names for this production
308                //sl_s.top_level_var_declared_names should be var_declared_names for this production
309                instructions = sl;
310            }
311            _ => return Err(get_unexpected_error("build_ast_from_script", &pair)),
312        };
313    }
314    Ok(ProgramData {
315        meta: Meta {
316            start_index: 0,
317            end_index: end,
318            script: script.clone(),
319        },
320        body: instructions,
321    })
322}
323
324fn build_ast_from_declaration(
325    pair: Pair<Rule>,
326    script: &Rc<String>,
327) -> Result<(DeclarationType, Semantics), JsRuleError> {
328    let inner_pair = expect_inner(pair, "build_ast_from_declaration", script)?;
329    Ok(match inner_pair.as_rule() {
330        Rule::hoistable_declaration | Rule::hoistable_declaration__yield => {
331            let (h, _h_s) = build_ast_from_hoistable_declaration(inner_pair, script)?;
332            (h, Semantics::new_empty()) // empty top_level_lexically_declared_names
333        }
334        Rule::class_declaration | Rule::class_declaration__yield => {
335            let (c, c_s) = build_ast_from_class_declaration(inner_pair, script)?;
336            let mut s = Semantics::new_empty();
337            s.top_level_lexically_declared_names = c_s.bound_names;
338            (DeclarationType::ClassDeclaration(c), s)
339        }
340        Rule::lexical_declaration__in | Rule::lexical_declaration__in_yield => {
341            let (ld, ld_s) = build_ast_from_lexical_declaration(inner_pair, script)?;
342            let mut s = Semantics::new_empty();
343            s.top_level_lexically_declared_names = ld_s.bound_names;
344            (DeclarationType::VariableDeclaration(ld), s)
345        }
346        _ => {
347            return Err(get_unexpected_error(
348                "build_ast_from_declaration",
349                &inner_pair,
350            ))
351        }
352    })
353}
354
355fn build_ast_from_lexical_declaration(
356    pair: Pair<Rule>,
357    script: &Rc<String>,
358) -> Result<(VariableDeclarationData, Semantics), JsRuleError> {
359    let meta = get_meta(&pair, script);
360    let mut s = Semantics::new_empty();
361    let mut declarations = vec![];
362    let mut inner_iter = pair.into_inner();
363    let let_or_const_pair = inner_iter.next().unwrap();
364    let is_let = let_or_const_pair.as_str() == "let";
365    let binding_list_pair = inner_iter.next().unwrap();
366    for lexical_binding_pair in binding_list_pair.into_inner() {
367        let lexical_binding_meta = get_meta(&lexical_binding_pair, script);
368        let (l, l_s) = build_ast_from_lexical_binding_or_variable_declaration_or_binding_element(
369            lexical_binding_pair,
370            script,
371        )?;
372        if !is_let {
373            // init is mandatory when it is constant declaration assigning to binding_identifier
374            if let PatternType::PatternWhichCanBeExpression(ExpressionPatternType::Identifier(id)) =
375                l.id.borrow()
376            {
377                if l.init.is_none() {
378                    return Err(get_validation_error_with_meta(
379                        format!(
380                            "Initializer not provided for constant declaration: {}",
381                            id.name
382                        ),
383                        AstBuilderValidationErrorType::SyntaxError,
384                        lexical_binding_meta,
385                    ));
386                }
387            }
388        }
389        s.merge(l_s);
390        declarations.push(l);
391    }
392    // Look for duplicates in BoundNames
393    let mut found = HashMap::new();
394    for n in &s.bound_names {
395        if n.name == "let" {
396            return Err(get_validation_error_with_meta(
397                format!("Illegal name found: {}", n),
398                AstBuilderValidationErrorType::SyntaxError,
399                n.meta.clone(),
400            ));
401        } else if found.contains_key(&n.name) {
402            return Err(get_validation_error_with_meta(
403                format!("Duplicate declaration found: {}", n),
404                AstBuilderValidationErrorType::SyntaxError,
405                n.meta.clone(),
406            ));
407        } else {
408            found.insert(n.name.clone(), true);
409        }
410    }
411    Ok((
412        VariableDeclarationData {
413            meta,
414            declarations,
415            kind: if is_let {
416                VariableDeclarationKind::Let
417            } else {
418                VariableDeclarationKind::Const
419            },
420        },
421        s,
422    ))
423}
424
425fn build_ast_from_hoistable_declaration(
426    pair: Pair<Rule>,
427    script: &Rc<String>,
428) -> Result<(DeclarationType, Semantics), JsRuleError> {
429    let inner_pair = pair.into_inner().next().unwrap();
430    Ok(match inner_pair.as_rule() {
431        Rule::generator_declaration | Rule::generator_declaration__yield => {
432            let (f, s) =
433                build_ast_from_generator_declaration_or_generator_expression(inner_pair, script)?;
434            (DeclarationType::FunctionOrGeneratorDeclaration(f), s)
435        }
436        Rule::function_declaration | Rule::function_declaration__yield => {
437            let (f, s) =
438                build_ast_from_function_declaration_or_function_expression(inner_pair, script)?;
439            (DeclarationType::FunctionOrGeneratorDeclaration(f), s)
440        }
441        _ => {
442            return Err(get_unexpected_error(
443                "build_ast_from_hoistable_declaration",
444                &inner_pair,
445            ))
446        }
447    })
448}
449
450fn build_ast_from_generator_declaration_or_generator_expression(
451    pair: Pair<Rule>,
452    script: &Rc<String>,
453) -> Result<(FunctionData, Semantics), JsRuleError> {
454    let is_generator_declaration = match pair.as_rule() {
455        Rule::generator_declaration | Rule::generator_declaration__yield => true,
456        _ => false,
457    };
458    let meta = get_meta(&pair, script);
459    let mut pair_iter = pair.into_inner();
460    let first_pair = pair_iter.next().unwrap();
461    let (f_name, mut s, formal_parameters_pair) =
462        if first_pair.as_rule() == Rule::binding_identifier {
463            let (bi, mut bi_s) = get_binding_identifier_data(first_pair, script)?;
464            if !is_generator_declaration {
465                // In case of generator_expression we ignore the binding_identifier
466                bi_s.bound_names = vec![];
467            }
468            (Some(bi), bi_s, pair_iter.next().unwrap())
469        } else {
470            (None, Semantics::new_empty(), first_pair)
471        };
472    let (args, args_s) = build_ast_from_formal_parameters(formal_parameters_pair, script)?;
473    if args_s.contains_yield_expression.is_true() {
474        return Err(get_validation_error_with_meta(
475            "Cannot reference 'yield' in parameters".to_string(),
476            AstBuilderValidationErrorType::SyntaxError,
477            meta.clone(),
478        ));
479    }
480    if args_s.contains_super_property.is_true() {
481        return Err(get_validation_error_with_meta(
482            "Cannot invoke 'super'".to_string(),
483            AstBuilderValidationErrorType::SyntaxError,
484            meta.clone(),
485        ));
486    }
487    // We first have generator_body then function_body__yield in it
488    let function_body_pair = pair_iter.next().unwrap().into_inner().next().unwrap();
489    let (f_body, f_body_s) = build_ast_from_function_body(function_body_pair, script)?;
490    if f_body_s.contains_super_property.is_true() {
491        return Err(get_validation_error_with_meta(
492            "Cannot invoke 'super'".to_string(),
493            AstBuilderValidationErrorType::SyntaxError,
494            meta.clone(),
495        ));
496    }
497    if f_body_s.has_direct_super.is_true() {
498        return Err(get_validation_error_with_meta(
499            "Invalid reference to 'super'".to_string(),
500            AstBuilderValidationErrorType::SyntaxError,
501            meta.clone(),
502        ));
503    }
504    validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&args_s.bound_names, &vec![], &f_body_s.lexically_declared_names)?;
505    let body = Box::new(f_body);
506    s.merge(args_s);
507    // .merge(f_body_s); bound_names from f_body_s are not returned
508    Ok((
509        FunctionData {
510            meta,
511            id: f_name,
512            body,
513            params: FormalParameters::new(args),
514            generator: true,
515        },
516        s,
517    ))
518}
519
520fn build_ast_from_function_declaration_or_function_expression(
521    pair: Pair<Rule>,
522    script: &Rc<String>,
523) -> Result<(FunctionData, Semantics), JsRuleError> {
524    let is_function_declaration = match pair.as_rule() {
525        Rule::function_declaration | Rule::function_declaration__yield => true,
526        _ => false,
527    };
528    let meta = get_meta(&pair, script);
529    let mut pair_iter = pair.into_inner();
530    let first_pair = pair_iter.next().unwrap();
531    let (f_name, mut s, formal_parameters_pair) =
532        if first_pair.as_rule() == Rule::binding_identifier {
533            let (bi, mut bi_s) = get_binding_identifier_data(first_pair, script)?;
534            if !is_function_declaration {
535                // In case of function_expression we ignore the binding_identifier
536                bi_s.bound_names = vec![];
537            }
538            (Some(bi), bi_s, pair_iter.next().unwrap())
539        } else {
540            (None, Semantics::new_empty(), first_pair)
541        };
542    let formal_parameters_meta = get_meta(&formal_parameters_pair, script);
543    let (args, args_s) = build_ast_from_formal_parameters(formal_parameters_pair, script)?;
544    if args_s.contains_super_call.is_true() || args_s.contains_super_property.is_true() {
545        return Err(get_validation_error_with_meta(
546            "Cannot invoke 'super'".to_string(),
547            AstBuilderValidationErrorType::SyntaxError,
548            formal_parameters_meta,
549        ));
550    }
551    let function_body_pair = pair_iter.next().unwrap();
552    let function_body_meta = get_meta(&function_body_pair, script);
553    let (f_body, f_body_s) = build_ast_from_function_body(function_body_pair, script)?;
554    if f_body_s.contains_super_call.is_true() || f_body_s.contains_super_property.is_true() {
555        return Err(get_validation_error_with_meta(
556            "Cannot invoke 'super'".to_string(),
557            AstBuilderValidationErrorType::SyntaxError,
558            function_body_meta,
559        ));
560    }
561    validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&args_s.bound_names, &vec![], &f_body_s.lexically_declared_names,)?;
562    let body = Box::new(f_body);
563    s.merge(args_s);
564    // .merge(f_body_s); bound_names from f_body_s are not returned
565    Ok((
566        FunctionData {
567            meta,
568            id: f_name,
569            body,
570            params: FormalParameters::new(args),
571            generator: false,
572        },
573        s,
574    ))
575}
576
577fn build_ast_from_formal_parameters(
578    pair: Pair<Rule>,
579    script: &Rc<String>,
580) -> Result<(Vec<PatternType>, Semantics), JsRuleError> {
581    let mut args: Vec<PatternType> = vec![];
582    let mut s = Semantics::new_empty();
583    for param in pair.into_inner() {
584        let meta = get_meta(&param, script);
585        args.push(match param.as_rule() {
586            Rule::function_rest_parameter | Rule::function_rest_parameter__yield => {
587                let binding_rest_element = param.into_inner().next().unwrap();
588                let binding_identifier_item = binding_rest_element.into_inner().next().unwrap();
589                let (binding_identifier, binding_identifier_s) =
590                    get_binding_identifier_data(binding_identifier_item, script)?;
591                s.merge(binding_identifier_s);
592                PatternType::RestElement {
593                    meta,
594                    argument: Box::new(
595                        ExpressionPatternType::Identifier(binding_identifier).convert_to_pattern(),
596                    ),
597                }
598            }
599            Rule::formal_parameter | Rule::formal_parameter__yield => {
600                // formal_parameter contains binding_element
601                let binding_element = param.into_inner().next().unwrap();
602                let (pattern, pattern_s) = build_ast_from_binding_element(binding_element, script)?;
603                s.merge(pattern_s);
604                pattern
605            }
606            _ => {
607                return Err(get_unexpected_error(
608                    "build_ast_from_formal_parameters",
609                    &param,
610                ))
611            }
612        });
613    }
614    Ok((args, s))
615}
616
617/// Build AST from a single formal parameter (used for setter property_set_parameter_list).
618fn build_ast_from_single_formal_parameter(
619    pair: Pair<Rule>,
620    script: &Rc<String>,
621) -> Result<(Vec<PatternType>, Semantics), JsRuleError> {
622    let mut args: Vec<PatternType> = vec![];
623    let mut s = Semantics::new_empty();
624
625    match pair.as_rule() {
626        Rule::formal_parameter | Rule::formal_parameter__yield => {
627            // formal_parameter contains binding_element
628            let binding_element = pair.into_inner().next().unwrap();
629            let (pattern, pattern_s) = build_ast_from_binding_element(binding_element, script)?;
630            s.merge(pattern_s);
631            args.push(pattern);
632        }
633        _ => {
634            return Err(get_unexpected_error(
635                "build_ast_from_single_formal_parameter",
636                &pair,
637            ))
638        }
639    }
640    Ok((args, s))
641}
642
643fn build_ast_from_generator_body(
644    pair: Pair<Rule>,
645    script: &Rc<String>,
646) -> Result<(FunctionBodyData, Semantics), JsRuleError> {
647    build_ast_from_function_body(pair.into_inner().next().unwrap(), script)
648}
649
650fn build_ast_from_function_body(
651    pair: Pair<Rule>,
652    script: &Rc<String>,
653) -> Result<(FunctionBodyData, Semantics), JsRuleError> {
654    let meta = get_meta(&pair, script);
655    let statement_list_pair = pair.into_inner().next().unwrap();
656    let statement_list_meta = get_meta(&statement_list_pair, script);
657    let (statements, statements_s) = build_ast_from_statement_list(statement_list_pair, script)?;
658    if statements_s.contains_unpaired_continue.is_true() {
659        return Err(get_validation_error_with_meta(
660            "Invalid 'continue' statement".to_string(),
661            AstBuilderValidationErrorType::SyntaxError,
662            statement_list_meta,
663        ));
664    }
665    if statements_s.contains_unpaired_break.is_true() {
666        return Err(get_validation_error_with_meta(
667            "Invalid 'break' statement".to_string(),
668            AstBuilderValidationErrorType::SyntaxError,
669            statement_list_meta,
670        ));
671    }
672    validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(&statements_s)?;
673    let mut s = Semantics::new_empty();
674    s.lexically_declared_names = statements_s.top_level_lexically_declared_names;
675    s.var_declared_names = statements_s.top_level_var_declared_names;
676    Ok((
677        FunctionBodyData {
678            meta,
679            body: statements,
680        },
681        s,
682    ))
683}
684
685fn build_ast_from_statement(
686    pair: Pair<Rule>,
687    script: &Rc<String>,
688) -> Result<(StatementType, Semantics), JsRuleError> {
689    let inner_pair = pair.into_inner().next().unwrap();
690    let meta = get_meta(&inner_pair, script);
691    Ok(match inner_pair.as_rule() {
692        Rule::debugger_statement => unimplemented!(),
693        Rule::continue_statement | Rule::continue_statement__yield => {
694            let (c, _) = build_ast_from_continue_statement(inner_pair, script)?;
695            (c, Semantics::new_empty())
696        }
697        Rule::break_statement | Rule::break_statement__yield => {
698            (BreakStatement { meta }, Semantics::new_empty())
699        }
700        Rule::throw_statement | Rule::throw_statement__yield => {
701            let (t, _) = build_ast_from_throw_statement(inner_pair, script)?;
702            (t, Semantics::new_empty())
703        }
704        Rule::if_statement
705        | Rule::if_statement__yield
706        | Rule::if_statement__return
707        | Rule::if_statement__yield_return => build_ast_from_if_statement(inner_pair, script)?,
708        Rule::with_statement
709        | Rule::with_statement__yield
710        | Rule::with_statement__return
711        | Rule::with_statement__yield_return => unimplemented!(),
712        Rule::try_statement
713        | Rule::try_statement__yield
714        | Rule::try_statement__return
715        | Rule::try_statement__yield_return => build_ast_from_try_statement(inner_pair, script)?,
716        Rule::variable_statement | Rule::variable_statement__yield => {
717            build_ast_from_variable_statement(inner_pair, script)?
718        }
719        Rule::breakable_statement
720        | Rule::breakable_statement__yield
721        | Rule::breakable_statement__return
722        | Rule::breakable_statement__yield_return => {
723            build_ast_from_breakable_statement(inner_pair, script)?
724        }
725        Rule::block_statement
726        | Rule::block_statement__yield
727        | Rule::block_statement__return
728        | Rule::block_statement__yield_return => {
729            let (bsd, bsd_s) =
730                build_ast_from_block(inner_pair.into_inner().next().unwrap(), script)?;
731            (StatementType::BlockStatement(bsd), bsd_s)
732        }
733        Rule::expression_statement | Rule::expression_statement__yield => {
734            let (exp, _exp_s) =
735                build_ast_from_expression(inner_pair.into_inner().next().unwrap(), script)?;
736            (
737                StatementType::ExpressionStatement {
738                    meta,
739                    expression: Box::new(exp),
740                },
741                Semantics::new_empty(),
742            )
743        }
744        Rule::empty_statement => (
745            StatementType::EmptyStatement { meta },
746            Semantics::new_empty(),
747        ),
748        Rule::return_statement | Rule::return_statement__yield => {
749            let (r, _) = build_ast_from_return_statement(inner_pair, script)?;
750            (r, Semantics::new_empty())
751        }
752        _ => {
753            return Err(get_unexpected_error(
754                "build_ast_from_statement",
755                &inner_pair,
756            ))
757        }
758    })
759}
760
761fn build_ast_from_if_statement(
762    pair: Pair<Rule>,
763    script: &Rc<String>,
764) -> Result<(StatementType, Semantics), JsRuleError> {
765    let meta = get_meta(&pair, script);
766    let mut inner_iter = pair.into_inner();
767    let expression_pair = inner_iter.next().unwrap();
768    let (expression, _) = build_ast_from_expression(expression_pair, script)?;
769    let mut s = Semantics::new_empty();
770    let (statement_true, statement_true_s) =
771        build_ast_from_statement(inner_iter.next().unwrap(), script)?;
772    s.var_declared_names = statement_true_s.var_declared_names;
773    let (statement_else, _statement_else_s) = if let Some(statement_else_pair) = inner_iter.next() {
774        let (st, mut st_s) = build_ast_from_statement(statement_else_pair, script)?;
775        s.var_declared_names.append(&mut st_s.var_declared_names);
776        (Some(Box::new(st)), st_s)
777    } else {
778        (None, Semantics::new_empty())
779    };
780    Ok((
781        StatementType::IfStatement {
782            meta,
783            test: Box::new(expression),
784            consequent: Box::new(statement_true),
785            alternate: statement_else,
786        },
787        s,
788    ))
789}
790
791fn build_ast_from_throw_statement(
792    pair: Pair<Rule>,
793    script: &Rc<String>,
794) -> Result<(StatementType, Semantics), JsRuleError> {
795    let meta = get_meta(&pair, script);
796    let inner_pair = pair.into_inner().next().unwrap();
797    let (e, e_s) = build_ast_from_expression(inner_pair, script)?;
798    Ok((
799        StatementType::ThrowStatement {
800            meta,
801            argument: Box::new(e),
802        },
803        e_s,
804    ))
805}
806
807fn build_ast_from_continue_statement(
808    pair: Pair<Rule>,
809    script: &Rc<String>,
810) -> Result<(StatementType, Semantics), JsRuleError> {
811    let mut s = Semantics::new_empty();
812    s.contains_unpaired_continue.make_true();
813    Ok((
814        StatementType::ContinueStatement {
815            meta: get_meta(&pair, script),
816        },
817        s,
818    ))
819}
820
821fn build_ast_from_statement_list(
822    pair: Pair<Rule>,
823    script: &Rc<String>,
824) -> Result<(Vec<StatementType>, Semantics), JsRuleError> {
825    let _meta = get_meta(&pair, script);
826    let mut declarations = vec![];
827    let mut s = Semantics::new_empty();
828    for inner_pair in pair.into_inner() {
829        declarations.push(match inner_pair.as_rule() {
830            Rule::declaration | Rule::declaration__yield => {
831                let (d, mut d_s) = build_ast_from_declaration(inner_pair, script)?;
832                s.lexically_declared_names.append(&mut d_s.bound_names);
833                StatementType::DeclarationStatement(d)
834            }
835            Rule::statement
836            | Rule::statement__yield
837            | Rule::statement__return
838            | Rule::statement__yield_return => {
839                let (st, st_s) = build_ast_from_statement(inner_pair, script)?;
840                s.merge(st_s);
841                st
842            }
843            _ => {
844                return Err(get_unexpected_error(
845                    "build_ast_from_statement_list",
846                    &inner_pair,
847                ))
848            }
849        });
850    }
851    Ok((declarations, s))
852}
853
854fn validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(
855    s: &Semantics,
856) -> Result<(), JsRuleError> {
857    // Look for duplicates in LexicallyDeclaredNames
858    let mut found = HashMap::new();
859    for n in &s.lexically_declared_names {
860        if found.contains_key(&n.name) || s.var_declared_names.contains(n) {
861            return Err(get_validation_error_with_meta(
862                format!("Duplicate declaration found: {}", n),
863                AstBuilderValidationErrorType::SyntaxError,
864                n.meta.clone(),
865            ));
866        } else {
867            found.insert(n.name.clone(), true);
868        }
869    }
870    Ok(())
871}
872
873fn validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(
874    bound_names: &Vec<IdentifierData>,
875    var_declared_names: &Vec<IdentifierData>,
876    lexically_declared_names: &Vec<IdentifierData>,
877) -> Result<(), JsRuleError> {
878    // Look for duplicates in LexicallyDeclaredNames
879    let mut found = HashMap::new();
880    for n in bound_names {
881        if found.contains_key(&n.name)
882            || var_declared_names.contains(n)
883            || lexically_declared_names.contains(n)
884        {
885            return Err(get_validation_error_with_meta(
886                format!("Duplicate declaration found: {}", n),
887                AstBuilderValidationErrorType::SyntaxError,
888                n.meta.clone(),
889            ));
890        } else {
891            found.insert(n.name.clone(), true);
892        }
893    }
894    Ok(())
895}
896
897fn build_ast_from_block(
898    pair: Pair<Rule>,
899    script: &Rc<String>,
900) -> Result<(BlockStatementData, Semantics), JsRuleError> {
901    let meta = get_meta(&pair, script);
902    let (declarations, s) = if let Some(inner_pair) = pair.into_inner().next() {
903        build_ast_from_statement_list(inner_pair, script)?
904    } else {
905        (vec![], Semantics::new_empty())
906    };
907    validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(&s)?;
908    Ok((
909        BlockStatementData {
910            meta,
911            body: declarations,
912        },
913        s,
914    ))
915}
916
917fn build_ast_from_breakable_statement(
918    pair: Pair<Rule>,
919    script: &Rc<String>,
920) -> Result<(StatementType, Semantics), JsRuleError> {
921    let inner_pair = pair.into_inner().next().unwrap();
922    Ok(
923        if inner_pair.as_rule() == Rule::iteration_statement
924            || inner_pair.as_rule() == Rule::iteration_statement__yield
925            || inner_pair.as_rule() == Rule::iteration_statement__return
926            || inner_pair.as_rule() == Rule::iteration_statement__yield_return
927        {
928            build_ast_from_iteration_statement(inner_pair, script)?
929        } else {
930            build_ast_from_switch_statement(inner_pair, script)?
931        },
932    )
933}
934
935fn build_ast_from_iteration_statement(
936    pair: Pair<Rule>,
937    script: &Rc<String>,
938) -> Result<(StatementType, Semantics), JsRuleError> {
939    let tag = pair.as_str().splitn(2, ' ').next().unwrap();
940    Ok(match tag {
941        "do" => build_ast_for_breakable_statement_do(pair, script)?,
942        "while" => build_ast_for_breakable_statement_while(pair, script)?,
943        "for" => build_ast_for_breakable_statement_for(pair, script)?,
944        _ => {
945            return Err(get_unexpected_error(
946                "build_ast_from_iteration_statement",
947                &pair,
948            ))
949        }
950    })
951}
952
953fn build_ast_for_breakable_statement_do(
954    pair: Pair<Rule>,
955    script: &Rc<String>,
956) -> Result<(StatementType, Semantics), JsRuleError> {
957    let meta = get_meta(&pair, script);
958    let mut inner_iter = pair.into_inner();
959    let statement_pair = inner_iter.next().unwrap();
960    let test_expression_pair = inner_iter.next().unwrap();
961    let mut s = Semantics::new_empty();
962    let (e, _) = build_ast_from_expression(test_expression_pair, script)?;
963    let (st, st_s) = build_ast_from_statement(statement_pair, script)?;
964    s.var_declared_names = st_s.var_declared_names;
965    Ok((
966        StatementType::DoWhileStatement {
967            meta,
968            test: Box::new(e),
969            body: Box::new(st),
970        },
971        s,
972    ))
973}
974
975fn build_ast_for_breakable_statement_while(
976    pair: Pair<Rule>,
977    script: &Rc<String>,
978) -> Result<(StatementType, Semantics), JsRuleError> {
979    let meta = get_meta(&pair, script);
980    let mut inner_iter = pair.into_inner();
981    let test_expression_pair = inner_iter.next().unwrap();
982    let statement_pair = inner_iter.next().unwrap();
983    let mut s = Semantics::new_empty();
984    let (e, _) = build_ast_from_expression(test_expression_pair, script)?;
985    let (st, st_s) = build_ast_from_statement(statement_pair, script)?;
986    s.var_declared_names = st_s.var_declared_names;
987    Ok((
988        StatementType::WhileStatement {
989            meta,
990            test: Box::new(e),
991            body: Box::new(st),
992        },
993        s,
994    ))
995}
996
997fn build_ast_for_breakable_statement_for(
998    pair: Pair<Rule>,
999    script: &Rc<String>,
1000) -> Result<(StatementType, Semantics), JsRuleError> {
1001    let meta = get_meta(&pair, script);
1002    let mut inner_iter = pair.into_inner();
1003    let first_pair = inner_iter.next().unwrap();
1004    let mut s = Semantics::new_empty();
1005    Ok(match first_pair.as_rule() {
1006        Rule::left_hand_side_expression
1007        | Rule::left_hand_side_expression__yield
1008        | Rule::for_binding
1009        | Rule::for_binding__yield
1010        | Rule::for_declaration
1011        | Rule::for_declaration__yield => {
1012            /* for-in or for-of */
1013            let in_of_left = match first_pair.as_rule() {
1014                Rule::left_hand_side_expression | Rule::left_hand_side_expression__yield => {
1015                    let (exp, exp_s) =
1016                        build_ast_from_left_hand_side_expression(first_pair, script)?;
1017                    let m = Box::new(convert_lhs_expression_to_pattern_for_assignment_operation(
1018                        exp,
1019                        Some(&exp_s),
1020                    )?);
1021                    VariableDeclarationOrPattern::Pattern(m)
1022                }
1023                Rule::for_binding | Rule::for_binding__yield => {
1024                    let meta = get_meta(&first_pair, script);
1025                    let meta2 = meta.clone();
1026                    let (b, mut b_s) = build_ast_from_for_binding(first_pair, script)?;
1027                    s.var_declared_names.append(&mut b_s.bound_names);
1028
1029                    VariableDeclarationOrPattern::VariableDeclaration(VariableDeclarationData {
1030                        meta,
1031                        declarations: vec![VariableDeclaratorData {
1032                            meta: meta2,
1033                            id: Box::new(b),
1034                            init: None,
1035                        }],
1036                        kind: VariableDeclarationKind::Var,
1037                    })
1038                }
1039                Rule::for_declaration | Rule::for_declaration__yield => {
1040                    let (d, d_s) = build_ast_from_for_declaration(first_pair, script)?;
1041                    let mut found = HashMap::new();
1042                    for bn in &d_s.bound_names {
1043                        if bn.name == "let" {
1044                            return Err(get_validation_error_with_meta(
1045                                "Illegal name: let".to_string(),
1046                                AstBuilderValidationErrorType::SyntaxError,
1047                                bn.meta.clone(),
1048                            ));
1049                        } else if found.contains_key(&bn.name) {
1050                            return Err(get_validation_error_with_meta(
1051                                format!("Duplicate declaration present: {}", bn),
1052                                AstBuilderValidationErrorType::SyntaxError,
1053                                bn.meta.clone(),
1054                            ));
1055                        } else if d_s.var_declared_names.contains(bn) {
1056                            return Err(get_validation_error_with_meta(
1057                                format!("Duplicate declaration present: {}", bn),
1058                                AstBuilderValidationErrorType::SyntaxError,
1059                                bn.meta.clone(),
1060                            ));
1061                        }
1062                        found.insert(bn.name.clone(), true);
1063                    }
1064                    VariableDeclarationOrPattern::VariableDeclaration(d)
1065                }
1066                _ => {
1067                    return Err(get_unexpected_error(
1068                        "build_ast_for_breakable_statement_for:2",
1069                        &first_pair,
1070                    ))
1071                }
1072            };
1073            let second_pair = inner_iter.next().unwrap();
1074            let ((in_of_right, _in_of_right_s), is_for_of) = match second_pair.as_rule() {
1075                Rule::assignment_expression__in | Rule::assignment_expression__in_yield => (
1076                    build_ast_from_assignment_expression(second_pair, script)?,
1077                    true,
1078                ),
1079                _ => (build_ast_from_expression(second_pair, script)?, false),
1080            };
1081            let (statement, mut statement_s) =
1082                build_ast_from_statement(inner_iter.next().unwrap(), script)?;
1083            let node = ForIteratorData {
1084                meta,
1085                left: in_of_left,
1086                right: Box::new(in_of_right),
1087                body: Box::new(statement),
1088            };
1089            s.var_declared_names
1090                .append(&mut statement_s.var_declared_names);
1091            (
1092                if is_for_of {
1093                    StatementType::ForOfStatement(node)
1094                } else {
1095                    StatementType::ForInStatement(node)
1096                },
1097                s,
1098            )
1099        }
1100        _ => {
1101            /* for(;;) variation */
1102            let mut lexical_bound_names = HashMap::new();
1103            let init = match first_pair.as_rule() {
1104                Rule::lexical_declaration | Rule::lexical_declaration__yield => {
1105                    //Lexical Declaration rule ends with smart semicolon which is too flexible. We need to ensure it is semi-colon and nothing else.
1106                    let last_char = first_pair.as_str().trim_end().chars().last().unwrap();
1107                    if last_char != ';' {
1108                        return Err(get_validation_error(
1109                            format!(
1110                                "Was expecting semi-colon at the end, but got '{}'.",
1111                                last_char
1112                            ),
1113                            AstBuilderValidationErrorType::SyntaxError,
1114                            &first_pair,
1115                            script,
1116                        ));
1117                    } else {
1118                        let (d, d_s) = build_ast_from_lexical_declaration(first_pair, script)?;
1119                        for n in &d_s.bound_names {
1120                            lexical_bound_names.insert(n.name.clone(), true);
1121                        }
1122                        Some(VariableDeclarationOrExpression::VariableDeclaration(d))
1123                    }
1124                }
1125                Rule::variable_declaration_list | Rule::variable_declaration_list__yield => {
1126                    let meta = get_meta(&first_pair, script);
1127                    let (declarations, mut declarations_s) =
1128                        build_ast_from_variable_declaration_list(first_pair, script)?;
1129                    s.var_declared_names.append(&mut declarations_s.bound_names);
1130
1131                    if declarations.is_empty() {
1132                        None
1133                    } else {
1134                        Some(VariableDeclarationOrExpression::VariableDeclaration(
1135                            VariableDeclarationData {
1136                                meta,
1137                                declarations,
1138                                kind: VariableDeclarationKind::Var,
1139                            },
1140                        ))
1141                    }
1142                }
1143                Rule::init_expression | Rule::init_expression__yield => {
1144                    if let Some(inner_pair) = first_pair.into_inner().next() {
1145                        let (e, _e_s) = build_ast_from_expression(inner_pair, script)?;
1146                        Some(VariableDeclarationOrExpression::Expression(Box::new(e)))
1147                    } else {
1148                        None
1149                    }
1150                }
1151                _ => {
1152                    return Err(get_unexpected_error(
1153                        "build_ast_for_breakable_statement_for:2",
1154                        &first_pair,
1155                    ))
1156                }
1157            };
1158            let test_pair = inner_iter.next().unwrap();
1159            let (test, _test_s) = if let Some(test_expression_pair) = test_pair.into_inner().next() {
1160                let (e, e_s) = build_ast_from_expression(test_expression_pair, script)?;
1161                (Some(Box::new(e)), e_s)
1162            } else {
1163                (None, Semantics::new_empty())
1164            };
1165            let update_pair = inner_iter.next().unwrap();
1166            let (update, _update_s) =
1167                if let Some(update_expression_pair) = update_pair.into_inner().next() {
1168                    let (e, e_s) = build_ast_from_expression(update_expression_pair, script)?;
1169                    (Some(Box::new(e)), e_s)
1170                } else {
1171                    (None, Semantics::new_empty())
1172                };
1173            let st_pair = inner_iter.next().unwrap();
1174            let (st, mut st_s) = build_ast_from_statement(st_pair, script)?;
1175            for n in &st_s.bound_names {
1176                if lexical_bound_names.contains_key(&n.name) {
1177                    return Err(get_validation_error_with_meta(
1178                        format!("Duplicate declaration found: {}", n),
1179                        AstBuilderValidationErrorType::SyntaxError,
1180                        n.meta.clone(),
1181                    ));
1182                }
1183            }
1184            s.var_declared_names.append(&mut st_s.var_declared_names);
1185            (
1186                StatementType::ForStatement {
1187                    meta,
1188                    init,
1189                    test,
1190                    update,
1191                    body: Box::new(st),
1192                },
1193                s,
1194            )
1195        }
1196    })
1197}
1198
1199fn build_ast_from_binding_pattern(
1200    pair: Pair<Rule>,
1201    script: &Rc<String>,
1202) -> Result<(PatternType, Semantics), JsRuleError> {
1203    let meta = get_meta(&pair, script);
1204    let mut binding_properties = vec![];
1205    let mut s = Semantics::new_empty();
1206    let inner_pair = pair.into_inner().next().unwrap();
1207    Ok(match inner_pair.as_rule() {
1208        Rule::object_binding_pattern | Rule::object_binding_pattern__yield => {
1209            let binding_pattern_inner_iter = inner_pair.into_inner();
1210            for binding_property_pair in binding_pattern_inner_iter {
1211                let (b, b_s) = build_ast_from_binding_property(binding_property_pair, script)?;
1212                s.merge(b_s);
1213                binding_properties.push(b);
1214            }
1215            (
1216                PatternType::ObjectPattern {
1217                    meta,
1218                    properties: binding_properties,
1219                },
1220                s,
1221            )
1222        }
1223        Rule::array_binding_pattern | Rule::array_binding_pattern__yield => {
1224            let mut elements: Vec<Option<Box<PatternType>>> = vec![];
1225            for item_pair in inner_pair.into_inner() {
1226                match item_pair.as_rule() {
1227                    Rule::elision => {
1228                        // Each comma in elision represents a hole
1229                        for _ in 0..(item_pair.as_str().matches(',').count()) {
1230                            elements.push(None);
1231                        }
1232                    }
1233                    Rule::binding_element | Rule::binding_element__yield => {
1234                        let (element, element_s) =
1235                            build_ast_from_binding_element(item_pair, script)?;
1236                        s.merge(element_s);
1237                        elements.push(Some(Box::new(element)));
1238                    }
1239                    Rule::binding_rest_element | Rule::binding_rest_element__yield => {
1240                        let rest_meta = get_meta(&item_pair, script);
1241                        let binding_id_pair = item_pair.into_inner().next().ok_or_else(|| {
1242                            get_validation_error_with_meta(
1243                                "Expected binding identifier in rest element".to_string(),
1244                                AstBuilderValidationErrorType::SyntaxError,
1245                                rest_meta.clone(),
1246                            )
1247                        })?;
1248                        let (id, id_s) = get_binding_identifier_data(binding_id_pair, script)?;
1249                        s.merge(id_s);
1250                        elements.push(Some(Box::new(PatternType::RestElement {
1251                            meta: rest_meta,
1252                            argument: Box::new(
1253                                ExpressionPatternType::Identifier(id).convert_to_pattern(),
1254                            ),
1255                        })));
1256                    }
1257                    _ => {
1258                        return Err(get_unexpected_error(
1259                            "build_ast_from_binding_pattern:array",
1260                            &item_pair,
1261                        ))
1262                    }
1263                }
1264            }
1265            (PatternType::ArrayPattern { meta, elements }, s)
1266        }
1267        _ => {
1268            return Err(get_unexpected_error(
1269                "build_ast_from_binding_pattern",
1270                &inner_pair,
1271            ))
1272        }
1273    })
1274}
1275
1276/// Handles binding_element rule: single_name_binding | binding_pattern ~ initializer?
1277fn build_ast_from_binding_element(
1278    pair: Pair<Rule>,
1279    script: &Rc<String>,
1280) -> Result<(PatternType, Semantics), JsRuleError> {
1281    let meta = get_meta(&pair, script);
1282    let mut inner_iter = pair.into_inner();
1283    let inner_pair = inner_iter.next().ok_or_else(|| {
1284        get_validation_error_with_meta(
1285            "Expected binding element content".to_string(),
1286            AstBuilderValidationErrorType::SyntaxError,
1287            meta.clone(),
1288        )
1289    })?;
1290
1291    match inner_pair.as_rule() {
1292        Rule::single_name_binding | Rule::single_name_binding__yield => {
1293            let (var_decl, s) = build_ast_from_single_name_binding(inner_pair, script)?;
1294            let VariableDeclaratorData { meta, id, init } = var_decl;
1295            if let Some(init_expr) = init {
1296                // Has default value: create AssignmentPattern
1297                Ok((
1298                    PatternType::AssignmentPattern {
1299                        meta,
1300                        left: id,
1301                        right: init_expr,
1302                    },
1303                    s,
1304                ))
1305            } else {
1306                // No default value: just return the pattern
1307                Ok((*id, s))
1308            }
1309        }
1310        Rule::binding_pattern | Rule::binding_pattern__yield => {
1311            let (pattern, s) = build_ast_from_binding_pattern(inner_pair, script)?;
1312            // Check for optional initializer
1313            if let Some(init_pair) = inner_iter.next() {
1314                let init_inner = init_pair.into_inner().next().ok_or_else(|| {
1315                    get_validation_error_with_meta(
1316                        "Expected initializer expression".to_string(),
1317                        AstBuilderValidationErrorType::SyntaxError,
1318                        meta.clone(),
1319                    )
1320                })?;
1321                let (init_expr, _init_s) =
1322                    build_ast_from_assignment_expression(init_inner, script)?;
1323                Ok((
1324                    PatternType::AssignmentPattern {
1325                        meta,
1326                        left: Box::new(pattern),
1327                        right: Box::new(init_expr),
1328                    },
1329                    s,
1330                ))
1331            } else {
1332                Ok((pattern, s))
1333            }
1334        }
1335        _ => Err(get_unexpected_error(
1336            "build_ast_from_binding_element",
1337            &inner_pair,
1338        )),
1339    }
1340}
1341
1342fn build_ast_from_binding_property(
1343    pair: Pair<Rule>,
1344    script: &Rc<String>,
1345) -> Result<(AssignmentPropertyData, Semantics), JsRuleError> {
1346    let mut inner_iter = pair.into_inner();
1347    let inner_pair = inner_iter.next().unwrap();
1348    let meta = get_meta(&inner_pair, script);
1349    if inner_pair.as_rule() == Rule::single_name_binding
1350        || inner_pair.as_rule() == Rule::single_name_binding__yield
1351    {
1352        let inner_pair_rule = &inner_pair.as_rule();
1353        let (VariableDeclaratorData { meta, id, init }, s) =
1354            build_ast_from_single_name_binding(inner_pair, script)?;
1355        let id = if let PatternType::PatternWhichCanBeExpression(
1356            ExpressionPatternType::Identifier(id),
1357        ) = *id
1358        {
1359            id
1360        } else {
1361            return Err(get_unexpected_error_with_rule(
1362                "build_ast_from_binding_property:1",
1363                inner_pair_rule,
1364            ));
1365        };
1366        let meta2 = meta.clone();
1367        let id2 = id.clone();
1368        let value = if let Some(init) = init {
1369            PatternType::AssignmentPattern {
1370                meta,
1371                left: Box::new(ExpressionPatternType::Identifier(id).convert_to_pattern()),
1372                right: init,
1373            }
1374        } else {
1375            ExpressionPatternType::Identifier(id).convert_to_pattern()
1376        };
1377        Ok((
1378            AssignmentPropertyData::new_with_identifier_key(meta2, id2, value, true),
1379            s,
1380        ))
1381    } else if inner_pair.as_rule() == Rule::property_name
1382        || inner_pair.as_rule() == Rule::property_name__yield
1383    {
1384        let (key, _key_s) = build_ast_from_property_name(inner_pair, script)?;
1385        let (value, value_s) =
1386            build_ast_from_lexical_binding_or_variable_declaration_or_binding_element(
1387                inner_iter.next().unwrap(),
1388                script,
1389            )?;
1390        let value_exp = if let Some(init) = value.init {
1391            PatternType::AssignmentPattern {
1392                meta: value.meta,
1393                left: value.id,
1394                right: init,
1395            }
1396        } else {
1397            *value.id
1398        };
1399        // s.merge(value_s); bound_names is read only from value_s (binding_element)
1400        Ok((
1401            AssignmentPropertyData::new_with_any_expression_key(meta, key, value_exp, false),
1402            value_s,
1403        ))
1404    } else {
1405        Err(get_unexpected_error(
1406            "build_ast_from_binding_property:2",
1407            &inner_pair,
1408        ))
1409    }
1410}
1411
1412fn build_ast_from_property_name(
1413    pair: Pair<Rule>,
1414    script: &Rc<String>,
1415) -> Result<(ExpressionType, Semantics), JsRuleError> {
1416    let inner_pair = pair.into_inner().next().unwrap();
1417    Ok(if inner_pair.as_rule() == Rule::literal_property_name {
1418        let pn_pair = inner_pair.into_inner().next().unwrap();
1419        let s = Semantics::new_empty();
1420        (
1421            if pn_pair.as_rule() == Rule::identifier_name {
1422                let id = get_identifier_data(pn_pair, script);
1423                ExpressionPatternType::Identifier(id).convert_to_expression()
1424            } else if pn_pair.as_rule() == Rule::string_literal {
1425                let d = build_ast_from_string_literal(pn_pair, script)?;
1426                ExpressionType::Literal(d)
1427            } else if pn_pair.as_rule() == Rule::numeric_literal {
1428                let meta = get_meta(&pn_pair, script);
1429                let d = build_ast_from_numeric_literal(pn_pair)?;
1430                ExpressionType::Literal(LiteralData {
1431                    meta,
1432                    value: LiteralType::NumberLiteral(d),
1433                })
1434            } else {
1435                return Err(get_unexpected_error(
1436                    "build_ast_from_property_name:1",
1437                    &pn_pair,
1438                ));
1439            },
1440            s,
1441        )
1442    } else if inner_pair.as_rule() == Rule::computed_property_name
1443        || inner_pair.as_rule() == Rule::computed_property_name__yield
1444    {
1445        build_ast_from_assignment_expression(inner_pair.into_inner().next().unwrap(), script)?
1446    } else {
1447        return Err(get_unexpected_error(
1448            "build_ast_from_property_name:2",
1449            &inner_pair,
1450        ));
1451    })
1452}
1453
1454fn build_ast_from_for_binding(
1455    pair: Pair<Rule>,
1456    script: &Rc<String>,
1457) -> Result<(PatternType, Semantics), JsRuleError> {
1458    let inner_pair = pair.into_inner().next().unwrap();
1459    Ok(match inner_pair.as_rule() {
1460        Rule::binding_identifier | Rule::binding_identifier__yield => {
1461            let (bi, bi_s) = get_binding_identifier_data(inner_pair, script)?;
1462            (
1463                ExpressionPatternType::Identifier(bi).convert_to_pattern(),
1464                bi_s,
1465            )
1466        }
1467        Rule::binding_pattern | Rule::binding_pattern__yield => {
1468            build_ast_from_binding_pattern(inner_pair, script)?
1469        }
1470        _ => {
1471            return Err(get_unexpected_error(
1472                "build_ast_from_for_binding",
1473                &inner_pair,
1474            ))
1475        }
1476    })
1477}
1478
1479fn build_ast_from_for_declaration(
1480    pair: Pair<Rule>,
1481    script: &Rc<String>,
1482) -> Result<(VariableDeclarationData, Semantics), JsRuleError> {
1483    let meta = get_meta(&pair, script);
1484    let mut inner_iter = pair.into_inner();
1485    let let_or_const_pair = inner_iter.next().unwrap();
1486    let for_binding_pair = inner_iter.next().unwrap();
1487    let meta2 = meta.clone();
1488    let (b, b_s) = build_ast_from_for_binding(for_binding_pair, script)?;
1489    Ok((
1490        VariableDeclarationData {
1491            meta,
1492            declarations: vec![VariableDeclaratorData {
1493                meta: meta2,
1494                id: Box::new(b),
1495                init: None,
1496            }],
1497            kind: get_let_or_const(let_or_const_pair)?,
1498        },
1499        b_s,
1500    ))
1501}
1502
1503fn get_let_or_const(let_or_const_pair: Pair<Rule>) -> Result<VariableDeclarationKind, JsRuleError> {
1504    Ok(match let_or_const_pair.as_str() {
1505        "let" => VariableDeclarationKind::Let,
1506        "const" => VariableDeclarationKind::Const,
1507        _ => return Err(get_unexpected_error("get_let_or_const", &let_or_const_pair)),
1508    })
1509}
1510
1511fn build_ast_from_switch_statement(
1512    pair: Pair<Rule>,
1513    script: &Rc<String>,
1514) -> Result<(StatementType, Semantics), JsRuleError> {
1515    let meta = get_meta(&pair, script);
1516    let mut inner_iter = pair.into_inner();
1517    let condition_pair = inner_iter.next().unwrap();
1518    let (condition, _condition_s) = build_ast_from_expression(condition_pair, script)?;
1519    let case_block_pair = inner_iter.next().unwrap();
1520    let mut cases = vec![];
1521    let mut s = Semantics::new_empty();
1522    for case_clause_pair in case_block_pair.into_inner() {
1523        match case_clause_pair.as_rule() {
1524            Rule::case_clause
1525            | Rule::case_clause__yield
1526            | Rule::case_clause__return
1527            | Rule::case_clause__yield_return => {
1528                let (c, c_s) = build_ast_from_case_clause(case_clause_pair, script)?;
1529                cases.push(c);
1530                s.merge(c_s);
1531            }
1532            Rule::default_clause
1533            | Rule::default_clause__yield
1534            | Rule::default_clause__return
1535            | Rule::default_clause__yield_return => {
1536                let (c, c_s) = build_ast_from_default_clause(case_clause_pair, script)?;
1537                cases.push(c);
1538                s.merge(c_s);
1539            }
1540            _ => {
1541                return Err(get_unexpected_error(
1542                    "build_ast_from_switch_statement",
1543                    &case_clause_pair,
1544                ))
1545            }
1546        }
1547    }
1548
1549    Ok((
1550        StatementType::SwitchStatement {
1551            meta,
1552            discriminant: Box::new(condition),
1553            cases,
1554        },
1555        s,
1556    ))
1557}
1558
1559fn build_ast_from_case_clause(
1560    pair: Pair<Rule>,
1561    script: &Rc<String>,
1562) -> Result<(SwitchCaseData, Semantics), JsRuleError> {
1563    let meta = get_meta(&pair, script);
1564    let mut inner_iter = pair.into_inner();
1565    let test_pair = inner_iter.next().unwrap();
1566    let (test_exp, _test_exp_s) = build_ast_from_expression(test_pair, script)?;
1567    let (statements, statements_s) = if let Some(statement_pair) = inner_iter.next() {
1568        build_ast_from_statement_list(statement_pair, script)?
1569    } else {
1570        (vec![], Semantics::new_empty())
1571    };
1572    // Resetting this flag, since if there is a 'break' here then it applies to this 'case' clause.
1573    // statements_s.contains_unpaired_break.make_false();
1574    validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(&statements_s)?;
1575    let mut s = Semantics::new_empty();
1576    s.var_declared_names = statements_s.var_declared_names;
1577    Ok((
1578        SwitchCaseData {
1579            meta,
1580            test: Some(Box::new(test_exp)),
1581            consequent: statements,
1582        },
1583        s,
1584    ))
1585}
1586
1587fn build_ast_from_default_clause(
1588    pair: Pair<Rule>,
1589    script: &Rc<String>,
1590) -> Result<(SwitchCaseData, Semantics), JsRuleError> {
1591    let meta = get_meta(&pair, script);
1592    let mut inner_iter = pair.into_inner();
1593    let (statements, statements_s) = if let Some(statement_pair) = inner_iter.next() {
1594        build_ast_from_statement_list(statement_pair, script)?
1595    } else {
1596        (vec![], Semantics::new_empty())
1597    };
1598    // Resetting this flag, since if there is a 'break' here then it applies to this 'case' clause.
1599    // statements_s.contains_unpaired_break.make_false();
1600    validate_lexically_declared_names_have_no_duplicates_and_also_not_present_in_var_declared_names(&statements_s)?;
1601    let mut s = Semantics::new_empty();
1602    s.var_declared_names = statements_s.var_declared_names;
1603    Ok((
1604        SwitchCaseData {
1605            meta,
1606            test: None,
1607            consequent: statements,
1608        },
1609        s,
1610    ))
1611}
1612
1613fn build_ast_from_return_statement(
1614    pair: Pair<Rule>,
1615    script: &Rc<String>,
1616) -> Result<(StatementType, Semantics), JsRuleError> {
1617    let meta = get_meta(&pair, script);
1618    let inner_pair = pair.into_inner().next().unwrap();
1619    let (argument, s) = if inner_pair.as_rule() == Rule::expression__in {
1620        let (e, e_s) = build_ast_from_expression(inner_pair, script)?;
1621        (Some(Box::new(e)), e_s)
1622    } else if inner_pair.as_rule() == Rule::smart_semicolon {
1623        (None, Semantics::new_empty())
1624    } else {
1625        return Err(get_unexpected_error(
1626            "build_ast_from_return_statement",
1627            &inner_pair,
1628        ));
1629    };
1630    Ok((StatementType::ReturnStatement { meta, argument }, s))
1631}
1632
1633fn build_ast_from_try_statement(
1634    pair: Pair<Rule>,
1635    script: &Rc<String>,
1636) -> Result<(StatementType, Semantics), JsRuleError> {
1637    let meta = get_meta(&pair, script);
1638    let mut inner_iter = pair.into_inner();
1639    let block_pair = inner_iter.next().unwrap();
1640    let mut s = Semantics::new_empty();
1641    let (block, mut block_s) = build_ast_from_block(block_pair, script)?;
1642    let next_pair = inner_iter.next().unwrap();
1643    let (handler, mut handler_s, next_pair_option) = match next_pair.as_rule() {
1644        Rule::catch | Rule::catch__yield | Rule::catch__return | Rule::catch__yield_return => {
1645            let meta = get_meta(&next_pair, script);
1646            let mut catch_inner_iter = next_pair.into_inner();
1647            let catch_parameter_pair = catch_inner_iter.next().unwrap();
1648            let catch_parameter_inner_pair = catch_parameter_pair.into_inner().next().unwrap();
1649            let (catch_param, catch_param_s) = match catch_parameter_inner_pair.as_rule() {
1650                Rule::binding_identifier | Rule::binding_identifier__yield => {
1651                    let (bi, bi_s) =
1652                        get_binding_identifier_data(catch_parameter_inner_pair, script)?;
1653                    (
1654                        ExpressionPatternType::Identifier(bi).convert_to_pattern(),
1655                        bi_s,
1656                    )
1657                }
1658                Rule::binding_pattern | Rule::binding_pattern__yield => {
1659                    build_ast_from_binding_pattern(catch_parameter_inner_pair, script)?
1660                }
1661                _ => {
1662                    return Err(get_unexpected_error(
1663                        "build_ast_from_try_statement",
1664                        &catch_parameter_inner_pair,
1665                    ))
1666                }
1667            };
1668            let block_pair = catch_inner_iter.next().unwrap();
1669            let (block, block_s) = build_ast_from_block(block_pair, script)?;
1670            validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&catch_param_s.bound_names, &block_s.var_declared_names,&block_s.lexically_declared_names)?;
1671            let mut s = Semantics::new_empty();
1672            s.var_declared_names = block_s.var_declared_names;
1673            (
1674                Some(CatchClauseData {
1675                    meta,
1676                    param: Box::new(catch_param),
1677                    body: block,
1678                }),
1679                s,
1680                inner_iter.next(),
1681            )
1682        }
1683        _ => (None, Semantics::new_empty(), Some(next_pair)),
1684    };
1685    let (finalizer, mut finalizer_s) = if let Some(finally_pair) = next_pair_option {
1686        let finally_block_pair = finally_pair.into_inner().next().unwrap();
1687        let (b, b_s) = build_ast_from_block(finally_block_pair, script)?;
1688        (Some(b), b_s)
1689    } else {
1690        (None, Semantics::new_empty())
1691    };
1692    s.var_declared_names.append(&mut block_s.var_declared_names);
1693    s.var_declared_names
1694        .append(&mut handler_s.var_declared_names);
1695    s.var_declared_names
1696        .append(&mut finalizer_s.var_declared_names);
1697    Ok((
1698        StatementType::TryStatement {
1699            meta,
1700            block,
1701            handler,
1702            finalizer,
1703        },
1704        s,
1705    ))
1706}
1707
1708fn build_ast_from_variable_statement(
1709    pair: Pair<Rule>,
1710    script: &Rc<String>,
1711) -> Result<(StatementType, Semantics), JsRuleError> {
1712    let meta = get_meta(&pair, script);
1713    let (dl, dl_s) =
1714        build_ast_from_variable_declaration_list(pair.into_inner().next().unwrap(), script)?;
1715    let mut s = Semantics::new_empty();
1716    s.var_declared_names = dl_s.bound_names;
1717    Ok((
1718        StatementType::DeclarationStatement(DeclarationType::VariableDeclaration(
1719            VariableDeclarationData {
1720                meta,
1721                declarations: dl,
1722                kind: VariableDeclarationKind::Var,
1723            },
1724        )),
1725        s,
1726    ))
1727}
1728
1729fn build_ast_from_variable_declaration_list(
1730    pair: Pair<Rule>,
1731    script: &Rc<String>,
1732) -> Result<(Vec<VariableDeclaratorData>, Semantics), JsRuleError> {
1733    let mut declarations = vec![];
1734    let mut s = Semantics::new_empty();
1735    for var_pair in pair.into_inner() {
1736        if var_pair.as_rule() == Rule::variable_declaration
1737            || var_pair.as_rule() == Rule::variable_declaration__in
1738        {
1739            let (d, d_s) =
1740                build_ast_from_lexical_binding_or_variable_declaration_or_binding_element(
1741                    var_pair, script,
1742                )?;
1743            s.merge(d_s);
1744            declarations.push(d)
1745        } else {
1746            return Err(get_unexpected_error(
1747                "build_ast_from_variable_declaration_list",
1748                &var_pair,
1749            ));
1750        }
1751    }
1752    Ok((declarations, s))
1753}
1754
1755fn build_ast_from_lexical_binding_or_variable_declaration_or_binding_element(
1756    pair: Pair<Rule>,
1757    script: &Rc<String>,
1758) -> Result<(VariableDeclaratorData, Semantics), JsRuleError> {
1759    let meta = get_meta(&pair, script);
1760    let mut inner_iter = pair.into_inner();
1761    let inner_pair = inner_iter.next().unwrap();
1762    Ok(
1763        if inner_pair.as_rule() == Rule::binding_identifier
1764            || inner_pair.as_rule() == Rule::binding_identifier__yield
1765        {
1766            let (bi, bi_s) = get_binding_identifier_data(inner_pair, script)?;
1767            let id = Box::new(ExpressionPatternType::Identifier(bi).convert_to_pattern());
1768            (
1769                if let Some(initializer) = inner_iter.next() {
1770                    let (a, _a_s) = build_ast_from_assignment_expression(
1771                        initializer.into_inner().next().unwrap(),
1772                        script,
1773                    )?;
1774                    // bi_s.merge(a_s); bound_names is required only from bi_s
1775                    VariableDeclaratorData {
1776                        meta,
1777                        id,
1778                        init: Some(Box::new(a)),
1779                    }
1780                } else {
1781                    VariableDeclaratorData {
1782                        meta,
1783                        id,
1784                        init: None,
1785                    }
1786                },
1787                bi_s,
1788            )
1789        } else if inner_pair.as_rule() == Rule::binding_pattern
1790            || inner_pair.as_rule() == Rule::binding_pattern__yield
1791        {
1792            let (b, b_s) = build_ast_from_binding_pattern(inner_pair, script)?;
1793            let id = Box::new(b);
1794            let init = if let Some(initializer) = inner_iter.next() {
1795                let (a, _a_s) = build_ast_from_assignment_expression(
1796                    initializer.into_inner().next().unwrap(),
1797                    script,
1798                )?;
1799                // b_s.merge(a_s);  bound_names is required only from b_s
1800                Some(Box::new(a))
1801            } else {
1802                None
1803            };
1804            (VariableDeclaratorData { meta, id, init }, b_s)
1805        } else if inner_pair.as_rule() == Rule::single_name_binding
1806            || inner_pair.as_rule() == Rule::single_name_binding__yield
1807        {
1808            build_ast_from_single_name_binding(inner_pair, script)?
1809        } else {
1810            return Err(get_unexpected_error(
1811                "build_ast_from_lexical_binding_or_variable_declaration",
1812                &inner_pair,
1813            ));
1814        },
1815    )
1816}
1817
1818fn build_ast_from_single_name_binding(
1819    pair: Pair<Rule>,
1820    script: &Rc<String>,
1821) -> Result<(VariableDeclaratorData, Semantics), JsRuleError> {
1822    let meta = get_meta(&pair, script);
1823    let mut inner_iter = pair.into_inner();
1824    let (b, s) = get_binding_identifier_data(inner_iter.next().unwrap(), script)?;
1825    let id = Box::new(ExpressionPatternType::Identifier(b).convert_to_pattern());
1826    Ok(if let Some(initializer) = inner_iter.next() {
1827        let (a, _a_s) = build_ast_from_assignment_expression(initializer, script)?;
1828        // s.merge(a_s); bound_names from s is only used
1829        (
1830            VariableDeclaratorData {
1831                meta,
1832                id,
1833                init: Some(Box::new(a)),
1834            },
1835            s,
1836        )
1837    } else {
1838        (
1839            VariableDeclaratorData {
1840                meta,
1841                id,
1842                init: None,
1843            },
1844            s,
1845        )
1846    })
1847}
1848
1849fn build_ast_from_assignment_expression(
1850    pair: Pair<Rule>,
1851    script: &Rc<String>,
1852) -> Result<(ExpressionType, Semantics), JsRuleError> {
1853    let meta = get_meta(&pair, script);
1854    let mut inner_pair_iter = pair.into_inner();
1855    let inner_pair = inner_pair_iter.next().unwrap();
1856    Ok(match inner_pair.as_rule() {
1857        Rule::arrow_function
1858        | Rule::arrow_function__in
1859        | Rule::arrow_function__yield
1860        | Rule::arrow_function__in_yield => build_ast_from_arrow_function(inner_pair, script)?,
1861        Rule::left_hand_side_expression | Rule::left_hand_side_expression__yield => {
1862            let lhs_pair = inner_pair;
1863            let lhs_meta = get_meta(&lhs_pair, script);
1864            let (lhs, mut s) = build_ast_from_left_hand_side_expression(lhs_pair, script)?;
1865            let mut next_pair = inner_pair_iter.next().unwrap();
1866            let (left, operator) = if next_pair.as_rule() == Rule::assignment_operator {
1867                if s.is_valid_simple_assignment_target.is_false() {
1868                    return Err(get_validation_error_with_meta(
1869                        "L.H.S. needs to be a simple expression".to_string(),
1870                        AstBuilderValidationErrorType::ReferenceError,
1871                        lhs_meta,
1872                    ));
1873                }
1874                let op_str = next_pair.as_str();
1875                next_pair = inner_pair_iter.next().unwrap();
1876                (
1877                    PatternOrExpression::Expression(Box::new(lhs)),
1878                    match op_str {
1879                        "*=" => AssignmentOperator::MultiplyEquals,
1880                        "/=" => AssignmentOperator::DivideEquals,
1881                        "%=" => AssignmentOperator::ModuloEquals,
1882                        "+=" => AssignmentOperator::AddEquals,
1883                        "-=" => AssignmentOperator::SubtractEquals,
1884                        "<<=" => AssignmentOperator::BitwiseLeftShiftEquals,
1885                        ">>=" => AssignmentOperator::BitwiseRightShiftEquals,
1886                        ">>>=" => AssignmentOperator::BitwiseUnsignedRightShiftEquals,
1887                        "&=" => AssignmentOperator::BitwiseAndEquals,
1888                        "^=" => AssignmentOperator::BitwiseXorEquals,
1889                        "|=" => AssignmentOperator::BitwiseOrEquals,
1890                        _ => {
1891                            return Err(get_unexpected_error(
1892                                "build_ast_from_assignment_expression:1",
1893                                &next_pair,
1894                            ))
1895                        }
1896                    },
1897                )
1898            } else {
1899                // For simple `=` assignment, check if LHS needs pattern conversion
1900                // Member expressions and identifiers stay as expressions
1901                // Array/object literals become destructuring patterns
1902                let left = match &lhs {
1903                    ExpressionType::MemberExpression(_) => {
1904                        // Member expression stays as expression (e.g., obj.prop = value)
1905                        PatternOrExpression::Expression(Box::new(lhs))
1906                    }
1907                    ExpressionType::ExpressionWhichCanBePattern(ExpressionPatternType::Identifier(_)) => {
1908                        // Simple identifier stays as expression (e.g., x = value)
1909                        PatternOrExpression::Expression(Box::new(lhs))
1910                    }
1911                    _ => {
1912                        // Array/object literals need pattern conversion for destructuring
1913                        PatternOrExpression::Pattern(Box::new(
1914                            convert_lhs_expression_to_pattern_for_assignment_operation(lhs, Some(&s))?,
1915                        ))
1916                    }
1917                };
1918                (left, AssignmentOperator::Equals)
1919            };
1920            // next_pair is now assignment_expression
1921            let (assignment_exp, assignment_exp_s) =
1922                build_ast_from_assignment_expression(next_pair, script)?;
1923            s.merge(assignment_exp_s);
1924            (
1925                ExpressionType::AssignmentExpression {
1926                    meta,
1927                    left,
1928                    operator,
1929                    right: Box::new(assignment_exp),
1930                },
1931                s,
1932            )
1933        }
1934        Rule::yield_expression | Rule::yield_expression__in => {
1935            match inner_pair.into_inner().next() {
1936                Some(inner_pair) => {
1937                    let (assign_rule_pair, delegate) = if inner_pair.as_rule()
1938                        == Rule::star_assignment_expression__yield
1939                        || inner_pair.as_rule() == Rule::star_assignment_expression__in_yield
1940                    {
1941                        (inner_pair.into_inner().next().unwrap(), true)
1942                    } else {
1943                        (inner_pair, false)
1944                    };
1945                    let (assignment_exp, assignment_exp_s) =
1946                        build_ast_from_assignment_expression(assign_rule_pair, script)?;
1947                    (
1948                        ExpressionType::YieldExpression {
1949                            meta,
1950                            delegate,
1951                            argument: Some(Box::new(assignment_exp)),
1952                        },
1953                        assignment_exp_s,
1954                    )
1955                }
1956                None => (
1957                    ExpressionType::YieldExpression {
1958                        meta,
1959                        delegate: false,
1960                        argument: None,
1961                    },
1962                    Semantics::new_empty(),
1963                ),
1964            }
1965        }
1966        Rule::conditional_expression
1967        | Rule::conditional_expression__in
1968        | Rule::conditional_expression__yield
1969        | Rule::conditional_expression__in_yield => {
1970            build_ast_from_conditional_expression(inner_pair, script)?
1971        }
1972        _ => {
1973            return Err(get_unexpected_error(
1974                "build_ast_from_assignment_expression:2",
1975                &inner_pair,
1976            ))
1977        }
1978    })
1979}
1980
1981fn convert_lhs_expression_to_pattern_for_assignment_operation(
1982    lhs_exp: ExpressionType,
1983    s: Option<&Semantics>,
1984) -> Result<PatternType, JsRuleError> {
1985    match lhs_exp {
1986        ExpressionType::ExpressionWhichCanBePattern(p) => Ok(p.convert_to_pattern()),
1987        ExpressionType::MemberExpression(member_expr) => {
1988            // MemberExpression is a valid assignment target (e.g., obj.prop = value)
1989            // but it doesn't convert directly to a pattern in the destructuring sense.
1990            // Return an error as member expressions can't be destructured.
1991            Err(get_validation_error_with_meta(
1992                "Member expression cannot be used as destructuring pattern".to_string(),
1993                AstBuilderValidationErrorType::ReferenceError,
1994                member_expr.get_meta().clone(),
1995            ))
1996        }
1997        ExpressionType::ArrayExpression {
1998            meta,
1999            elements: o_elements,
2000        } => {
2001            // We need to convert this to ObjectPattern
2002            let mut elements = vec![];
2003            for p in o_elements {
2004                elements.push(if let Some(es) = p {
2005                    Some(Box::new(match es {
2006                        ExpressionOrSpreadElement::Expression(e) => {
2007                            convert_lhs_expression_to_pattern_for_assignment_operation(
2008                                *e,
2009                                None,
2010                            )?
2011                        }
2012                        ExpressionOrSpreadElement::SpreadElement(s) => {
2013                            let s = convert_lhs_expression_to_pattern_for_assignment_operation(
2014                                *s,
2015                                None,
2016                            )?;
2017                            PatternType::RestElement {
2018                                meta: s.get_meta().clone(),
2019                                argument: Box::new(s),
2020                            }
2021                        }
2022                    }))
2023                } else {
2024                    None
2025                });
2026            }
2027            Ok(PatternType::ArrayPattern { meta, elements })
2028        }
2029        ExpressionType::ObjectExpression {
2030            meta,
2031            properties: o_props,
2032        } => {
2033            // We need to convert this to ObjectPattern
2034            let mut properties = vec![];
2035            for p in o_props {
2036                if p.method {
2037                    return Err(get_validation_error_with_meta(
2038                        "Invalid object pattern. Cannot have methods.".to_string(),
2039                        AstBuilderValidationErrorType::SyntaxError,
2040                        p.meta,
2041                    ));
2042                } else {
2043                    properties.push(AssignmentPropertyData::new_with_any_expression_key(
2044                        p.meta,
2045                        *p.key,
2046                        convert_lhs_expression_to_pattern_for_assignment_operation(
2047                            *p.value,
2048                            None,
2049                        )?,
2050                        p.shorthand,
2051                    ));
2052                }
2053            }
2054            Ok(PatternType::ObjectPattern { meta, properties })
2055        }
2056        ExpressionType::Literal(LiteralData { meta, .. })
2057        | ExpressionType::ThisExpression { meta }
2058        | ExpressionType::FunctionOrGeneratorExpression(FunctionData { meta, .. })
2059        | ExpressionType::UnaryExpression { meta, .. }
2060        | ExpressionType::UpdateExpression { meta, .. }
2061        | ExpressionType::BinaryExpression { meta, .. }
2062        | ExpressionType::AssignmentExpression { meta, .. }
2063        | ExpressionType::LogicalExpression { meta, .. }
2064        | ExpressionType::ConditionalExpression { meta, .. }
2065        | ExpressionType::CallExpression { meta, .. }
2066        | ExpressionType::NewExpression { meta, .. }
2067        | ExpressionType::SequenceExpression { meta, .. }
2068        | ExpressionType::ArrowFunctionExpression { meta, .. }
2069        | ExpressionType::YieldExpression { meta, .. }
2070        | ExpressionType::TemplateLiteral(TemplateLiteralData { meta, .. })
2071        | ExpressionType::TaggedTemplateExpression { meta, .. }
2072        | ExpressionType::ClassExpression(ClassData { meta, .. })
2073        | ExpressionType::MetaProperty { meta, .. } => {
2074            if s.is_some() && s.unwrap().is_valid_simple_assignment_target.is_true() {
2075                Err(JsRuleError{ kind: JsErrorType::Unexpected("Unexpected error reached in convert_lhs_expression_to_pattern"), message: "Did not expect a simple assignment target here. It then needs to be converted to pattern".to_string() })
2076            } else {
2077                Err( get_validation_error_with_meta("Parsing error encountered: L.H.S. needs to be a simple expression or object/array literal".to_string(),AstBuilderValidationErrorType::ReferenceError, meta ) )
2078            }
2079        }
2080    }
2081}
2082
2083fn build_ast_from_arrow_function(
2084    pair: Pair<Rule>,
2085    script: &Rc<String>,
2086) -> Result<(ExpressionType, Semantics), JsRuleError> {
2087    let meta = get_meta(&pair, script);
2088    let mut inner_iter = pair.into_inner();
2089    let arrow_parameters_pair = inner_iter.next().unwrap();
2090    let inner_arrow_parameters_pair = arrow_parameters_pair.into_inner().next().unwrap();
2091    let (params, params_s) = match inner_arrow_parameters_pair.as_rule() {
2092        Rule::binding_identifier | Rule::binding_identifier__yield => {
2093            let (b, b_s) = get_binding_identifier_data(inner_arrow_parameters_pair, script)?;
2094            (
2095                vec![
2096                    ExpressionPatternType::Identifier(b).convert_to_pattern()
2097                ],
2098                b_s,
2099            )
2100        }
2101        Rule::formal_parameters | Rule::formal_parameters__yield => {
2102            let (f, f_s) = build_ast_from_formal_parameters(inner_arrow_parameters_pair, script)?;
2103            (f, f_s)
2104        }
2105        _ => {
2106            return Err(get_unexpected_error(
2107                "build_ast_from_arrow_function:1",
2108                &inner_arrow_parameters_pair,
2109            ));
2110        }
2111    };
2112    let concise_body_pair = inner_iter.next().unwrap();
2113    let inner_concise_body_pair = concise_body_pair.into_inner().next().unwrap();
2114    let (body, body_s) = match inner_concise_body_pair.as_rule() {
2115        Rule::function_body => {
2116            let (f, f_s) = build_ast_from_function_body(inner_concise_body_pair, script)?;
2117            (Box::new(FunctionBodyOrExpression::FunctionBody(f)), f_s)
2118        }
2119        Rule::assignment_expression | Rule::assignment_expression__in => {
2120            let (a, _a_s) = build_ast_from_assignment_expression(inner_concise_body_pair, script)?;
2121            (
2122                Box::new(FunctionBodyOrExpression::Expression(a)),
2123                Semantics::new_empty(),
2124            )
2125        }
2126        _ => {
2127            return Err(get_unexpected_error(
2128                "build_ast_from_arrow_function:2",
2129                &inner_concise_body_pair,
2130            ));
2131        }
2132    };
2133    if body_s.contains_yield_expression.is_true() || params_s.contains_yield_expression.is_true() {
2134        Err(get_validation_error_with_meta(
2135            "'yield' is not allowed in arrow function".to_string(),
2136            AstBuilderValidationErrorType::SyntaxError,
2137            body.get_meta().clone(),
2138        ))
2139    } else {
2140        validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&params_s.bound_names,&vec![], &body_s.lexically_declared_names)?;
2141
2142        // let mut s = Semantics::new_empty();
2143        // s.merge(params_s).merge(body_s);
2144        // params_s produces bound_names and body_s produces var_declared_names & lexically_declared_names
2145        Ok((
2146            ExpressionType::ArrowFunctionExpression { meta, params, body },
2147            Semantics::new_empty(),
2148        ))
2149    }
2150}
2151
2152fn build_ast_from_left_hand_side_expression(
2153    pair: Pair<Rule>,
2154    script: &Rc<String>,
2155) -> Result<(ExpressionType, Semantics), JsRuleError> {
2156    let inner_pair: Pair<Rule> = pair.into_inner().next().unwrap();
2157    Ok(match inner_pair.as_rule() {
2158        Rule::call_expression | Rule::call_expression__yield => {
2159            build_ast_from_call_expression(inner_pair, script)?
2160        }
2161        Rule::new_expression | Rule::new_expression__yield => {
2162            build_ast_from_new_expression(inner_pair, script)?
2163        }
2164        _ => {
2165            return Err(get_unexpected_error(
2166                "build_ast_from_left_hand_side_expression",
2167                &inner_pair,
2168            ))
2169        }
2170    })
2171}
2172
2173fn build_ast_from_new_expression(
2174    pair: Pair<Rule>,
2175    script: &Rc<String>,
2176) -> Result<(ExpressionType, Semantics), JsRuleError> {
2177    let inner_pair = pair.into_inner().next().unwrap();
2178    Ok(
2179        if inner_pair.as_rule() == Rule::member_expression
2180            || inner_pair.as_rule() == Rule::member_expression__yield
2181        {
2182            build_ast_from_member_expression(inner_pair, script)?
2183        } else {
2184            let ne_meta = get_meta(&inner_pair, script);
2185            let (n, n_s) = build_ast_from_new_expression(inner_pair, script)?;
2186            (
2187                ExpressionType::NewExpression {
2188                    meta: ne_meta,
2189                    callee: Box::new(n),
2190                    arguments: vec![],
2191                },
2192                n_s,
2193            )
2194        },
2195    )
2196}
2197
2198fn build_ast_from_conditional_expression(
2199    pair: Pair<Rule>,
2200    script: &Rc<String>,
2201) -> Result<(ExpressionType, Semantics), JsRuleError> {
2202    let meta = get_meta(&pair, script);
2203    let mut pair_iter = pair.into_inner();
2204    let logical_or_pair = pair_iter.next().unwrap();
2205    let (or_node, mut s) = build_ast_from_logical_or_expression(logical_or_pair, script)?;
2206    if let Some(inner_pair) = pair_iter.next() {
2207        let (truthy, truthy_s) = build_ast_from_assignment_expression(inner_pair, script)?;
2208        let (falsy, falsy_s) =
2209            build_ast_from_assignment_expression(pair_iter.next().unwrap(), script)?;
2210        s.merge(truthy_s).merge(falsy_s);
2211        Ok((
2212            ExpressionType::ConditionalExpression {
2213                meta,
2214                test: Box::new(or_node),
2215                consequent: Box::new(truthy),
2216                alternate: Box::new(falsy),
2217            },
2218            s,
2219        ))
2220    } else {
2221        Ok((or_node, s))
2222    }
2223}
2224
2225fn get_ast_for_logical_expression(
2226    left: Option<ExpressionType>,
2227    right: ExpressionType,
2228    operator: LogicalOperator,
2229    script: &Rc<String>,
2230) -> ExpressionType {
2231    if let Some(actual_left) = left {
2232        ExpressionType::LogicalExpression {
2233            meta: Meta {
2234                start_index: actual_left.get_meta().start_index,
2235                end_index: right.get_meta().end_index,
2236                script: script.clone(),
2237            },
2238            operator,
2239            left: Box::new(actual_left),
2240            right: Box::new(right),
2241        }
2242    } else {
2243        right
2244    }
2245}
2246
2247fn get_ast_for_binary_expression(
2248    left: Option<ExpressionType>,
2249    right: ExpressionType,
2250    operator: Option<BinaryOperator>,
2251    script: &Rc<String>,
2252) -> ExpressionType {
2253    if let Some(actual_left) = left {
2254        ExpressionType::BinaryExpression {
2255            meta: Meta {
2256                start_index: actual_left.get_meta().start_index,
2257                end_index: right.get_meta().end_index,
2258                script: script.clone(),
2259            },
2260            operator: operator.unwrap(),
2261            left: Box::new(actual_left),
2262            right: Box::new(right),
2263        }
2264    } else {
2265        right
2266    }
2267}
2268
2269fn build_ast_from_logical_or_expression(
2270    pair: Pair<Rule>,
2271    script: &Rc<String>,
2272) -> Result<(ExpressionType, Semantics), JsRuleError> {
2273    let mut left = None;
2274    let mut s = Semantics::new_empty();
2275    for inner_pair in pair.into_inner() {
2276        let (right, right_s) = build_ast_from_logical_and_expression(inner_pair, script)?;
2277        s.merge(right_s);
2278        left = Some(get_ast_for_logical_expression(
2279            left,
2280            right,
2281            LogicalOperator::Or,
2282            script,
2283        ));
2284    }
2285    Ok((left.unwrap(), s))
2286}
2287
2288fn build_ast_from_logical_and_expression(
2289    pair: Pair<Rule>,
2290    script: &Rc<String>,
2291) -> Result<(ExpressionType, Semantics), JsRuleError> {
2292    let mut left = None;
2293    let mut s = Semantics::new_empty();
2294    for inner_pair in pair.into_inner() {
2295        let (right, right_s) = build_ast_from_bitwise_or_expression(inner_pair, script)?;
2296        s.merge(right_s);
2297        left = Some(get_ast_for_logical_expression(
2298            left,
2299            right,
2300            LogicalOperator::And,
2301            script,
2302        ));
2303    }
2304    Ok((left.unwrap(), s))
2305}
2306
2307fn build_ast_from_bitwise_or_expression(
2308    pair: Pair<Rule>,
2309    script: &Rc<String>,
2310) -> Result<(ExpressionType, Semantics), JsRuleError> {
2311    let mut left = None;
2312    let mut s = Semantics::new_empty();
2313    for inner_pair in pair.into_inner() {
2314        let (right, right_s) = build_ast_from_bitwise_xor_expression(inner_pair, script)?;
2315        s.merge(right_s);
2316        left = Some(get_ast_for_binary_expression(
2317            left,
2318            right,
2319            Some(BinaryOperator::BitwiseOr),
2320            script,
2321        ))
2322    }
2323    Ok((left.unwrap(), s))
2324}
2325
2326fn build_ast_from_bitwise_xor_expression(
2327    pair: Pair<Rule>,
2328    script: &Rc<String>,
2329) -> Result<(ExpressionType, Semantics), JsRuleError> {
2330    let mut left = None;
2331    let mut s = Semantics::new_empty();
2332    for inner_pair in pair.into_inner() {
2333        let (right, right_s) = build_ast_from_bitwise_and_expression(inner_pair, script)?;
2334        s.merge(right_s);
2335        left = Some(get_ast_for_binary_expression(
2336            left,
2337            right,
2338            Some(BinaryOperator::BitwiseXor),
2339            script,
2340        ))
2341    }
2342    Ok((left.unwrap(), s))
2343}
2344
2345fn build_ast_from_bitwise_and_expression(
2346    pair: Pair<Rule>,
2347    script: &Rc<String>,
2348) -> Result<(ExpressionType, Semantics), JsRuleError> {
2349    let mut left = None;
2350    let mut s = Semantics::new_empty();
2351    for inner_pair in pair.into_inner() {
2352        let (right, right_s) = build_ast_from_equality_expression(inner_pair, script)?;
2353        s.merge(right_s);
2354        left = Some(get_ast_for_binary_expression(
2355            left,
2356            right,
2357            Some(BinaryOperator::BitwiseAnd),
2358            script,
2359        ))
2360    }
2361    Ok((left.unwrap(), s))
2362}
2363
2364fn build_ast_from_equality_expression(
2365    pair: Pair<Rule>,
2366    script: &Rc<String>,
2367) -> Result<(ExpressionType, Semantics), JsRuleError> {
2368    if cfg!(debug_assertions) {
2369        if pair.as_rule() != Rule::equality_expression
2370            && pair.as_rule() != Rule::equality_expression__in
2371            && pair.as_rule() != Rule::equality_expression__yield
2372            && pair.as_rule() != Rule::equality_expression__in_yield
2373        {
2374            return Err(get_unexpected_error(
2375                "build_ast_from_equality_expression:0",
2376                &pair,
2377            ));
2378        }
2379    }
2380    let mut left = None;
2381    let mut s = Semantics::new_empty();
2382    let mut pair_iter = pair.into_inner();
2383    loop {
2384        if let Some(mut inner_pair) = pair_iter.next() {
2385            let mut operator = None;
2386            if inner_pair.as_rule() == Rule::equality_operator {
2387                operator = Some(match inner_pair.as_str() {
2388                    "===" => BinaryOperator::StrictlyEqual,
2389                    "!==" => BinaryOperator::StrictlyUnequal,
2390                    "==" => BinaryOperator::LooselyEqual,
2391                    "!=" => BinaryOperator::LooselyUnequal,
2392                    _ => {
2393                        return Err(get_unexpected_error(
2394                            "build_ast_from_equality_expression",
2395                            &inner_pair,
2396                        ))
2397                    }
2398                });
2399                inner_pair = pair_iter.next().unwrap();
2400            }
2401            let (right, right_s) = build_ast_from_relational_expression(inner_pair, script)?;
2402            s.merge(right_s);
2403            left = Some(get_ast_for_binary_expression(left, right, operator, script));
2404        } else {
2405            break;
2406        }
2407    }
2408    Ok((left.unwrap(), s))
2409}
2410
2411fn build_ast_from_relational_expression(
2412    pair: Pair<Rule>,
2413    script: &Rc<String>,
2414) -> Result<(ExpressionType, Semantics), JsRuleError> {
2415    if cfg!(debug_assertions) {
2416        if pair.as_rule() != Rule::relational_expression
2417            && pair.as_rule() != Rule::relational_expression__in
2418            && pair.as_rule() != Rule::relational_expression__yield
2419            && pair.as_rule() != Rule::relational_expression__in_yield
2420        {
2421            return Err(get_unexpected_error(
2422                "build_ast_from_relational_expression:0",
2423                &pair,
2424            ));
2425        }
2426    }
2427    let mut left = None;
2428    let mut s = Semantics::new_empty();
2429    let mut pair_iter = pair.into_inner();
2430    loop {
2431        if let Some(mut inner_pair) = pair_iter.next() {
2432            let mut operator = None;
2433            if inner_pair.as_rule() == Rule::relational_operator
2434                || inner_pair.as_rule() == Rule::relational_operator__in
2435            {
2436                operator = Some(match inner_pair.as_str() {
2437                    "<=" => BinaryOperator::LessThanEqual,
2438                    ">=" => BinaryOperator::GreaterThanEqual,
2439                    "<" => BinaryOperator::LessThan,
2440                    ">" => BinaryOperator::GreaterThan,
2441                    "instanceof" => BinaryOperator::InstanceOf,
2442                    "in" => BinaryOperator::In,
2443                    _ => {
2444                        return Err(get_unexpected_error(
2445                            "build_ast_from_relational_expression",
2446                            &inner_pair,
2447                        ))
2448                    }
2449                });
2450                inner_pair = pair_iter.next().unwrap();
2451            }
2452            let (right, right_s) = build_ast_from_shift_expression(inner_pair, script)?;
2453            s.merge(right_s);
2454            left = Some(get_ast_for_binary_expression(left, right, operator, script));
2455        } else {
2456            break;
2457        }
2458    }
2459    Ok((left.unwrap(), s))
2460}
2461
2462fn build_ast_from_shift_expression(
2463    pair: Pair<Rule>,
2464    script: &Rc<String>,
2465) -> Result<(ExpressionType, Semantics), JsRuleError> {
2466    if cfg!(debug_assertions) {
2467        if pair.as_rule() != Rule::shift_expression
2468            && pair.as_rule() != Rule::shift_expression__yield
2469        {
2470            return Err(get_unexpected_error(
2471                "build_ast_from_shift_expression:0",
2472                &pair,
2473            ));
2474        }
2475    }
2476    let mut left = None;
2477    let mut s = Semantics::new_empty();
2478    let mut pair_iter = pair.into_inner();
2479    loop {
2480        if let Some(mut inner_pair) = pair_iter.next() {
2481            let mut operator = None;
2482            if inner_pair.as_rule() == Rule::shift_operator {
2483                operator = Some(match inner_pair.as_str() {
2484                    "<<" => BinaryOperator::BitwiseLeftShift,
2485                    ">>>" => BinaryOperator::BitwiseUnsignedRightShift,
2486                    ">>" => BinaryOperator::BitwiseRightShift,
2487                    _ => {
2488                        return Err(get_unexpected_error(
2489                            "build_ast_from_shift_expression",
2490                            &inner_pair,
2491                        ))
2492                    }
2493                });
2494                inner_pair = pair_iter.next().unwrap();
2495            }
2496            let (right, right_s) = build_ast_from_additive_expression(inner_pair, script)?;
2497            s.merge(right_s);
2498            left = Some(get_ast_for_binary_expression(left, right, operator, script));
2499        } else {
2500            break;
2501        }
2502    }
2503    Ok((left.unwrap(), s))
2504}
2505
2506fn build_ast_from_additive_expression(
2507    pair: Pair<Rule>,
2508    script: &Rc<String>,
2509) -> Result<(ExpressionType, Semantics), JsRuleError> {
2510    let mut left = None;
2511    let mut s = Semantics::new_empty();
2512    let mut pair_iter = pair.into_inner();
2513    loop {
2514        if let Some(mut inner_pair) = pair_iter.next() {
2515            let mut operator = None;
2516            if inner_pair.as_rule() == Rule::additive_operator {
2517                operator = Some(match inner_pair.as_str() {
2518                    "+" => BinaryOperator::Add,
2519                    "-" => BinaryOperator::Subtract,
2520                    _ => {
2521                        return Err(get_unexpected_error(
2522                            "build_ast_from_additive_expression",
2523                            &inner_pair,
2524                        ))
2525                    }
2526                });
2527                inner_pair = pair_iter.next().unwrap();
2528            }
2529            let (right, right_s) = build_ast_from_multiplicative_expression(inner_pair, script)?;
2530            s.merge(right_s);
2531            left = Some(get_ast_for_binary_expression(left, right, operator, script));
2532        } else {
2533            break;
2534        }
2535    }
2536    Ok((left.unwrap(), s))
2537}
2538
2539fn build_ast_from_multiplicative_expression(
2540    pair: Pair<Rule>,
2541    script: &Rc<String>,
2542) -> Result<(ExpressionType, Semantics), JsRuleError> {
2543    let mut left = None;
2544    let mut s = Semantics::new_empty();
2545    let mut pair_iter = pair.into_inner();
2546    loop {
2547        if let Some(mut inner_pair) = pair_iter.next() {
2548            let mut operator = None;
2549            if inner_pair.as_rule() == Rule::multiplicative_operator {
2550                operator = Some(match inner_pair.as_str() {
2551                    "*" => BinaryOperator::Multiply,
2552                    "/" => BinaryOperator::Divide,
2553                    "%" => BinaryOperator::Modulo,
2554                    _ => {
2555                        return Err(get_unexpected_error(
2556                            "build_ast_from_multiplicative_expression",
2557                            &inner_pair,
2558                        ))
2559                    }
2560                });
2561                inner_pair = pair_iter.next().unwrap();
2562            }
2563            let (right, right_s) = build_ast_from_unary_expression(inner_pair, script)?;
2564            s.merge(right_s);
2565            left = Some(get_ast_for_binary_expression(left, right, operator, script));
2566        } else {
2567            break;
2568        }
2569    }
2570    Ok((left.unwrap(), s))
2571}
2572
2573fn build_ast_from_unary_expression(
2574    pair: Pair<Rule>,
2575    script: &Rc<String>,
2576) -> Result<(ExpressionType, Semantics), JsRuleError> {
2577    let meta = get_meta(&pair, script);
2578    let mut pair_iter = pair.into_inner();
2579    let first_pair = pair_iter.next().unwrap();
2580
2581    Ok(
2582        if first_pair.as_rule() == Rule::postfix_expression
2583            || first_pair.as_rule() == Rule::postfix_expression__yield
2584        {
2585            build_ast_from_postfix_expression(first_pair, script)?
2586        } else {
2587            // first_pair is unary_operator - get the operator string directly
2588            let operator_str = first_pair.as_str();
2589            match operator_str {
2590                "++" | "--" => {
2591                    let u_pair = pair_iter.next().unwrap();
2592                    let u_pair_meta = get_meta(&u_pair, script);
2593                    let (u, u_s) = build_ast_from_unary_expression(u_pair, script)?;
2594                    if u_s.is_valid_simple_assignment_target.is_false() {
2595                        return Err(get_validation_error_with_meta(
2596                            "Invalid expression for prefix operator".to_string(),
2597                            AstBuilderValidationErrorType::ReferenceError,
2598                            u_pair_meta,
2599                        ));
2600                    } else {
2601                        (
2602                            ExpressionType::UpdateExpression {
2603                                meta,
2604                                operator: match operator_str {
2605                                    "++" => UpdateOperator::PlusPlus,
2606                                    "--" => UpdateOperator::MinusMinus,
2607                                    _ => unreachable!(),
2608                                },
2609                                argument: Box::new(u),
2610                                prefix: true,
2611                            },
2612                            u_s,
2613                        )
2614                    }
2615                }
2616                _ => {
2617                    let (u, u_s) =
2618                        build_ast_from_unary_expression(pair_iter.next().unwrap(), script)?;
2619                    (
2620                        ExpressionType::UnaryExpression {
2621                            meta,
2622                            operator: match operator_str {
2623                                "delete" => {
2624                                    if let ExpressionType::ExpressionWhichCanBePattern(
2625                                        ExpressionPatternType::Identifier(id),
2626                                    ) = &u
2627                                    {
2628                                        return Err(get_validation_error_with_meta(
2629                                            format!(
2630                                                "Cannot delete identifier reference: {}",
2631                                                id.name
2632                                            ),
2633                                            AstBuilderValidationErrorType::SyntaxError,
2634                                            id.meta.clone(),
2635                                        ));
2636                                    }
2637                                    UnaryOperator::Delete
2638                                }
2639                                "void" => UnaryOperator::Void,
2640                                "typeof" => UnaryOperator::TypeOf,
2641                                "+" => UnaryOperator::Plus,
2642                                "-" => UnaryOperator::Minus,
2643                                "~" => UnaryOperator::BitwiseNot,
2644                                "!" => UnaryOperator::LogicalNot,
2645                                _ => {
2646                                    return Err(get_unexpected_error(
2647                                        "build_ast_from_unary_expression:2",
2648                                        &first_pair,
2649                                    ))
2650                                }
2651                            },
2652                            argument: Box::new(u),
2653                        },
2654                        u_s,
2655                    )
2656                }
2657            }
2658        },
2659    )
2660}
2661
2662fn build_ast_from_postfix_expression(
2663    pair: Pair<Rule>,
2664    script: &Rc<String>,
2665) -> Result<(ExpressionType, Semantics), JsRuleError> {
2666    let meta = get_meta(&pair, script);
2667    let mut pair_iter = pair.into_inner();
2668    let lhs_pair = pair_iter.next().unwrap();
2669    let (lhs, lhs_s) = build_ast_from_left_hand_side_expression(lhs_pair, script)?;
2670    if lhs_s.is_valid_simple_assignment_target.is_false() {
2671        Err(get_validation_error_with_meta(
2672            "Invalid expression for postfix operator".to_string(),
2673            AstBuilderValidationErrorType::ReferenceError,
2674            lhs.get_meta().clone(),
2675        ))
2676    } else {
2677        Ok((
2678            if let Some(op_pair) = pair_iter.next() {
2679                ExpressionType::UpdateExpression {
2680                    meta,
2681                    operator: match op_pair.as_str() {
2682                        "++" => UpdateOperator::PlusPlus,
2683                        "--" => UpdateOperator::MinusMinus,
2684                        _ => {
2685                            return Err(get_unexpected_error(
2686                                "build_ast_from_postfix_expression",
2687                                &op_pair,
2688                            ))
2689                        }
2690                    },
2691                    argument: Box::new(lhs),
2692                    prefix: false,
2693                }
2694            } else {
2695                lhs
2696            },
2697            lhs_s,
2698        ))
2699    }
2700}
2701
2702fn build_ast_from_call_expression(
2703    pair: Pair<Rule>,
2704    script: &Rc<String>,
2705) -> Result<(ExpressionType, Semantics), JsRuleError> {
2706    let mut pair_iter = pair.into_inner();
2707    let pair = pair_iter.next().unwrap();
2708    let meta = get_meta(&pair, script);
2709    let (mut obj, mut s) =
2710        if pair.as_rule() == Rule::super_call || pair.as_rule() == Rule::super_call__yield {
2711            let (a, a_s) = build_ast_from_arguments(pair.into_inner().next().unwrap(), script)?;
2712            (
2713                ExpressionType::CallExpression {
2714                    meta,
2715                    callee: ExpressionOrSuper::Super,
2716                    arguments: a,
2717                },
2718                a_s,
2719            )
2720        } else {
2721            let arguments_pair = pair_iter.next().unwrap();
2722            let (m, mut s) = build_ast_from_member_expression(pair, script)?;
2723            let (a, a_s) = build_ast_from_arguments(arguments_pair, script)?;
2724            s.merge(a_s);
2725            (
2726                ExpressionType::CallExpression {
2727                    meta,
2728                    callee: ExpressionOrSuper::Expression(Box::new(m)),
2729                    arguments: a,
2730                },
2731                s,
2732            )
2733        };
2734    for pair in pair_iter {
2735        let second_meta = get_meta(&pair, script);
2736        let meta = Meta {
2737            start_index: obj.get_meta().start_index,
2738            end_index: second_meta.end_index,
2739            script: script.clone(),
2740        };
2741        obj = match pair.as_rule() {
2742            Rule::expression__in_yield | Rule::expression__in => {
2743                let (e, e_s) = build_ast_from_expression(pair, script)?;
2744                s.merge(e_s);
2745                ExpressionType::MemberExpression(
2746                    MemberExpressionType::ComputedMemberExpression {
2747                        meta,
2748                        object: ExpressionOrSuper::Expression(Box::new(obj)),
2749                        property: Box::new(e),
2750                    },
2751                )
2752            }
2753            Rule::identifier_name => ExpressionType::MemberExpression(
2754                MemberExpressionType::SimpleMemberExpression {
2755                    meta,
2756                    object: ExpressionOrSuper::Expression(Box::new(obj)),
2757                    property: get_identifier_data(pair, script),
2758                },
2759            ),
2760            //Tagged template literal
2761            Rule::template_literal | Rule::template_literal__yield => {
2762                let (template, t_s) = build_ast_from_template_literal(pair, script)?;
2763                s.merge(t_s);
2764                let quasi = if let ExpressionType::TemplateLiteral(data) = template {
2765                    data
2766                } else {
2767                    return Err(get_validation_error_with_meta(
2768                        "Expected template literal".to_string(),
2769                        AstBuilderValidationErrorType::SyntaxError,
2770                        meta.clone(),
2771                    ));
2772                };
2773                ExpressionType::TaggedTemplateExpression {
2774                    meta,
2775                    tag: Box::new(obj),
2776                    quasi,
2777                }
2778            }
2779            Rule::arguments | Rule::arguments__yield => {
2780                let (a, a_s) = build_ast_from_arguments(pair, script)?;
2781                s.merge(a_s);
2782                ExpressionType::CallExpression {
2783                    meta,
2784                    callee: ExpressionOrSuper::Expression(Box::new(obj)),
2785                    arguments: a,
2786                }
2787            }
2788            _ => {
2789                return Err(get_unexpected_error(
2790                    "build_ast_from_call_expression",
2791                    &pair,
2792                ))
2793            }
2794        };
2795    }
2796    Ok((obj, s))
2797}
2798
2799fn get_binding_identifier_data(
2800    pair: Pair<Rule>,
2801    script: &Rc<String>,
2802) -> Result<(IdentifierData, Semantics), JsRuleError> {
2803    let mut id = get_identifier_data(pair, script);
2804    if id.name == "arguments" || id.name == "eval" || id.name == "yield" {
2805        Err(get_validation_error_with_meta(
2806            format!("Invalid binding identifier: {}", id.name),
2807            AstBuilderValidationErrorType::SyntaxError,
2808            id.meta,
2809        ))
2810    } else {
2811        id.is_binding_identifier = true;
2812        let mut s = Semantics::new_empty();
2813        s.bound_names.push(id.clone());
2814        Ok((id, s))
2815    }
2816}
2817
2818fn get_identifier_data(pair: Pair<Rule>, script: &Rc<String>) -> IdentifierData {
2819    IdentifierData {
2820        meta: get_meta(&pair, script),
2821        name: pair.as_str().trim().to_string(),
2822        is_binding_identifier: false,
2823    }
2824}
2825
2826fn build_ast_from_expression(
2827    pair: Pair<Rule>,
2828    script: &Rc<String>,
2829) -> Result<(ExpressionType, Semantics), JsRuleError> {
2830    let meta = get_meta(&pair, script);
2831    let mut node_children: Vec<Box<ExpressionType>> = vec![];
2832    let mut s = Semantics::new_empty();
2833    for inner_pair in pair.into_inner() {
2834        let (a, a_s) = build_ast_from_assignment_expression(inner_pair, script)?;
2835        s.merge(a_s);
2836        node_children.push(Box::new(a));
2837    }
2838    Ok((
2839        ExpressionType::SequenceExpression {
2840            meta,
2841            expressions: node_children,
2842        },
2843        s,
2844    ))
2845}
2846
2847fn build_ast_from_arguments(
2848    pair: Pair<Rule>,
2849    script: &Rc<String>,
2850) -> Result<(Vec<ExpressionOrSpreadElement>, Semantics), JsRuleError> {
2851    let mut arguments = vec![];
2852    let mut s = Semantics::new_empty();
2853    if let Some(argument_list_pair) = pair.into_inner().next() {
2854        for inner_pair in argument_list_pair.into_inner() {
2855            arguments.push(
2856                if inner_pair.as_rule() == Rule::rest_assignment_expression__in
2857                    || inner_pair.as_rule() == Rule::rest_assignment_expression__in_yield
2858                {
2859                    let (a, a_s) = build_ast_from_assignment_expression(
2860                        inner_pair.into_inner().next().unwrap(),
2861                        script,
2862                    )?;
2863                    s.merge(a_s);
2864                    ExpressionOrSpreadElement::SpreadElement(Box::new(a))
2865                } else {
2866                    let (a, a_s) = build_ast_from_assignment_expression(inner_pair, script)?;
2867                    s.merge(a_s);
2868                    ExpressionOrSpreadElement::Expression(Box::new(a))
2869                },
2870            );
2871        }
2872    }
2873    Ok((arguments, s))
2874}
2875
2876fn build_ast_from_member_expression(
2877    pair: Pair<Rule>,
2878    script: &Rc<String>,
2879) -> Result<(ExpressionType, Semantics), JsRuleError> {
2880    let meta = get_meta(&pair, script);
2881    let mut pair_iter = pair.into_inner();
2882    let pair_1 = pair_iter.next().unwrap();
2883    Ok(
2884        if pair_1.as_rule() == Rule::new_member_expression
2885            || pair_1.as_rule() == Rule::new_member_expression__yield
2886        {
2887            let member_expression_pair = pair_1.into_inner().next().unwrap();
2888            let arguments_pair = pair_iter.next().unwrap();
2889            let (m, mut s) = build_ast_from_member_expression(member_expression_pair, script)?;
2890            let (a, a_s) = build_ast_from_arguments(arguments_pair, script)?;
2891            s.merge(a_s);
2892            (
2893                ExpressionType::NewExpression {
2894                    meta,
2895                    callee: Box::new(m),
2896                    arguments: a,
2897                },
2898                s,
2899            )
2900        } else {
2901            let mut s = Semantics::new_empty();
2902            let mut obj: ExpressionType = match pair_1.as_rule() {
2903                Rule::super_property | Rule::super_property__yield => {
2904                    let super_pair = pair_1.into_inner().next().unwrap();
2905                    if super_pair.as_rule() == Rule::identifier_name {
2906                        ExpressionType::MemberExpression(
2907                            MemberExpressionType::SimpleMemberExpression {
2908                                meta,
2909                                object: ExpressionOrSuper::Super,
2910                                property: get_identifier_data(super_pair, script),
2911                            },
2912                        )
2913                    } else {
2914                        let (e, e_s) = build_ast_from_expression(super_pair, script)?;
2915                        s.merge(e_s);
2916                        ExpressionType::MemberExpression(
2917                            MemberExpressionType::ComputedMemberExpression {
2918                                meta,
2919                                object: ExpressionOrSuper::Super,
2920                                property: Box::new(e),
2921                            },
2922                        )
2923                    }
2924                }
2925                Rule::meta_property => {
2926                    let start = meta.start_index;
2927                    let end = meta.end_index;
2928                    ExpressionType::MetaProperty {
2929                        meta,
2930                        meta_object: IdentifierData {
2931                            meta: Meta {
2932                                start_index: start,
2933                                end_index: start + 3,
2934                                script: script.clone(),
2935                            },
2936                            name: "new".to_string(),
2937                            is_binding_identifier: false,
2938                        },
2939                        property: IdentifierData {
2940                            meta: Meta {
2941                                start_index: start + 4,
2942                                end_index: end,
2943                                script: script.clone(),
2944                            },
2945                            name: "target".to_string(),
2946                            is_binding_identifier: false,
2947                        },
2948                    }
2949                }
2950                Rule::primary_expression | Rule::primary_expression__yield => {
2951                    let (p, p_s) = build_ast_from_primary_expression(pair_1, script)?;
2952                    s.merge(p_s);
2953                    p
2954                }
2955                _ => {
2956                    return Err(get_unexpected_error(
2957                        "build_ast_from_member_expression:1",
2958                        &pair_1,
2959                    ))
2960                }
2961            };
2962            for pair in pair_iter {
2963                let second_meta = get_meta(&pair, script);
2964                let meta = Meta {
2965                    start_index: obj.get_meta().start_index,
2966                    end_index: second_meta.end_index,
2967                    script: script.clone(),
2968                };
2969                obj = match pair.as_rule() {
2970                    Rule::expression__in_yield | Rule::expression__in => {
2971                        let (st, st_s) = build_ast_from_expression(pair, script)?;
2972                        s.merge(st_s);
2973                        ExpressionType::MemberExpression(
2974                            MemberExpressionType::ComputedMemberExpression {
2975                                meta,
2976                                object: ExpressionOrSuper::Expression(Box::new(obj)),
2977                                property: Box::new(st),
2978                            },
2979                        )
2980                    }
2981                    Rule::identifier_name => ExpressionType::MemberExpression(
2982                        MemberExpressionType::SimpleMemberExpression {
2983                            meta,
2984                            object: ExpressionOrSuper::Expression(Box::new(obj)),
2985                            property: get_identifier_data(pair, script),
2986                        },
2987                    ),
2988                    Rule::template_literal | Rule::template_literal__yield => {
2989                        let (template, t_s) = build_ast_from_template_literal(pair, script)?;
2990                        s.merge(t_s);
2991                        let quasi = if let ExpressionType::TemplateLiteral(data) = template {
2992                            data
2993                        } else {
2994                            return Err(get_validation_error_with_meta(
2995                                "Expected template literal".to_string(),
2996                                AstBuilderValidationErrorType::SyntaxError,
2997                                meta.clone(),
2998                            ));
2999                        };
3000                        ExpressionType::TaggedTemplateExpression {
3001                            meta,
3002                            tag: Box::new(obj),
3003                            quasi,
3004                        }
3005                    }
3006                    _ => {
3007                        return Err(get_unexpected_error(
3008                            "build_ast_from_member_expression:2",
3009                            &pair,
3010                        ))
3011                    }
3012                };
3013            }
3014            (obj, s)
3015        },
3016    )
3017}
3018
3019fn build_ast_from_primary_expression(
3020    pair: Pair<Rule>,
3021    script: &Rc<String>,
3022) -> Result<(ExpressionType, Semantics), JsRuleError> {
3023    let inner_pair = pair.into_inner().next().unwrap();
3024    let meta = get_meta(&inner_pair, script);
3025    Ok(match inner_pair.as_rule() {
3026        Rule::identifier_reference | Rule::identifier_reference__yield => {
3027            let (i, i_s) = build_ast_from_identifier_reference(inner_pair, script)?;
3028            (i, i_s)
3029        }
3030        Rule::literal => (
3031            ExpressionType::Literal(build_ast_from_literal(inner_pair, script)?),
3032            Semantics::new_empty(),
3033        ),
3034        Rule::this_exp => (
3035            ExpressionType::ThisExpression { meta },
3036            Semantics::new_empty(),
3037        ),
3038        Rule::array_literal | Rule::array_literal__yield => {
3039            let (a, a_s) = build_ast_from_array_literal(inner_pair, script)?;
3040            (a, a_s)
3041        }
3042        Rule::object_literal | Rule::object_literal__yield => {
3043            build_ast_from_object_literal(inner_pair, script)?
3044        } /* is_valid_simple_assignment_target&is_function_definition&is_identifier_ref=false */
3045        Rule::generator_expression => {
3046            let (f, f_s) =
3047                build_ast_from_generator_declaration_or_generator_expression(inner_pair, script)?;
3048            (ExpressionType::FunctionOrGeneratorExpression(f), f_s)
3049        } /* is_valid_simple_assignment_target&is_identifier_ref=false */
3050        Rule::function_expression => {
3051            let (f, f_s) =
3052                build_ast_from_function_declaration_or_function_expression(inner_pair, script)?;
3053            (ExpressionType::FunctionOrGeneratorExpression(f), f_s)
3054        }
3055        Rule::class_expression | Rule::class_expression__yield => {
3056            let (c, c_s) = build_ast_from_class_expression(inner_pair, script)?;
3057            (ExpressionType::ClassExpression(c), c_s)
3058        } /* is_valid_simple_assignment_target&is_identifier_ref=false */
3059        Rule::regular_expression_literal => unimplemented!(), /* is_valid_simple_assignment_target&is_function_definition&is_identifier_ref=false */
3060        Rule::template_literal | Rule::template_literal__yield => {
3061            build_ast_from_template_literal(inner_pair, script)?
3062        } /* is_valid_simple_assignment_target&is_function_definition&is_identifier_ref=false */
3063        Rule::cover_parenthesized_expression_and_arrow_parameter_list
3064        | Rule::cover_parenthesized_expression_and_arrow_parameter_list__yield => {
3065            build_ast_from_cover_parenthesized_expression_and_arrow_parameter_list(
3066                inner_pair, script,
3067            )?
3068        }
3069        _ => {
3070            return Err(get_unexpected_error(
3071                "build_ast_from_primary_expression",
3072                &inner_pair,
3073            ))
3074        }
3075    })
3076}
3077
3078fn build_ast_from_cover_parenthesized_expression_and_arrow_parameter_list(
3079    pair: Pair<Rule>,
3080    script: &Rc<String>,
3081) -> Result<(ExpressionType, Semantics), JsRuleError> {
3082    let inner_pair = expect_inner(pair, "build_ast_from_cover_parenthesized_expression_and_arrow_parameter_list", script)?;
3083    build_ast_from_expression(inner_pair, script)
3084}
3085
3086fn build_ast_from_literal(
3087    pair: Pair<Rule>,
3088    script: &Rc<String>,
3089) -> Result<LiteralData, JsRuleError> {
3090    let inner_pair = expect_inner(pair, "build_ast_from_literal", script)?;
3091    let meta = get_meta(&inner_pair, script);
3092    Ok(match inner_pair.as_rule() {
3093        Rule::null_literal => LiteralData {
3094            meta,
3095            value: LiteralType::NullLiteral,
3096        },
3097        Rule::numeric_literal => LiteralData {
3098            meta,
3099            value: LiteralType::NumberLiteral(build_ast_from_numeric_literal(inner_pair)?),
3100        },
3101        Rule::string_literal => build_ast_from_string_literal(inner_pair, script)?,
3102        Rule::boolean_literal => {
3103            let bool = inner_pair.as_str();
3104            LiteralData {
3105                meta,
3106                value: LiteralType::BooleanLiteral(bool == "true"),
3107            }
3108        }
3109        _ => return Err(get_unexpected_error("build_ast_from_literal", &inner_pair)),
3110    })
3111}
3112
3113fn build_ast_from_string_literal(
3114    pair: Pair<Rule>,
3115    script: &Rc<String>,
3116) -> Result<LiteralData, JsRuleError> {
3117    let meta = get_meta(&pair, script);
3118    let s = pair.as_str();
3119    Ok(LiteralData {
3120        meta,
3121        value: LiteralType::StringLiteral(String::from(&s[1..s.len() - 1])),
3122    })
3123}
3124
3125/// Builds AST from a template literal.
3126/// Template literals can be:
3127///   - no_substitution_template: `hello world`
3128///   - template with substitutions: `hello ${name}!`
3129fn build_ast_from_template_literal(
3130    pair: Pair<Rule>,
3131    script: &Rc<String>,
3132) -> Result<(ExpressionType, Semantics), JsRuleError> {
3133    let meta = get_meta(&pair, script);
3134    let mut quasis: Vec<TemplateElementData> = vec![];
3135    let mut expressions: Vec<Box<ExpressionType>> = vec![];
3136    let mut s = Semantics::new_empty();
3137
3138    for inner_pair in pair.into_inner() {
3139        match inner_pair.as_rule() {
3140            Rule::no_substitution_template => {
3141                // Simple template with no interpolations: `hello`
3142                let raw_str = inner_pair.as_str();
3143                // Remove the backticks
3144                let content = &raw_str[1..raw_str.len() - 1];
3145                let quasi_meta = get_meta(&inner_pair, script);
3146                quasis.push(TemplateElementData {
3147                    meta: quasi_meta,
3148                    tail: true,
3149                    cooked_value: process_template_escapes(content),
3150                    raw_value: content.to_string(),
3151                });
3152            }
3153            Rule::template_head => {
3154                // Head of template with substitutions: `hello ${
3155                let raw_str = inner_pair.as_str();
3156                // Remove ` from start and ${ from end
3157                let content = &raw_str[1..raw_str.len() - 2];
3158                let quasi_meta = get_meta(&inner_pair, script);
3159                quasis.push(TemplateElementData {
3160                    meta: quasi_meta,
3161                    tail: false,
3162                    cooked_value: process_template_escapes(content),
3163                    raw_value: content.to_string(),
3164                });
3165            }
3166            Rule::template_middle => {
3167                // Middle part between substitutions: }...${
3168                let raw_str = inner_pair.as_str();
3169                // Remove } from start and ${ from end
3170                let content = &raw_str[1..raw_str.len() - 2];
3171                let quasi_meta = get_meta(&inner_pair, script);
3172                quasis.push(TemplateElementData {
3173                    meta: quasi_meta,
3174                    tail: false,
3175                    cooked_value: process_template_escapes(content),
3176                    raw_value: content.to_string(),
3177                });
3178            }
3179            Rule::template_tail => {
3180                // End of template with substitutions: }...`
3181                let raw_str = inner_pair.as_str();
3182                // Remove } from start and ` from end
3183                let content = &raw_str[1..raw_str.len() - 1];
3184                let quasi_meta = get_meta(&inner_pair, script);
3185                quasis.push(TemplateElementData {
3186                    meta: quasi_meta,
3187                    tail: true,
3188                    cooked_value: process_template_escapes(content),
3189                    raw_value: content.to_string(),
3190                });
3191            }
3192            Rule::expression__in | Rule::expression__in_yield => {
3193                let (expr, expr_s) = build_ast_from_expression(inner_pair, script)?;
3194                s.merge(expr_s);
3195                expressions.push(Box::new(expr));
3196            }
3197            _ => {
3198                return Err(get_unexpected_error(
3199                    "build_ast_from_template_literal",
3200                    &inner_pair,
3201                ))
3202            }
3203        }
3204    }
3205
3206    Ok((
3207        ExpressionType::TemplateLiteral(TemplateLiteralData {
3208            meta,
3209            quasis,
3210            expressions,
3211        }),
3212        s,
3213    ))
3214}
3215
3216/// Process escape sequences in template literal content.
3217fn process_template_escapes(s: &str) -> String {
3218    let mut result = String::with_capacity(s.len());
3219    let mut chars = s.chars().peekable();
3220
3221    while let Some(c) = chars.next() {
3222        if c == '\\' {
3223            match chars.next() {
3224                Some('n') => result.push('\n'),
3225                Some('r') => result.push('\r'),
3226                Some('t') => result.push('\t'),
3227                Some('\\') => result.push('\\'),
3228                Some('`') => result.push('`'),
3229                Some('$') => result.push('$'),
3230                Some('0') => result.push('\0'),
3231                Some('\'') => result.push('\''),
3232                Some('"') => result.push('"'),
3233                Some('x') => {
3234                    // Hex escape: \xHH
3235                    let mut hex = String::new();
3236                    for _ in 0..2 {
3237                        if let Some(&c) = chars.peek() {
3238                            if c.is_ascii_hexdigit() {
3239                                hex.push(chars.next().unwrap());
3240                            }
3241                        }
3242                    }
3243                    if hex.len() == 2 {
3244                        if let Ok(val) = u8::from_str_radix(&hex, 16) {
3245                            result.push(val as char);
3246                        }
3247                    }
3248                }
3249                Some('u') => {
3250                    // Unicode escape: \uHHHH or \u{H...}
3251                    if chars.peek() == Some(&'{') {
3252                        chars.next(); // consume '{'
3253                        let mut hex = String::new();
3254                        while let Some(&c) = chars.peek() {
3255                            if c == '}' {
3256                                chars.next();
3257                                break;
3258                            }
3259                            if c.is_ascii_hexdigit() {
3260                                hex.push(chars.next().unwrap());
3261                            } else {
3262                                break;
3263                            }
3264                        }
3265                        if let Ok(val) = u32::from_str_radix(&hex, 16) {
3266                            if let Some(ch) = char::from_u32(val) {
3267                                result.push(ch);
3268                            }
3269                        }
3270                    } else {
3271                        let mut hex = String::new();
3272                        for _ in 0..4 {
3273                            if let Some(&c) = chars.peek() {
3274                                if c.is_ascii_hexdigit() {
3275                                    hex.push(chars.next().unwrap());
3276                                }
3277                            }
3278                        }
3279                        if hex.len() == 4 {
3280                            if let Ok(val) = u16::from_str_radix(&hex, 16) {
3281                                result.push(char::from_u32(val as u32).unwrap_or('\u{FFFD}'));
3282                            }
3283                        }
3284                    }
3285                }
3286                Some(other) => {
3287                    // Unknown escape, just include the character
3288                    result.push(other);
3289                }
3290                None => {
3291                    // Trailing backslash
3292                    result.push('\\');
3293                }
3294            }
3295        } else {
3296            result.push(c);
3297        }
3298    }
3299
3300    result
3301}
3302
3303fn build_ast_from_str_numeric_literal(
3304    pair: Pair<Rule>,
3305) -> Result<ExtendedNumberLiteralType, JsRuleError> {
3306    let inner_pair = pair.into_inner().next().unwrap();
3307    Ok(match inner_pair.as_rule() {
3308        Rule::binary_integer_literal => {
3309            ExtendedNumberLiteralType::Std(get_ast_for_binary_integer_literal(inner_pair))
3310        }
3311        Rule::octal_integer_literal => {
3312            ExtendedNumberLiteralType::Std(get_ast_for_octal_integer_literal(inner_pair))
3313        }
3314        Rule::hex_integer_literal => {
3315            ExtendedNumberLiteralType::Std(get_ast_for_hex_integer_literal(inner_pair))
3316        }
3317        Rule::str_decimal_literal => build_ast_str_decimal_literal(inner_pair)?,
3318        _ => {
3319            return Err(get_unexpected_error(
3320                "build_ast_from_str_numeric_literal",
3321                &inner_pair,
3322            ))
3323        }
3324    })
3325}
3326
3327fn build_ast_str_decimal_literal(
3328    pair: Pair<Rule>,
3329) -> Result<ExtendedNumberLiteralType, JsRuleError> {
3330    let mut pair_iter = pair.into_inner();
3331    let mut inner_pair = pair_iter.next().unwrap();
3332    let is_negative = if inner_pair.as_rule() == Rule::str_negative_op {
3333        inner_pair = pair_iter.next().unwrap();
3334        true
3335    } else {
3336        false
3337    };
3338    build_ast_str_unsigned_decimal_literal(inner_pair, is_negative)
3339}
3340
3341fn build_ast_str_unsigned_decimal_literal(
3342    pair: Pair<Rule>,
3343    is_negative: bool,
3344) -> Result<ExtendedNumberLiteralType, JsRuleError> {
3345    let mut num: f64 = 0.0;
3346    let mut is_float = false;
3347    for decimal_pair in pair.into_inner() {
3348        num = match decimal_pair.as_rule() {
3349            Rule::str_decimal_literal_infinity => {
3350                return Ok(if is_negative {
3351                    ExtendedNumberLiteralType::NegativeInfinity
3352                } else {
3353                    ExtendedNumberLiteralType::Infinity
3354                });
3355            }
3356            Rule::decimal_digits_integer_part => parse_decimal_integer_literal(decimal_pair),
3357            Rule::decimal_digits => {
3358                is_float = true;
3359                num + parse_decimal_digits(decimal_pair)
3360            }
3361            Rule::exponent_part => num * parse_exponent_part(decimal_pair),
3362            _ => {
3363                return Err(get_unexpected_error(
3364                    "build_ast_str_unsigned_decimal_literal",
3365                    &decimal_pair,
3366                ))
3367            }
3368        }
3369    }
3370    if is_negative {
3371        num *= -1.0;
3372    }
3373    Ok(if !is_float {
3374        ExtendedNumberLiteralType::Std(NumberLiteralType::IntegerLiteral(num as i64))
3375    } else {
3376        ExtendedNumberLiteralType::Std(NumberLiteralType::FloatLiteral(num))
3377    })
3378}
3379
3380fn get_ast_for_binary_integer_literal(pair: Pair<Rule>) -> NumberLiteralType {
3381    NumberLiteralType::IntegerLiteral(isize::from_str_radix(&pair.as_str()[2..], 2).unwrap() as i64)
3382}
3383
3384fn get_ast_for_octal_integer_literal(pair: Pair<Rule>) -> NumberLiteralType {
3385    NumberLiteralType::IntegerLiteral(isize::from_str_radix(&pair.as_str()[2..], 8).unwrap() as i64)
3386}
3387
3388fn get_ast_for_hex_integer_literal(pair: Pair<Rule>) -> NumberLiteralType {
3389    NumberLiteralType::IntegerLiteral(isize::from_str_radix(&pair.as_str()[2..], 16).unwrap() as i64)
3390}
3391
3392fn parse_decimal_integer_literal(decimal_pair: Pair<Rule>) -> f64 {
3393    isize::from_str_radix(decimal_pair.as_str(), 10).unwrap() as f64
3394}
3395
3396fn parse_decimal_digits(decimal_pair: Pair<Rule>) -> f64 {
3397    let d = decimal_pair.as_str();
3398    isize::from_str_radix(d, 10).unwrap() as f64 / 10_f64.powf(d.len() as f64)
3399}
3400
3401fn parse_exponent_part(decimal_pair: Pair<Rule>) -> f64 {
3402    10_f64.powf(isize::from_str_radix(&decimal_pair.as_str()[1..], 10).unwrap() as f64)
3403}
3404
3405fn build_ast_decimal_literal(pair: Pair<Rule>) -> Result<NumberLiteralType, JsRuleError> {
3406    let mut num: f64 = 0.0;
3407    let mut is_float = false;
3408    for decimal_pair in pair.into_inner() {
3409        num = match decimal_pair.as_rule() {
3410            Rule::decimal_integer_literal => parse_decimal_integer_literal(decimal_pair),
3411            Rule::decimal_digits => {
3412                is_float = true;
3413                num + parse_decimal_digits(decimal_pair)
3414            }
3415            Rule::exponent_part => num * parse_exponent_part(decimal_pair),
3416            _ => {
3417                return Err(get_unexpected_error(
3418                    "build_ast_decimal_literal",
3419                    &decimal_pair,
3420                ))
3421            }
3422        }
3423    }
3424    Ok(if !is_float {
3425        NumberLiteralType::IntegerLiteral(num as i64)
3426    } else {
3427        NumberLiteralType::FloatLiteral(num)
3428    })
3429}
3430
3431fn build_ast_from_numeric_literal(pair: Pair<Rule>) -> Result<NumberLiteralType, JsRuleError> {
3432    let inner_pair = pair.into_inner().next().unwrap();
3433    Ok(match inner_pair.as_rule() {
3434        Rule::binary_integer_literal => get_ast_for_binary_integer_literal(inner_pair),
3435        Rule::octal_integer_literal => get_ast_for_octal_integer_literal(inner_pair),
3436        Rule::hex_integer_literal => get_ast_for_hex_integer_literal(inner_pair),
3437        Rule::decimal_literal => build_ast_decimal_literal(inner_pair)?,
3438        _ => {
3439            return Err(get_unexpected_error(
3440                "build_ast_from_numeric_literal",
3441                &inner_pair,
3442            ))
3443        }
3444    })
3445}
3446
3447fn build_ast_from_array_literal(
3448    pair: Pair<Rule>,
3449    script: &Rc<String>,
3450) -> Result<(ExpressionType, Semantics), JsRuleError> {
3451    let meta = get_meta(&pair, script);
3452    let mut arguments = vec![];
3453    let mut s = Semantics::new_empty();
3454    for inner_pair in pair.into_inner() {
3455        match inner_pair.as_rule() {
3456            Rule::elision => {
3457                for _ in 0..(inner_pair.as_str().matches(',').count()) {
3458                    arguments.push(None);
3459                }
3460            }
3461            Rule::assignment_expression__in | Rule::assignment_expression__in_yield => {
3462                let (a, a_s) = build_ast_from_assignment_expression(inner_pair, script)?;
3463                s.merge(a_s);
3464                arguments.push(Some(ExpressionOrSpreadElement::Expression(Box::new(a))));
3465            }
3466            Rule::spread_element | Rule::spread_element__yield => {
3467                let spread_inner = expect_inner(inner_pair, "spread_element", script)?;
3468                let (a, a_s) = build_ast_from_assignment_expression(spread_inner, script)?;
3469                s.merge(a_s);
3470                arguments.push(Some(ExpressionOrSpreadElement::SpreadElement(Box::new(a))));
3471            }
3472            _ => {
3473                return Err(get_unexpected_error(
3474                    "build_ast_from_array_literal",
3475                    &inner_pair,
3476                ))
3477            }
3478        }
3479    }
3480    Ok((
3481        ExpressionType::ArrayExpression {
3482            meta,
3483            elements: arguments,
3484        },
3485        s,
3486    ))
3487}
3488
3489fn build_ast_from_object_literal(
3490    pair: Pair<Rule>,
3491    script: &Rc<String>,
3492) -> Result<(ExpressionType, Semantics), JsRuleError> {
3493    let meta = get_meta(&pair, script);
3494    let mut s = Semantics::new_empty();
3495    let mut properties = vec![];
3496    for property_pair in pair.into_inner() {
3497        let (p, p_s) = build_ast_from_property_definition(property_pair, script)?;
3498        s.merge(p_s);
3499        properties.push(p);
3500    }
3501    Ok((ExpressionType::ObjectExpression { meta, properties }, s))
3502}
3503
3504fn build_ast_from_property_definition(
3505    pair: Pair<Rule>,
3506    script: &Rc<String>,
3507) -> Result<(PropertyData<Box<ExpressionType>>, Semantics), JsRuleError> {
3508    let meta = get_meta(&pair, script);
3509    let mut s = Semantics::new_empty();
3510    let mut inner_pair_iter = pair.into_inner();
3511    let inner_pair = inner_pair_iter.next().unwrap();
3512    let p = match inner_pair.as_rule() {
3513        Rule::property_name | Rule::property_name__yield => {
3514            let (p, p_s) = build_ast_from_property_name(inner_pair, script)?;
3515            let (a, a_s) =
3516                build_ast_from_assignment_expression(inner_pair_iter.next().unwrap(), script)?;
3517            s.merge(p_s).merge(a_s);
3518            PropertyData::new_with_any_expression_key(
3519                meta,
3520                p,
3521                Box::new(a),
3522                PropertyKind::Init,
3523                false,
3524                false,
3525            )
3526        }
3527        Rule::cover_initialized_name | Rule::cover_initialized_name__yield => {
3528            let error = format!("Initialization is only possible for object destruction pattern not in object literal: {}", inner_pair.as_str());
3529            return Err(get_validation_error(
3530                error,
3531                AstBuilderValidationErrorType::SyntaxError,
3532                &inner_pair,
3533                &script,
3534            ));
3535        }
3536        Rule::method_definition | Rule::method_definition__yield => {
3537            let meta = get_meta(&inner_pair, script);
3538            let (m, m_s) = build_ast_from_method_definition(inner_pair, script)?;
3539            if m_s.has_direct_super.is_true() {
3540                return Err(get_validation_error_with_meta(
3541                    "Invalid reference to super".to_string(),
3542                    AstBuilderValidationErrorType::SyntaxError,
3543                    meta,
3544                ));
3545            }
3546            s.merge(m_s);
3547            m
3548        }
3549        Rule::identifier_reference | Rule::identifier_reference__yield => {
3550            let id = get_identifier_data(inner_pair, script);
3551            let id2 = id.clone();
3552            PropertyData::new_with_identifier_key(
3553                meta,
3554                id,
3555                Box::new(ExpressionPatternType::Identifier(id2).convert_to_expression()),
3556                PropertyKind::Init,
3557                false,
3558                true,
3559            )
3560        }
3561        _ => {
3562            return Err(get_unexpected_error(
3563                "build_ast_from_property_definition",
3564                &inner_pair,
3565            ))
3566        }
3567    };
3568    Ok((p, s))
3569}
3570
3571fn build_ast_from_method_definition(
3572    pair: Pair<Rule>,
3573    script: &Rc<String>,
3574) -> Result<(PropertyData<Box<ExpressionType>>, Semantics), JsRuleError> {
3575    let meta = get_meta(&pair, script);
3576    let mut s = Semantics::new_empty();
3577    let mut inner_iter = pair.into_inner();
3578    let inner_pair = inner_iter.next().unwrap();
3579    let m = match inner_pair.as_rule() {
3580        Rule::property_name | Rule::property_name__yield => {
3581            let (p, p_s) = build_ast_from_property_name(inner_pair, script)?;
3582            let (fp, fp_s) = build_ast_from_formal_parameters(inner_iter.next().unwrap(), script)?;
3583            let (fb, fb_s) = build_ast_from_function_body(inner_iter.next().unwrap(), script)?;
3584            validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&fp_s.bound_names,&vec![],&fb_s.lexically_declared_names)?;
3585            s.merge(p_s).merge(fp_s).merge(fb_s);
3586            let meta2 = meta.clone();
3587            PropertyData::new_with_any_expression_key(
3588                meta,
3589                p,
3590                Box::new(ExpressionType::FunctionOrGeneratorExpression(
3591                    FunctionData {
3592                        meta: meta2,
3593                        id: None,
3594                        params: FormalParameters::new(fp),
3595                        body: Box::new(fb),
3596                        generator: false,
3597                    },
3598                )),
3599                PropertyKind::Init,
3600                true,
3601                false,
3602            )
3603        }
3604        Rule::generator_method | Rule::generator_method__yield => {
3605            let mut inner_inner_iter = inner_pair.into_inner();
3606            let (p, p_s) = build_ast_from_property_name(inner_inner_iter.next().unwrap(), script)?;
3607            let (fp, fp_s) =
3608                build_ast_from_formal_parameters(inner_inner_iter.next().unwrap(), script)?;
3609            let (fb, fb_s) =
3610                build_ast_from_generator_body(inner_inner_iter.next().unwrap(), script)?;
3611            if fb_s.has_direct_super.is_true() {
3612                return Err(get_validation_error_with_meta(
3613                    "Invalid reference to 'super'".to_string(),
3614                    AstBuilderValidationErrorType::SyntaxError,
3615                    meta.clone(),
3616                ));
3617            }
3618            validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&fp_s.bound_names,&vec![],&fb_s.lexically_declared_names)?;
3619            s.merge(p_s).merge(fp_s).merge(fb_s);
3620            let meta2 = meta.clone();
3621            PropertyData::new_with_any_expression_key(
3622                meta,
3623                p,
3624                Box::new(ExpressionType::FunctionOrGeneratorExpression(
3625                    FunctionData {
3626                        meta: meta2,
3627                        id: None,
3628                        params: FormalParameters::new(fp),
3629                        body: Box::new(fb),
3630                        generator: true,
3631                    },
3632                )),
3633                PropertyKind::Init,
3634                true,
3635                false,
3636            )
3637        }
3638        Rule::getter => {
3639            let (p, p_s) = build_ast_from_property_name(inner_iter.next().unwrap(), script)?;
3640            let (fb, fb_s) = build_ast_from_function_body(inner_iter.next().unwrap(), script)?;
3641            s.merge(p_s).merge(fb_s);
3642            let meta2 = meta.clone();
3643            PropertyData::new_with_any_expression_key(
3644                meta,
3645                p,
3646                Box::new(ExpressionType::FunctionOrGeneratorExpression(
3647                    FunctionData {
3648                        meta: meta2,
3649                        id: None,
3650                        params: FormalParameters::new(vec![]),
3651                        body: Box::new(fb),
3652                        generator: false,
3653                    },
3654                )),
3655                PropertyKind::Get,
3656                false,
3657                false,
3658            )
3659        }
3660        Rule::setter => {
3661            let (p, p_s) = build_ast_from_property_name(inner_iter.next().unwrap(), script)?;
3662            // Setters use property_set_parameter_list which is a single formal_parameter (silent rule)
3663            let (fp, fp_s) = build_ast_from_single_formal_parameter(inner_iter.next().unwrap(), script)?;
3664            let (fb, fb_s) = build_ast_from_function_body(inner_iter.next().unwrap(), script)?;
3665            validate_bound_names_have_no_duplicates_and_also_not_present_in_var_declared_names_or_lexically_declared_names(&fp_s.bound_names,&vec![],&fb_s.lexically_declared_names)?;
3666            s.merge(p_s).merge(fp_s).merge(fb_s);
3667            let meta2 = meta.clone();
3668            PropertyData::new_with_any_expression_key(
3669                meta,
3670                p,
3671                Box::new(ExpressionType::FunctionOrGeneratorExpression(
3672                    FunctionData {
3673                        meta: meta2,
3674                        id: None,
3675                        params: FormalParameters::new(fp),
3676                        body: Box::new(fb),
3677                        generator: false,
3678                    },
3679                )),
3680                PropertyKind::Set,
3681                false,
3682                false,
3683            )
3684        }
3685        _ => {
3686            return Err(get_unexpected_error(
3687                "build_ast_from_method_definition",
3688                &inner_pair,
3689            ))
3690        }
3691    };
3692    Ok((m, s))
3693}
3694
3695fn build_ast_from_identifier_reference(
3696    pair: Pair<Rule>,
3697    script: &Rc<String>,
3698) -> Result<(ExpressionType, Semantics), JsRuleError> {
3699    let id = pair.as_str();
3700    if id == "yield" {
3701        Err(get_validation_error(
3702            format!("Invalid identifier reference: {}", id),
3703            AstBuilderValidationErrorType::SyntaxError,
3704            &pair,
3705            &script,
3706        ))
3707    } else {
3708        let s = Semantics::new_empty();
3709        Ok((
3710            ExpressionPatternType::Identifier(get_identifier_data(pair, script))
3711                .convert_to_expression(),
3712            s,
3713        ))
3714    }
3715}
3716
3717/// Builds AST from a class declaration.
3718/// Grammar: "class" ~ binding_identifier ~ class_tail
3719fn build_ast_from_class_declaration(
3720    pair: Pair<Rule>,
3721    script: &Rc<String>,
3722) -> Result<(ClassData, Semantics), JsRuleError> {
3723    let meta = get_meta(&pair, script);
3724    let mut pair_iter = pair.into_inner();
3725    let mut s = Semantics::new_empty();
3726
3727    // binding_identifier is required for class declarations
3728    let id_pair = pair_iter.next().ok_or_else(|| {
3729        get_validation_error_with_meta(
3730            "Expected class name".to_string(),
3731            AstBuilderValidationErrorType::SyntaxError,
3732            meta.clone(),
3733        )
3734    })?;
3735    let (id, id_s) = get_binding_identifier_data(id_pair, script)?;
3736    s.merge(id_s);
3737
3738    // Parse class_tail
3739    let class_tail_pair = pair_iter.next().ok_or_else(|| {
3740        get_validation_error_with_meta(
3741            "Expected class body".to_string(),
3742            AstBuilderValidationErrorType::SyntaxError,
3743            meta.clone(),
3744        )
3745    })?;
3746    let (super_class, body, tail_s) = build_ast_from_class_tail(class_tail_pair, script)?;
3747    s.merge(tail_s);
3748
3749    Ok((
3750        ClassData {
3751            meta,
3752            id: Some(id),
3753            super_class,
3754            body,
3755        },
3756        s,
3757    ))
3758}
3759
3760/// Builds AST from a class expression.
3761/// Grammar: "class" ~ binding_identifier? ~ class_tail
3762fn build_ast_from_class_expression(
3763    pair: Pair<Rule>,
3764    script: &Rc<String>,
3765) -> Result<(ClassData, Semantics), JsRuleError> {
3766    let meta = get_meta(&pair, script);
3767    let mut pair_iter = pair.into_inner();
3768    let mut s = Semantics::new_empty();
3769
3770    // Check if there's an optional binding_identifier
3771    let first_pair = pair_iter.next();
3772    let (id, class_tail_pair) = if let Some(fp) = first_pair {
3773        if fp.as_rule() == Rule::binding_identifier || fp.as_rule() == Rule::binding_identifier__yield
3774        {
3775            let (id, _id_s) = get_binding_identifier_data(fp, script)?;
3776            // For class expressions, we don't include the name in bound_names
3777            let tail = pair_iter.next().ok_or_else(|| {
3778                get_validation_error_with_meta(
3779                    "Expected class body".to_string(),
3780                    AstBuilderValidationErrorType::SyntaxError,
3781                    meta.clone(),
3782                )
3783            })?;
3784            (Some(id), tail)
3785        } else {
3786            // It's the class_tail
3787            (None, fp)
3788        }
3789    } else {
3790        return Err(get_validation_error_with_meta(
3791            "Expected class body".to_string(),
3792            AstBuilderValidationErrorType::SyntaxError,
3793            meta.clone(),
3794        ));
3795    };
3796
3797    let (super_class, body, tail_s) = build_ast_from_class_tail(class_tail_pair, script)?;
3798    s.merge(tail_s);
3799
3800    Ok((
3801        ClassData {
3802            meta,
3803            id,
3804            super_class,
3805            body,
3806        },
3807        s,
3808    ))
3809}
3810
3811/// Builds AST from class_tail.
3812/// Grammar: class_heritage? ~ "{" ~ class_body? ~ "}"
3813fn build_ast_from_class_tail(
3814    pair: Pair<Rule>,
3815    script: &Rc<String>,
3816) -> Result<(Option<Box<ExpressionType>>, ClassBodyData, Semantics), JsRuleError> {
3817    let meta = get_meta(&pair, script);
3818    let mut s = Semantics::new_empty();
3819    let mut super_class = None;
3820    let mut methods: Vec<MethodDefinitionData> = vec![];
3821
3822    for inner_pair in pair.into_inner() {
3823        match inner_pair.as_rule() {
3824            Rule::class_heritage | Rule::class_heritage__yield => {
3825                // class_heritage = "extends" ~ left_hand_side_expression
3826                let lhs_pair = inner_pair.into_inner().next().ok_or_else(|| {
3827                    get_validation_error_with_meta(
3828                        "Expected superclass expression".to_string(),
3829                        AstBuilderValidationErrorType::SyntaxError,
3830                        meta.clone(),
3831                    )
3832                })?;
3833                let (expr, expr_s) = build_ast_from_left_hand_side_expression(lhs_pair, script)?;
3834                s.merge(expr_s);
3835                super_class = Some(Box::new(expr));
3836            }
3837            Rule::class_body | Rule::class_body__yield => {
3838                // class_body = class_element_list
3839                for element_pair in inner_pair.into_inner() {
3840                    if let Some(method) =
3841                        build_ast_from_class_element(element_pair, script, &mut s)?
3842                    {
3843                        methods.push(method);
3844                    }
3845                }
3846            }
3847            _ => {
3848                return Err(get_unexpected_error("build_ast_from_class_tail", &inner_pair))
3849            }
3850        }
3851    }
3852
3853    Ok((
3854        super_class,
3855        ClassBodyData { meta, body: methods },
3856        s,
3857    ))
3858}
3859
3860/// Builds AST from a class_element.
3861/// Grammar: method_definition | "static" ~ method_definition | ";"
3862fn build_ast_from_class_element(
3863    pair: Pair<Rule>,
3864    script: &Rc<String>,
3865    s: &mut Semantics,
3866) -> Result<Option<MethodDefinitionData>, JsRuleError> {
3867    let meta = get_meta(&pair, script);
3868    let mut inner_iter = pair.into_inner();
3869
3870    // Check if empty (semicolon-only element)
3871    let first_pair = match inner_iter.next() {
3872        Some(p) => p,
3873        None => return Ok(None), // Empty class element (;)
3874    };
3875
3876    let (is_static, method_pair) = if first_pair.as_rule() == Rule::class_static {
3877        let mp = inner_iter.next().ok_or_else(|| {
3878            get_validation_error_with_meta(
3879                "Expected method definition after 'static'".to_string(),
3880                AstBuilderValidationErrorType::SyntaxError,
3881                meta.clone(),
3882            )
3883        })?;
3884        (true, mp)
3885    } else {
3886        (false, first_pair)
3887    };
3888
3889    // Parse the method definition
3890    let (prop_data, method_s) = build_ast_from_method_definition(method_pair, script)?;
3891    s.merge(method_s);
3892
3893    // Convert PropertyData to MethodDefinitionData
3894    let PropertyData {
3895        meta: prop_meta,
3896        key,
3897        value,
3898        kind,
3899        method: _,
3900        shorthand: _,
3901        computed,
3902    } = prop_data;
3903
3904    // Extract FunctionData from the value expression
3905    let func_data = match *value {
3906        ExpressionType::FunctionOrGeneratorExpression(f) => f,
3907        _ => {
3908            return Err(get_validation_error_with_meta(
3909                "Expected function in method definition".to_string(),
3910                AstBuilderValidationErrorType::SyntaxError,
3911                prop_meta.clone(),
3912            ));
3913        }
3914    };
3915
3916    // Determine method kind
3917    let method_kind = match kind {
3918        PropertyKind::Init => {
3919            // Check if it's a constructor
3920            if let ExpressionType::ExpressionWhichCanBePattern(ExpressionPatternType::Identifier(
3921                ref id,
3922            )) = *key
3923            {
3924                if id.name == "constructor" && !is_static {
3925                    MethodDefinitionKind::Constructor
3926                } else {
3927                    MethodDefinitionKind::Method
3928                }
3929            } else {
3930                MethodDefinitionKind::Method
3931            }
3932        }
3933        PropertyKind::Get => MethodDefinitionKind::Get,
3934        PropertyKind::Set => MethodDefinitionKind::Set,
3935    };
3936
3937    Ok(Some(MethodDefinitionData {
3938        meta: prop_meta,
3939        key,
3940        value: func_data,
3941        kind: method_kind,
3942        computed,
3943        static_flag: is_static,
3944    }))
3945}