solscript_parser/
parser.rs

1//! AST construction from pest parse tree (Solidity-Style)
2
3use pest::Parser;
4use smol_str::SmolStr;
5use solscript_ast::*;
6
7use crate::{ParseError, Rule, SolScriptParser};
8
9type Pair<'a> = pest::iterators::Pair<'a, Rule>;
10
11/// Parse a complete SolScript program
12pub fn parse_program(source: &str) -> Result<Program, ParseError> {
13    let mut pairs = SolScriptParser::parse(Rule::program, source).map_err(|e| {
14        let mut err: ParseError = e.into();
15        if let ParseError::Syntax { src, .. } = &mut err {
16            *src = source.to_string();
17        }
18        err
19    })?;
20
21    let mut items = Vec::new();
22    let mut span = Span::dummy();
23
24    // Get the program rule's inner pairs
25    let program_pair = pairs.next().unwrap();
26    span = span_from_pair(&program_pair);
27
28    for pair in program_pair.into_inner() {
29        match pair.as_rule() {
30            Rule::item => {
31                let item = parse_item(pair.into_inner().next().unwrap())?;
32                items.push(item);
33            }
34            Rule::EOI => {}
35            _ => {}
36        }
37    }
38
39    Ok(Program { items, span })
40}
41
42fn span_from_pair(pair: &Pair) -> Span {
43    let span = pair.as_span();
44    Span::new(span.start(), span.end())
45}
46
47fn parse_ident(pair: Pair) -> Ident {
48    Ident::new(pair.as_str(), span_from_pair(&pair))
49}
50
51fn parse_item(pair: Pair) -> Result<Item, ParseError> {
52    match pair.as_rule() {
53        Rule::import_stmt => Ok(Item::Import(parse_import(pair)?)),
54        Rule::contract_def => Ok(Item::Contract(parse_contract(pair)?)),
55        Rule::interface_def => Ok(Item::Interface(parse_interface(pair)?)),
56        Rule::struct_def => Ok(Item::Struct(parse_struct(pair)?)),
57        Rule::enum_def => Ok(Item::Enum(parse_enum(pair)?)),
58        Rule::event_def => Ok(Item::Event(parse_event(pair)?)),
59        Rule::error_def => Ok(Item::Error(parse_error_def(pair)?)),
60        Rule::function_def => Ok(Item::Function(parse_function(pair)?)),
61        _ => unreachable!("Unexpected rule: {:?}", pair.as_rule()),
62    }
63}
64
65// =============================================================================
66// Import parsing
67// =============================================================================
68
69fn parse_import(pair: Pair) -> Result<ImportStmt, ParseError> {
70    let span = span_from_pair(&pair);
71    let mut items = Vec::new();
72    let mut source = SmolStr::default();
73
74    for inner in pair.into_inner() {
75        match inner.as_rule() {
76            Rule::import_list => {
77                for item in inner.into_inner() {
78                    if item.as_rule() == Rule::import_item {
79                        items.push(parse_import_item(item)?);
80                    }
81                }
82            }
83            Rule::string_lit => {
84                source = parse_string_content(inner.as_str());
85            }
86            _ => {}
87        }
88    }
89
90    Ok(ImportStmt {
91        items,
92        source,
93        span,
94    })
95}
96
97fn parse_import_item(pair: Pair) -> Result<ImportItem, ParseError> {
98    let span = span_from_pair(&pair);
99    let mut inner = pair.into_inner();
100
101    let name = parse_ident(inner.next().unwrap());
102    let alias = inner.next().map(parse_ident);
103
104    Ok(ImportItem { name, alias, span })
105}
106
107fn parse_string_content(s: &str) -> SmolStr {
108    // Remove quotes and handle escape sequences
109    let s = &s[1..s.len() - 1];
110    SmolStr::new(s)
111}
112
113// =============================================================================
114// Contract parsing
115// =============================================================================
116
117fn parse_contract(pair: Pair) -> Result<ContractDef, ParseError> {
118    let span = span_from_pair(&pair);
119    let mut attributes = Vec::new();
120    let mut is_abstract = false;
121    let mut name = None;
122    let mut bases = Vec::new();
123    let mut members = Vec::new();
124
125    for inner in pair.into_inner() {
126        match inner.as_rule() {
127            Rule::attribute => attributes.push(parse_attribute(inner)?),
128            Rule::abstract_kw => is_abstract = true,
129            Rule::ident => name = Some(parse_ident(inner)),
130            Rule::inheritance_list => {
131                for tp in inner.into_inner() {
132                    if tp.as_rule() == Rule::type_path {
133                        bases.push(parse_type_path(tp)?);
134                    }
135                }
136            }
137            Rule::contract_member => {
138                let member_inner = inner.into_inner().next().unwrap();
139                match member_inner.as_rule() {
140                    Rule::state_var => {
141                        members.push(ContractMember::StateVar(parse_state_var(member_inner)?));
142                    }
143                    Rule::constructor_def => {
144                        members.push(ContractMember::Constructor(parse_constructor(
145                            member_inner,
146                        )?));
147                    }
148                    Rule::modifier_def => {
149                        members.push(ContractMember::Modifier(parse_modifier_def(member_inner)?));
150                    }
151                    Rule::function_def => {
152                        members.push(ContractMember::Function(parse_function(member_inner)?));
153                    }
154                    Rule::event_def => {
155                        members.push(ContractMember::Event(parse_event(member_inner)?));
156                    }
157                    Rule::error_def => {
158                        members.push(ContractMember::Error(parse_error_def(member_inner)?));
159                    }
160                    Rule::struct_def => {
161                        members.push(ContractMember::Struct(parse_struct(member_inner)?));
162                    }
163                    Rule::enum_def => {
164                        members.push(ContractMember::Enum(parse_enum(member_inner)?));
165                    }
166                    _ => {}
167                }
168            }
169            _ => {}
170        }
171    }
172
173    Ok(ContractDef {
174        attributes,
175        is_abstract,
176        name: name.unwrap(),
177        bases,
178        members,
179        span,
180    })
181}
182
183fn parse_state_var(pair: Pair) -> Result<StateVar, ParseError> {
184    let span = span_from_pair(&pair);
185    let mut attributes = Vec::new();
186    let mut ty = None;
187    let mut visibility = None;
188    let mut name = None;
189    let mut initializer = None;
190
191    for inner in pair.into_inner() {
192        match inner.as_rule() {
193            Rule::attribute => attributes.push(parse_attribute(inner)?),
194            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
195            Rule::visibility => visibility = Some(parse_visibility(inner)),
196            Rule::ident => name = Some(parse_ident(inner)),
197            Rule::expr => initializer = Some(parse_expr(inner)?),
198            _ => {}
199        }
200    }
201
202    Ok(StateVar {
203        attributes,
204        ty: ty.unwrap(),
205        visibility,
206        name: name.unwrap(),
207        initializer,
208        span,
209    })
210}
211
212fn parse_constructor(pair: Pair) -> Result<ConstructorDef, ParseError> {
213    let span = span_from_pair(&pair);
214    let mut params = Vec::new();
215    let mut modifiers = Vec::new();
216    let mut body = None;
217
218    for inner in pair.into_inner() {
219        match inner.as_rule() {
220            Rule::param_list => params = parse_param_list(inner)?,
221            Rule::modifier_invocation => modifiers.push(parse_modifier_invocation(inner)?),
222            Rule::block => body = Some(parse_block(inner)?),
223            _ => {}
224        }
225    }
226
227    Ok(ConstructorDef {
228        params,
229        modifiers,
230        body: body.unwrap(),
231        span,
232    })
233}
234
235fn parse_modifier_def(pair: Pair) -> Result<ModifierDef, ParseError> {
236    let span = span_from_pair(&pair);
237    let mut name = None;
238    let mut params = Vec::new();
239    let mut body = None;
240
241    for inner in pair.into_inner() {
242        match inner.as_rule() {
243            Rule::ident => name = Some(parse_ident(inner)),
244            Rule::param_list => params = parse_param_list(inner)?,
245            Rule::modifier_block => body = Some(parse_modifier_block(inner)?),
246            _ => {}
247        }
248    }
249
250    Ok(ModifierDef {
251        name: name.unwrap(),
252        params,
253        body: body.unwrap(),
254        span,
255    })
256}
257
258fn parse_modifier_block(pair: Pair) -> Result<Block, ParseError> {
259    let span = span_from_pair(&pair);
260    let mut stmts = Vec::new();
261
262    for inner in pair.into_inner() {
263        if inner.as_rule() == Rule::modifier_stmt {
264            stmts.push(parse_modifier_stmt(inner)?);
265        }
266    }
267
268    Ok(Block { stmts, span })
269}
270
271fn parse_modifier_stmt(pair: Pair) -> Result<Stmt, ParseError> {
272    let inner = pair.into_inner().next().unwrap();
273
274    match inner.as_rule() {
275        Rule::placeholder_stmt => Ok(Stmt::Placeholder(span_from_pair(&inner))),
276        Rule::var_decl_stmt => Ok(Stmt::VarDecl(parse_var_decl_stmt(inner)?)),
277        Rule::return_stmt => Ok(Stmt::Return(parse_return_stmt(inner)?)),
278        Rule::if_stmt => Ok(Stmt::If(parse_if_stmt(inner)?)),
279        Rule::require_stmt => Ok(Stmt::Require(parse_require_stmt(inner)?)),
280        Rule::revert_stmt => Ok(Stmt::Revert(parse_revert_stmt(inner)?)),
281        Rule::expr_stmt => Ok(Stmt::Expr(parse_expr_stmt(inner)?)),
282        _ => unreachable!("Unexpected modifier_stmt rule: {:?}", inner.as_rule()),
283    }
284}
285
286// =============================================================================
287// Interface parsing
288// =============================================================================
289
290fn parse_interface(pair: Pair) -> Result<InterfaceDef, ParseError> {
291    let span = span_from_pair(&pair);
292    let mut attributes = Vec::new();
293    let mut name = None;
294    let mut bases = Vec::new();
295    let mut members = Vec::new();
296
297    for inner in pair.into_inner() {
298        match inner.as_rule() {
299            Rule::attribute => attributes.push(parse_attribute(inner)?),
300            Rule::ident => name = Some(parse_ident(inner)),
301            Rule::inheritance_list => {
302                for tp in inner.into_inner() {
303                    if tp.as_rule() == Rule::type_path {
304                        bases.push(parse_type_path(tp)?);
305                    }
306                }
307            }
308            Rule::interface_member => {
309                // interface_member = { function_sig ~ ";" }
310                let sig_pair = inner.into_inner().next().unwrap();
311                members.push(parse_function_sig(sig_pair)?);
312            }
313            _ => {}
314        }
315    }
316
317    Ok(InterfaceDef {
318        attributes,
319        name: name.unwrap(),
320        bases,
321        members,
322        span,
323    })
324}
325
326fn parse_function_sig(pair: Pair) -> Result<FnSig, ParseError> {
327    let span = span_from_pair(&pair);
328    let mut name = None;
329    let mut generic_params = None;
330    let mut params = Vec::new();
331    let mut visibility = None;
332    let mut state_mutability = Vec::new();
333    let mut modifiers = Vec::new();
334    let mut return_params = Vec::new();
335
336    for inner in pair.into_inner() {
337        match inner.as_rule() {
338            Rule::ident => name = Some(parse_ident(inner)),
339            Rule::generic_params => generic_params = Some(parse_generic_params(inner)?),
340            Rule::param_list => params = parse_param_list(inner)?,
341            Rule::visibility => visibility = Some(parse_visibility(inner)),
342            Rule::state_mutability => state_mutability.push(parse_state_mutability(inner)),
343            Rule::modifier_invocation => modifiers.push(parse_modifier_invocation(inner)?),
344            Rule::returns_clause => return_params = parse_returns_clause(inner)?,
345            _ => {}
346        }
347    }
348
349    Ok(FnSig {
350        name: name.unwrap(),
351        generic_params,
352        params,
353        visibility,
354        state_mutability,
355        modifiers,
356        return_params,
357        span,
358    })
359}
360
361// =============================================================================
362// Struct parsing
363// =============================================================================
364
365fn parse_struct(pair: Pair) -> Result<StructDef, ParseError> {
366    let span = span_from_pair(&pair);
367    let mut attributes = Vec::new();
368    let mut name = None;
369    let mut generic_params = None;
370    let mut fields = Vec::new();
371
372    for inner in pair.into_inner() {
373        match inner.as_rule() {
374            Rule::attribute => attributes.push(parse_attribute(inner)?),
375            Rule::ident => name = Some(parse_ident(inner)),
376            Rule::generic_params => generic_params = Some(parse_generic_params(inner)?),
377            Rule::struct_field => fields.push(parse_struct_field(inner)?),
378            _ => {}
379        }
380    }
381
382    Ok(StructDef {
383        attributes,
384        name: name.unwrap(),
385        generic_params,
386        fields,
387        span,
388    })
389}
390
391fn parse_struct_field(pair: Pair) -> Result<StructField, ParseError> {
392    let span = span_from_pair(&pair);
393    let mut inner = pair.into_inner();
394
395    // Solidity-style: type name;
396    let ty = parse_type_expr(inner.next().unwrap())?;
397    let name = parse_ident(inner.next().unwrap());
398
399    Ok(StructField { ty, name, span })
400}
401
402// =============================================================================
403// Enum parsing
404// =============================================================================
405
406fn parse_enum(pair: Pair) -> Result<EnumDef, ParseError> {
407    let span = span_from_pair(&pair);
408    let mut attributes = Vec::new();
409    let mut name = None;
410    let mut variants = Vec::new();
411
412    for inner in pair.into_inner() {
413        match inner.as_rule() {
414            Rule::attribute => attributes.push(parse_attribute(inner)?),
415            Rule::ident => name = Some(parse_ident(inner)),
416            Rule::enum_variant => variants.push(parse_enum_variant(inner)?),
417            _ => {}
418        }
419    }
420
421    Ok(EnumDef {
422        attributes,
423        name: name.unwrap(),
424        variants,
425        span,
426    })
427}
428
429fn parse_enum_variant(pair: Pair) -> Result<EnumVariant, ParseError> {
430    let span = span_from_pair(&pair);
431    let name = parse_ident(pair.into_inner().next().unwrap());
432
433    Ok(EnumVariant { name, span })
434}
435
436// =============================================================================
437// Event & Error parsing
438// =============================================================================
439
440fn parse_event(pair: Pair) -> Result<EventDef, ParseError> {
441    let span = span_from_pair(&pair);
442    let mut name = None;
443    let mut params = Vec::new();
444
445    for inner in pair.into_inner() {
446        match inner.as_rule() {
447            Rule::ident => name = Some(parse_ident(inner)),
448            Rule::event_param => params.push(parse_event_param(inner)?),
449            _ => {}
450        }
451    }
452
453    Ok(EventDef {
454        name: name.unwrap(),
455        params,
456        span,
457    })
458}
459
460fn parse_event_param(pair: Pair) -> Result<EventParam, ParseError> {
461    let span = span_from_pair(&pair);
462    let mut ty = None;
463    let mut indexed = false;
464    let mut name = None;
465
466    for inner in pair.into_inner() {
467        match inner.as_rule() {
468            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
469            Rule::indexed_kw => indexed = true,
470            Rule::ident => name = Some(parse_ident(inner)),
471            _ => {}
472        }
473    }
474
475    Ok(EventParam {
476        ty: ty.unwrap(),
477        indexed,
478        name: name.unwrap(),
479        span,
480    })
481}
482
483fn parse_error_def(pair: Pair) -> Result<ErrorDef, ParseError> {
484    let span = span_from_pair(&pair);
485    let mut name = None;
486    let mut params = Vec::new();
487
488    for inner in pair.into_inner() {
489        match inner.as_rule() {
490            Rule::ident => name = Some(parse_ident(inner)),
491            Rule::error_param => params.push(parse_error_param(inner)?),
492            _ => {}
493        }
494    }
495
496    Ok(ErrorDef {
497        name: name.unwrap(),
498        params,
499        span,
500    })
501}
502
503fn parse_error_param(pair: Pair) -> Result<ErrorParam, ParseError> {
504    let span = span_from_pair(&pair);
505    let mut inner = pair.into_inner();
506
507    let ty = parse_type_expr(inner.next().unwrap())?;
508    let name = parse_ident(inner.next().unwrap());
509
510    Ok(ErrorParam { ty, name, span })
511}
512
513// =============================================================================
514// Function parsing
515// =============================================================================
516
517fn parse_function(pair: Pair) -> Result<FnDef, ParseError> {
518    let span = span_from_pair(&pair);
519    let mut attributes = Vec::new();
520    let mut name = None;
521    let mut generic_params = None;
522    let mut params = Vec::new();
523    let mut visibility = None;
524    let mut state_mutability = Vec::new();
525    let mut modifiers = Vec::new();
526    let mut return_params = Vec::new();
527    let mut body = None;
528
529    for inner in pair.into_inner() {
530        match inner.as_rule() {
531            Rule::attribute => attributes.push(parse_attribute(inner)?),
532            Rule::ident => name = Some(parse_ident(inner)),
533            Rule::generic_params => generic_params = Some(parse_generic_params(inner)?),
534            Rule::param_list => params = parse_param_list(inner)?,
535            Rule::visibility => visibility = Some(parse_visibility(inner)),
536            Rule::state_mutability => state_mutability.push(parse_state_mutability(inner)),
537            Rule::modifier_invocation => modifiers.push(parse_modifier_invocation(inner)?),
538            Rule::returns_clause => return_params = parse_returns_clause(inner)?,
539            Rule::block => body = Some(parse_block(inner)?),
540            _ => {}
541        }
542    }
543
544    Ok(FnDef {
545        attributes,
546        name: name.unwrap(),
547        generic_params,
548        params,
549        visibility,
550        state_mutability,
551        modifiers,
552        return_params,
553        body, // None for abstract functions (semicolon instead of block)
554        span,
555    })
556}
557
558fn parse_visibility(pair: Pair) -> Visibility {
559    match pair.as_str() {
560        "public" => Visibility::Public,
561        "private" => Visibility::Private,
562        "internal" => Visibility::Internal,
563        "external" => Visibility::External,
564        _ => unreachable!(),
565    }
566}
567
568fn parse_state_mutability(pair: Pair) -> StateMutability {
569    match pair.as_str() {
570        "view" => StateMutability::View,
571        "pure" => StateMutability::Pure,
572        "payable" => StateMutability::Payable,
573        _ => unreachable!(),
574    }
575}
576
577fn parse_modifier_invocation(pair: Pair) -> Result<ModifierInvocation, ParseError> {
578    let span = span_from_pair(&pair);
579    let mut name = None;
580    let mut args = Vec::new();
581
582    for inner in pair.into_inner() {
583        match inner.as_rule() {
584            Rule::ident => name = Some(parse_ident(inner)),
585            Rule::arg_list => args = parse_arg_list(inner)?,
586            _ => {}
587        }
588    }
589
590    Ok(ModifierInvocation {
591        name: name.unwrap(),
592        args,
593        span,
594    })
595}
596
597fn parse_returns_clause(pair: Pair) -> Result<Vec<ReturnParam>, ParseError> {
598    let mut return_params = Vec::new();
599
600    for inner in pair.into_inner() {
601        if inner.as_rule() == Rule::return_param_list {
602            for rp in inner.into_inner() {
603                if rp.as_rule() == Rule::return_param {
604                    return_params.push(parse_return_param(rp)?);
605                }
606            }
607        }
608    }
609
610    Ok(return_params)
611}
612
613fn parse_return_param(pair: Pair) -> Result<ReturnParam, ParseError> {
614    let span = span_from_pair(&pair);
615    let mut ty = None;
616    let mut name = None;
617
618    for inner in pair.into_inner() {
619        match inner.as_rule() {
620            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
621            Rule::ident => name = Some(parse_ident(inner)),
622            _ => {}
623        }
624    }
625
626    Ok(ReturnParam {
627        ty: ty.unwrap(),
628        name,
629        span,
630    })
631}
632
633fn parse_param_list(pair: Pair) -> Result<Vec<Param>, ParseError> {
634    let mut params = Vec::new();
635    for inner in pair.into_inner() {
636        if inner.as_rule() == Rule::param {
637            params.push(parse_param(inner)?);
638        }
639    }
640    Ok(params)
641}
642
643fn parse_param(pair: Pair) -> Result<Param, ParseError> {
644    let span = span_from_pair(&pair);
645    let mut ty = None;
646    let mut storage_location = None;
647    let mut name = None;
648
649    for inner in pair.into_inner() {
650        match inner.as_rule() {
651            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
652            Rule::storage_location => storage_location = Some(parse_storage_location(inner)),
653            Rule::ident => name = Some(parse_ident(inner)),
654            _ => {}
655        }
656    }
657
658    Ok(Param {
659        ty: ty.unwrap(),
660        storage_location,
661        name: name.unwrap(),
662        span,
663    })
664}
665
666fn parse_storage_location(pair: Pair) -> StorageLocation {
667    match pair.as_str() {
668        "memory" => StorageLocation::Memory,
669        "storage" => StorageLocation::Storage,
670        "calldata" => StorageLocation::Calldata,
671        _ => unreachable!(),
672    }
673}
674
675// =============================================================================
676// Generics parsing
677// =============================================================================
678
679fn parse_generic_params(pair: Pair) -> Result<GenericParams, ParseError> {
680    let span = span_from_pair(&pair);
681    let mut params = Vec::new();
682
683    for inner in pair.into_inner() {
684        if inner.as_rule() == Rule::generic_param {
685            params.push(parse_generic_param(inner)?);
686        }
687    }
688
689    Ok(GenericParams { params, span })
690}
691
692fn parse_generic_param(pair: Pair) -> Result<GenericParam, ParseError> {
693    let span = span_from_pair(&pair);
694    let mut name = None;
695    let mut bounds = Vec::new();
696
697    for inner in pair.into_inner() {
698        match inner.as_rule() {
699            Rule::ident => name = Some(parse_ident(inner)),
700            Rule::type_expr => bounds.push(parse_type_expr(inner)?),
701            _ => {}
702        }
703    }
704
705    Ok(GenericParam {
706        name: name.unwrap(),
707        bounds,
708        span,
709    })
710}
711
712fn parse_generic_args(pair: Pair) -> Result<GenericArgs, ParseError> {
713    let span = span_from_pair(&pair);
714    let mut args = Vec::new();
715
716    for inner in pair.into_inner() {
717        if inner.as_rule() == Rule::type_expr {
718            args.push(parse_type_expr(inner)?);
719        }
720    }
721
722    Ok(GenericArgs { args, span })
723}
724
725// =============================================================================
726// Attribute parsing
727// =============================================================================
728
729fn parse_attribute(pair: Pair) -> Result<Attribute, ParseError> {
730    let span = span_from_pair(&pair);
731    let inner = pair.into_inner().next().unwrap(); // attribute_inner
732
733    let mut name = None;
734    let mut args = Vec::new();
735
736    for p in inner.into_inner() {
737        match p.as_rule() {
738            Rule::ident => name = Some(parse_ident(p)),
739            Rule::attribute_args => {
740                for arg in p.into_inner() {
741                    if arg.as_rule() == Rule::attribute_arg {
742                        args.push(parse_attribute_arg(arg)?);
743                    }
744                }
745            }
746            _ => {}
747        }
748    }
749
750    Ok(Attribute {
751        name: name.unwrap(),
752        args,
753        span,
754    })
755}
756
757fn parse_attribute_arg(pair: Pair) -> Result<AttributeArg, ParseError> {
758    let span = span_from_pair(&pair);
759    let mut name = None;
760    let mut value = None;
761
762    for inner in pair.into_inner() {
763        match inner.as_rule() {
764            Rule::ident => {
765                if name.is_none() && value.is_none() {
766                    // Could be name or value
767                    let ident = parse_ident(inner);
768                    value = Some(AttributeValue::Ident(ident));
769                } else {
770                    name = value.take().and_then(|v| {
771                        if let AttributeValue::Ident(i) = v {
772                            Some(i)
773                        } else {
774                            None
775                        }
776                    });
777                    value = Some(AttributeValue::Ident(parse_ident(inner)));
778                }
779            }
780            Rule::literal => {
781                value = Some(AttributeValue::Literal(parse_literal(inner)?));
782            }
783            Rule::string_lit => {
784                let s = parse_string_content(inner.as_str());
785                value = Some(AttributeValue::Literal(Literal::String(
786                    s,
787                    span_from_pair(&inner),
788                )));
789            }
790            _ => {}
791        }
792    }
793
794    Ok(AttributeArg {
795        name,
796        value: value.unwrap(),
797        span,
798    })
799}
800
801// =============================================================================
802// Type expression parsing
803// =============================================================================
804
805fn parse_type_expr(pair: Pair) -> Result<TypeExpr, ParseError> {
806    let inner = pair.into_inner().next().unwrap();
807
808    match inner.as_rule() {
809        Rule::mapping_type => {
810            let span = span_from_pair(&inner);
811            let mut inner_iter = inner.into_inner();
812            let key = parse_type_expr(inner_iter.next().unwrap())?;
813            let value = parse_type_expr(inner_iter.next().unwrap())?;
814            Ok(TypeExpr::Mapping(Box::new(MappingType {
815                key,
816                value,
817                span,
818            })))
819        }
820        Rule::array_type => {
821            let span = span_from_pair(&inner);
822            let mut element = None;
823            let mut sizes = Vec::new();
824
825            for p in inner.into_inner() {
826                match p.as_rule() {
827                    Rule::type_path => element = Some(parse_type_path(p)?),
828                    Rule::array_size => {
829                        let size: u64 = p.as_str().parse().unwrap_or(0);
830                        sizes.push(Some(size));
831                    }
832                    _ => {
833                        // Empty brackets []
834                        if sizes.is_empty() || sizes.last() != Some(&None) {
835                            // Only add None if we haven't just added one
836                        }
837                    }
838                }
839            }
840
841            // If no explicit sizes were found, it's a dynamic array
842            if sizes.is_empty() {
843                sizes.push(None);
844            }
845
846            Ok(TypeExpr::Array(Box::new(ArrayType {
847                element: element.unwrap(),
848                sizes,
849                span,
850            })))
851        }
852        Rule::type_tuple => {
853            let span = span_from_pair(&inner);
854            let mut elements = Vec::new();
855            for p in inner.into_inner() {
856                if p.as_rule() == Rule::type_expr {
857                    elements.push(parse_type_expr(p)?);
858                }
859            }
860            Ok(TypeExpr::Tuple(TypeTuple { elements, span }))
861        }
862        Rule::type_path => Ok(TypeExpr::Path(parse_type_path(inner)?)),
863        _ => unreachable!("Unexpected type rule: {:?}", inner.as_rule()),
864    }
865}
866
867fn parse_type_path(pair: Pair) -> Result<TypePath, ParseError> {
868    let span = span_from_pair(&pair);
869    let mut segments = Vec::new();
870    let mut generic_args = None;
871
872    for inner in pair.into_inner() {
873        match inner.as_rule() {
874            Rule::ident => segments.push(parse_ident(inner)),
875            Rule::generic_args => generic_args = Some(parse_generic_args(inner)?),
876            _ => {}
877        }
878    }
879
880    Ok(TypePath {
881        segments,
882        generic_args,
883        span,
884    })
885}
886
887// =============================================================================
888// Statement parsing
889// =============================================================================
890
891fn parse_block(pair: Pair) -> Result<Block, ParseError> {
892    let span = span_from_pair(&pair);
893    let mut stmts = Vec::new();
894
895    for inner in pair.into_inner() {
896        if inner.as_rule() == Rule::stmt {
897            stmts.push(parse_stmt(inner)?);
898        }
899    }
900
901    Ok(Block { stmts, span })
902}
903
904fn parse_stmt(pair: Pair) -> Result<Stmt, ParseError> {
905    let inner = pair.into_inner().next().unwrap();
906
907    match inner.as_rule() {
908        Rule::var_decl_stmt => Ok(Stmt::VarDecl(parse_var_decl_stmt(inner)?)),
909        Rule::return_stmt => Ok(Stmt::Return(parse_return_stmt(inner)?)),
910        Rule::if_stmt => Ok(Stmt::If(parse_if_stmt(inner)?)),
911        Rule::while_stmt => Ok(Stmt::While(parse_while_stmt(inner)?)),
912        Rule::for_stmt => Ok(Stmt::For(parse_for_stmt(inner)?)),
913        Rule::emit_stmt => Ok(Stmt::Emit(parse_emit_stmt(inner)?)),
914        Rule::require_stmt => Ok(Stmt::Require(parse_require_stmt(inner)?)),
915        Rule::revert_stmt => Ok(Stmt::Revert(parse_revert_stmt(inner)?)),
916        Rule::delete_stmt => Ok(Stmt::Delete(parse_delete_stmt(inner)?)),
917        Rule::selfdestruct_stmt => Ok(Stmt::Selfdestruct(parse_selfdestruct_stmt(inner)?)),
918        Rule::expr_stmt => Ok(Stmt::Expr(parse_expr_stmt(inner)?)),
919        _ => unreachable!("Unexpected statement rule: {:?}", inner.as_rule()),
920    }
921}
922
923fn parse_var_decl_stmt(pair: Pair) -> Result<VarDeclStmt, ParseError> {
924    let span = span_from_pair(&pair);
925    let mut ty = None;
926    let mut storage_location = None;
927    let mut name = None;
928    let mut initializer = None;
929
930    for inner in pair.into_inner() {
931        match inner.as_rule() {
932            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
933            Rule::storage_location => storage_location = Some(parse_storage_location(inner)),
934            Rule::ident => name = Some(parse_ident(inner)),
935            Rule::expr => initializer = Some(parse_expr(inner)?),
936            _ => {}
937        }
938    }
939
940    Ok(VarDeclStmt {
941        ty: ty.unwrap(),
942        storage_location,
943        name: name.unwrap(),
944        initializer,
945        span,
946    })
947}
948
949fn parse_return_stmt(pair: Pair) -> Result<ReturnStmt, ParseError> {
950    let span = span_from_pair(&pair);
951    let mut value = None;
952
953    for inner in pair.into_inner() {
954        if inner.as_rule() == Rule::expr {
955            value = Some(parse_expr(inner)?);
956        }
957    }
958
959    Ok(ReturnStmt { value, span })
960}
961
962fn parse_if_stmt(pair: Pair) -> Result<IfStmt, ParseError> {
963    let span = span_from_pair(&pair);
964    let mut condition = None;
965    let mut then_block = None;
966    let mut else_branch = None;
967
968    for inner in pair.into_inner() {
969        match inner.as_rule() {
970            Rule::expr => condition = Some(parse_expr(inner)?),
971            Rule::block => {
972                if then_block.is_none() {
973                    then_block = Some(parse_block(inner)?);
974                } else {
975                    else_branch = Some(ElseBranch::Else(parse_block(inner)?));
976                }
977            }
978            Rule::if_stmt => {
979                else_branch = Some(ElseBranch::ElseIf(Box::new(parse_if_stmt(inner)?)));
980            }
981            _ => {}
982        }
983    }
984
985    Ok(IfStmt {
986        condition: condition.unwrap(),
987        then_block: then_block.unwrap(),
988        else_branch,
989        span,
990    })
991}
992
993fn parse_while_stmt(pair: Pair) -> Result<WhileStmt, ParseError> {
994    let span = span_from_pair(&pair);
995    let mut condition = None;
996    let mut body = None;
997
998    for inner in pair.into_inner() {
999        match inner.as_rule() {
1000            Rule::expr => condition = Some(parse_expr(inner)?),
1001            Rule::block => body = Some(parse_block(inner)?),
1002            _ => {}
1003        }
1004    }
1005
1006    Ok(WhileStmt {
1007        condition: condition.unwrap(),
1008        body: body.unwrap(),
1009        span,
1010    })
1011}
1012
1013fn parse_for_stmt(pair: Pair) -> Result<ForStmt, ParseError> {
1014    let span = span_from_pair(&pair);
1015    let mut init = None;
1016    let mut condition = None;
1017    let mut update = None;
1018    let mut body = None;
1019
1020    let mut expr_count = 0;
1021
1022    for inner in pair.into_inner() {
1023        match inner.as_rule() {
1024            Rule::for_init => {
1025                let init_inner = inner.into_inner().next().unwrap();
1026                match init_inner.as_rule() {
1027                    Rule::var_decl_stmt_no_semi => {
1028                        init = Some(ForInit::VarDecl(parse_var_decl_stmt_no_semi(init_inner)?));
1029                    }
1030                    Rule::expr => {
1031                        init = Some(ForInit::Expr(parse_expr(init_inner)?));
1032                    }
1033                    _ => {}
1034                }
1035            }
1036            Rule::expr => {
1037                if expr_count == 0 {
1038                    condition = Some(parse_expr(inner)?);
1039                } else {
1040                    update = Some(parse_expr(inner)?);
1041                }
1042                expr_count += 1;
1043            }
1044            Rule::block => body = Some(parse_block(inner)?),
1045            _ => {}
1046        }
1047    }
1048
1049    Ok(ForStmt {
1050        init,
1051        condition,
1052        update,
1053        body: body.unwrap(),
1054        span,
1055    })
1056}
1057
1058fn parse_var_decl_stmt_no_semi(pair: Pair) -> Result<VarDeclStmt, ParseError> {
1059    let span = span_from_pair(&pair);
1060    let mut ty = None;
1061    let mut storage_location = None;
1062    let mut name = None;
1063    let mut initializer = None;
1064
1065    for inner in pair.into_inner() {
1066        match inner.as_rule() {
1067            Rule::type_expr => ty = Some(parse_type_expr(inner)?),
1068            Rule::storage_location => storage_location = Some(parse_storage_location(inner)),
1069            Rule::ident => name = Some(parse_ident(inner)),
1070            Rule::expr => initializer = Some(parse_expr(inner)?),
1071            _ => {}
1072        }
1073    }
1074
1075    Ok(VarDeclStmt {
1076        ty: ty.unwrap(),
1077        storage_location,
1078        name: name.unwrap(),
1079        initializer,
1080        span,
1081    })
1082}
1083
1084fn parse_emit_stmt(pair: Pair) -> Result<EmitStmt, ParseError> {
1085    let span = span_from_pair(&pair);
1086    let mut event = None;
1087    let mut args = Vec::new();
1088
1089    for inner in pair.into_inner() {
1090        match inner.as_rule() {
1091            Rule::ident => event = Some(parse_ident(inner)),
1092            Rule::arg_list => args = parse_arg_list(inner)?,
1093            _ => {}
1094        }
1095    }
1096
1097    Ok(EmitStmt {
1098        event: event.unwrap(),
1099        args,
1100        span,
1101    })
1102}
1103
1104fn parse_require_stmt(pair: Pair) -> Result<RequireStmt, ParseError> {
1105    let span = span_from_pair(&pair);
1106    let mut condition = None;
1107    let mut message = None;
1108
1109    for inner in pair.into_inner() {
1110        match inner.as_rule() {
1111            Rule::expr => condition = Some(parse_expr(inner)?),
1112            Rule::string_lit => message = Some(parse_string_content(inner.as_str())),
1113            _ => {}
1114        }
1115    }
1116
1117    Ok(RequireStmt {
1118        condition: condition.unwrap(),
1119        message,
1120        span,
1121    })
1122}
1123
1124fn parse_revert_stmt(pair: Pair) -> Result<RevertStmt, ParseError> {
1125    let span = span_from_pair(&pair);
1126
1127    for inner in pair.into_inner() {
1128        match inner.as_rule() {
1129            Rule::revert_with_error => {
1130                // revert ErrorName(args)
1131                let mut inner_pairs = inner.into_inner();
1132                let name = parse_ident(inner_pairs.next().unwrap());
1133                let args = if let Some(arg_list) = inner_pairs.next() {
1134                    parse_arg_list(arg_list)?
1135                } else {
1136                    Vec::new()
1137                };
1138                return Ok(RevertStmt {
1139                    kind: RevertKind::Error { name, args },
1140                    span,
1141                });
1142            }
1143            Rule::revert_with_message => {
1144                // revert("message") or revert()
1145                let message = inner
1146                    .into_inner()
1147                    .next()
1148                    .map(|s| parse_string_content(s.as_str()));
1149                return Ok(RevertStmt {
1150                    kind: RevertKind::Message(message),
1151                    span,
1152                });
1153            }
1154            _ => {}
1155        }
1156    }
1157
1158    // Default to empty message
1159    Ok(RevertStmt {
1160        kind: RevertKind::Message(None),
1161        span,
1162    })
1163}
1164
1165fn parse_delete_stmt(pair: Pair) -> Result<DeleteStmt, ParseError> {
1166    let span = span_from_pair(&pair);
1167    let target = parse_expr(pair.into_inner().next().unwrap())?;
1168    Ok(DeleteStmt { target, span })
1169}
1170
1171fn parse_selfdestruct_stmt(pair: Pair) -> Result<SelfdestructStmt, ParseError> {
1172    let span = span_from_pair(&pair);
1173    let recipient = parse_expr(pair.into_inner().next().unwrap())?;
1174    Ok(SelfdestructStmt { recipient, span })
1175}
1176
1177fn parse_expr_stmt(pair: Pair) -> Result<ExprStmt, ParseError> {
1178    let span = span_from_pair(&pair);
1179    let expr = parse_expr(pair.into_inner().next().unwrap())?;
1180    Ok(ExprStmt { expr, span })
1181}
1182
1183// =============================================================================
1184// Expression parsing
1185// =============================================================================
1186
1187fn parse_expr(pair: Pair) -> Result<Expr, ParseError> {
1188    // expr = { ternary_expr }
1189    parse_ternary_expr(pair.into_inner().next().unwrap())
1190}
1191
1192fn parse_ternary_expr(pair: Pair) -> Result<Expr, ParseError> {
1193    let span = span_from_pair(&pair);
1194    let mut inner = pair.into_inner();
1195    let mut left = parse_assign_expr(inner.next().unwrap())?;
1196
1197    // Check for ternary: expr ? then : else
1198    if let Some(then_expr_pair) = inner.next() {
1199        let then_expr = parse_expr(then_expr_pair)?;
1200        let else_expr = parse_ternary_expr(inner.next().unwrap())?;
1201        left = Expr::Ternary(Box::new(TernaryExpr {
1202            condition: left,
1203            then_expr,
1204            else_expr,
1205            span,
1206        }));
1207    }
1208
1209    Ok(left)
1210}
1211
1212fn parse_assign_expr(pair: Pair) -> Result<Expr, ParseError> {
1213    let mut inner = pair.into_inner();
1214    let mut left = parse_or_expr(inner.next().unwrap())?;
1215
1216    while let Some(op_pair) = inner.next() {
1217        let op = match op_pair.as_str() {
1218            "=" => AssignOp::Assign,
1219            "+=" => AssignOp::AddAssign,
1220            "-=" => AssignOp::SubAssign,
1221            "*=" => AssignOp::MulAssign,
1222            "/=" => AssignOp::DivAssign,
1223            "%=" => AssignOp::RemAssign,
1224            "&=" => AssignOp::BitAndAssign,
1225            "|=" => AssignOp::BitOrAssign,
1226            "^=" => AssignOp::BitXorAssign,
1227            _ => unreachable!(),
1228        };
1229        let right = parse_or_expr(inner.next().unwrap())?;
1230        let span = Span::dummy();
1231        left = Expr::Assign(Box::new(AssignExpr {
1232            target: left,
1233            op,
1234            value: right,
1235            span,
1236        }));
1237    }
1238
1239    Ok(left)
1240}
1241
1242fn parse_or_expr(pair: Pair) -> Result<Expr, ParseError> {
1243    let mut inner = pair.into_inner();
1244    let mut left = parse_and_expr(inner.next().unwrap())?;
1245
1246    for right_pair in inner {
1247        let right = parse_and_expr(right_pair)?;
1248        let span = Span::dummy();
1249        left = Expr::Binary(Box::new(BinaryExpr {
1250            left,
1251            op: BinaryOp::Or,
1252            right,
1253            span,
1254        }));
1255    }
1256
1257    Ok(left)
1258}
1259
1260fn parse_and_expr(pair: Pair) -> Result<Expr, ParseError> {
1261    let mut inner = pair.into_inner();
1262    let mut left = parse_bit_or_expr(inner.next().unwrap())?;
1263
1264    for right_pair in inner {
1265        let right = parse_bit_or_expr(right_pair)?;
1266        let span = Span::dummy();
1267        left = Expr::Binary(Box::new(BinaryExpr {
1268            left,
1269            op: BinaryOp::And,
1270            right,
1271            span,
1272        }));
1273    }
1274
1275    Ok(left)
1276}
1277
1278fn parse_bit_or_expr(pair: Pair) -> Result<Expr, ParseError> {
1279    let mut inner = pair.into_inner();
1280    let mut left = parse_bit_xor_expr(inner.next().unwrap())?;
1281
1282    for right_pair in inner {
1283        let right = parse_bit_xor_expr(right_pair)?;
1284        let span = Span::dummy();
1285        left = Expr::Binary(Box::new(BinaryExpr {
1286            left,
1287            op: BinaryOp::BitOr,
1288            right,
1289            span,
1290        }));
1291    }
1292
1293    Ok(left)
1294}
1295
1296fn parse_bit_xor_expr(pair: Pair) -> Result<Expr, ParseError> {
1297    let mut inner = pair.into_inner();
1298    let mut left = parse_bit_and_expr(inner.next().unwrap())?;
1299
1300    for right_pair in inner {
1301        let right = parse_bit_and_expr(right_pair)?;
1302        let span = Span::dummy();
1303        left = Expr::Binary(Box::new(BinaryExpr {
1304            left,
1305            op: BinaryOp::BitXor,
1306            right,
1307            span,
1308        }));
1309    }
1310
1311    Ok(left)
1312}
1313
1314fn parse_bit_and_expr(pair: Pair) -> Result<Expr, ParseError> {
1315    let mut inner = pair.into_inner();
1316    let mut left = parse_eq_expr(inner.next().unwrap())?;
1317
1318    for right_pair in inner {
1319        let right = parse_eq_expr(right_pair)?;
1320        let span = Span::dummy();
1321        left = Expr::Binary(Box::new(BinaryExpr {
1322            left,
1323            op: BinaryOp::BitAnd,
1324            right,
1325            span,
1326        }));
1327    }
1328
1329    Ok(left)
1330}
1331
1332fn parse_eq_expr(pair: Pair) -> Result<Expr, ParseError> {
1333    let mut inner = pair.into_inner();
1334    let mut left = parse_cmp_expr(inner.next().unwrap())?;
1335
1336    while let Some(op_pair) = inner.next() {
1337        let op = match op_pair.as_str() {
1338            "==" => BinaryOp::Eq,
1339            "!=" => BinaryOp::Ne,
1340            _ => unreachable!(),
1341        };
1342        let right = parse_cmp_expr(inner.next().unwrap())?;
1343        let span = Span::dummy();
1344        left = Expr::Binary(Box::new(BinaryExpr {
1345            left,
1346            op,
1347            right,
1348            span,
1349        }));
1350    }
1351
1352    Ok(left)
1353}
1354
1355fn parse_cmp_expr(pair: Pair) -> Result<Expr, ParseError> {
1356    let mut inner = pair.into_inner();
1357    let mut left = parse_shift_expr(inner.next().unwrap())?;
1358
1359    while let Some(op_pair) = inner.next() {
1360        let op = match op_pair.as_str() {
1361            "<" => BinaryOp::Lt,
1362            "<=" => BinaryOp::Le,
1363            ">" => BinaryOp::Gt,
1364            ">=" => BinaryOp::Ge,
1365            _ => unreachable!(),
1366        };
1367        let right = parse_shift_expr(inner.next().unwrap())?;
1368        let span = Span::dummy();
1369        left = Expr::Binary(Box::new(BinaryExpr {
1370            left,
1371            op,
1372            right,
1373            span,
1374        }));
1375    }
1376
1377    Ok(left)
1378}
1379
1380fn parse_shift_expr(pair: Pair) -> Result<Expr, ParseError> {
1381    let mut inner = pair.into_inner();
1382    let mut left = parse_add_expr(inner.next().unwrap())?;
1383
1384    while let Some(op_pair) = inner.next() {
1385        let op = match op_pair.as_str() {
1386            "<<" => BinaryOp::Shl,
1387            ">>" => BinaryOp::Shr,
1388            _ => unreachable!(),
1389        };
1390        let right = parse_add_expr(inner.next().unwrap())?;
1391        let span = Span::dummy();
1392        left = Expr::Binary(Box::new(BinaryExpr {
1393            left,
1394            op,
1395            right,
1396            span,
1397        }));
1398    }
1399
1400    Ok(left)
1401}
1402
1403fn parse_add_expr(pair: Pair) -> Result<Expr, ParseError> {
1404    let mut inner = pair.into_inner();
1405    let mut left = parse_mul_expr(inner.next().unwrap())?;
1406
1407    while let Some(op_pair) = inner.next() {
1408        let op = match op_pair.as_str() {
1409            "+" => BinaryOp::Add,
1410            "-" => BinaryOp::Sub,
1411            _ => unreachable!(),
1412        };
1413        let right = parse_mul_expr(inner.next().unwrap())?;
1414        let span = Span::dummy();
1415        left = Expr::Binary(Box::new(BinaryExpr {
1416            left,
1417            op,
1418            right,
1419            span,
1420        }));
1421    }
1422
1423    Ok(left)
1424}
1425
1426fn parse_mul_expr(pair: Pair) -> Result<Expr, ParseError> {
1427    let mut inner = pair.into_inner();
1428    let mut left = parse_exp_expr(inner.next().unwrap())?;
1429
1430    while let Some(op_pair) = inner.next() {
1431        let op = match op_pair.as_str() {
1432            "*" => BinaryOp::Mul,
1433            "/" => BinaryOp::Div,
1434            "%" => BinaryOp::Rem,
1435            _ => unreachable!(),
1436        };
1437        let right = parse_exp_expr(inner.next().unwrap())?;
1438        let span = Span::dummy();
1439        left = Expr::Binary(Box::new(BinaryExpr {
1440            left,
1441            op,
1442            right,
1443            span,
1444        }));
1445    }
1446
1447    Ok(left)
1448}
1449
1450fn parse_exp_expr(pair: Pair) -> Result<Expr, ParseError> {
1451    let mut inner = pair.into_inner();
1452    let left = parse_unary_expr(inner.next().unwrap())?;
1453
1454    // Exponentiation is right-associative
1455    if let Some(right_pair) = inner.next() {
1456        let right = parse_exp_expr(right_pair)?;
1457        let span = Span::dummy();
1458        return Ok(Expr::Binary(Box::new(BinaryExpr {
1459            left,
1460            op: BinaryOp::Exp,
1461            right,
1462            span,
1463        })));
1464    }
1465
1466    Ok(left)
1467}
1468
1469fn parse_unary_expr(pair: Pair) -> Result<Expr, ParseError> {
1470    let mut ops = Vec::new();
1471
1472    for inner in pair.into_inner() {
1473        match inner.as_rule() {
1474            Rule::unary_op => {
1475                let op = match inner.as_str() {
1476                    "!" => UnaryOp::Not,
1477                    "-" => UnaryOp::Neg,
1478                    "~" => UnaryOp::BitNot,
1479                    "++" => UnaryOp::PreInc,
1480                    "--" => UnaryOp::PreDec,
1481                    _ => unreachable!(),
1482                };
1483                ops.push(op);
1484            }
1485            Rule::postfix_expr => {
1486                let mut expr = parse_postfix_expr(inner)?;
1487                // Apply unary operators in reverse order
1488                for op in ops.into_iter().rev() {
1489                    let span = Span::dummy();
1490                    expr = Expr::Unary(Box::new(UnaryExpr { op, expr, span }));
1491                }
1492                return Ok(expr);
1493            }
1494            _ => {}
1495        }
1496    }
1497
1498    unreachable!()
1499}
1500
1501fn parse_postfix_expr(pair: Pair) -> Result<Expr, ParseError> {
1502    let mut inner = pair.into_inner();
1503    let mut expr = parse_primary_expr(inner.next().unwrap())?;
1504
1505    for postfix in inner {
1506        // postfix_op wraps the actual operator
1507        let op = postfix.into_inner().next().unwrap();
1508        match op.as_rule() {
1509            Rule::call_op => {
1510                let span = Span::dummy();
1511                let args = if let Some(arg_list) = op.into_inner().next() {
1512                    parse_arg_list(arg_list)?
1513                } else {
1514                    Vec::new()
1515                };
1516                expr = Expr::Call(Box::new(CallExpr {
1517                    callee: expr,
1518                    args,
1519                    span,
1520                }));
1521            }
1522            Rule::method_call_op => {
1523                let span = Span::dummy();
1524                let mut method = None;
1525                let mut generic_args = None;
1526                let mut args = Vec::new();
1527
1528                for p in op.into_inner() {
1529                    match p.as_rule() {
1530                        Rule::ident => method = Some(parse_ident(p)),
1531                        Rule::generic_args => generic_args = Some(parse_generic_args(p)?),
1532                        Rule::arg_list => args = parse_arg_list(p)?,
1533                        _ => {}
1534                    }
1535                }
1536
1537                expr = Expr::MethodCall(Box::new(MethodCallExpr {
1538                    receiver: expr,
1539                    method: method.unwrap(),
1540                    generic_args,
1541                    args,
1542                    span,
1543                }));
1544            }
1545            Rule::field_access_op => {
1546                let span = Span::dummy();
1547                let field = parse_ident(op.into_inner().next().unwrap());
1548                expr = Expr::FieldAccess(Box::new(FieldAccessExpr { expr, field, span }));
1549            }
1550            Rule::index_op => {
1551                let span = Span::dummy();
1552                let index = parse_expr(op.into_inner().next().unwrap())?;
1553                expr = Expr::Index(Box::new(IndexExpr { expr, index, span }));
1554            }
1555            Rule::increment_op => {
1556                let span = Span::dummy();
1557                let op = match op.as_str() {
1558                    "++" => UnaryOp::PostInc,
1559                    "--" => UnaryOp::PostDec,
1560                    _ => unreachable!(),
1561                };
1562                expr = Expr::Unary(Box::new(UnaryExpr { op, expr, span }));
1563            }
1564            _ => {}
1565        }
1566    }
1567
1568    Ok(expr)
1569}
1570
1571fn parse_primary_expr(pair: Pair) -> Result<Expr, ParseError> {
1572    let inner = pair.into_inner().next().unwrap();
1573
1574    match inner.as_rule() {
1575        Rule::literal => Ok(Expr::Literal(parse_literal(inner)?)),
1576        Rule::new_expr => parse_new_expr(inner),
1577        Rule::if_expr => parse_if_expr(inner),
1578        Rule::array_literal => parse_array_literal(inner),
1579        Rule::tuple_expr => parse_tuple_expr(inner),
1580        Rule::builtin_object => {
1581            // msg, block, tx - parsed as identifiers
1582            let span = span_from_pair(&inner);
1583            let name = inner.as_str();
1584            Ok(Expr::Ident(Ident::new(name, span)))
1585        }
1586        Rule::ident_expr => {
1587            let ident = parse_ident(inner.into_inner().next().unwrap());
1588            Ok(Expr::Ident(ident))
1589        }
1590        Rule::paren_expr => {
1591            let expr = parse_expr(inner.into_inner().next().unwrap())?;
1592            Ok(Expr::Paren(Box::new(expr)))
1593        }
1594        _ => unreachable!("Unexpected primary expr rule: {:?}", inner.as_rule()),
1595    }
1596}
1597
1598fn parse_new_expr(pair: Pair) -> Result<Expr, ParseError> {
1599    let span = span_from_pair(&pair);
1600    let mut ty = None;
1601    let mut args = Vec::new();
1602
1603    for inner in pair.into_inner() {
1604        match inner.as_rule() {
1605            Rule::type_path => ty = Some(parse_type_path(inner)?),
1606            Rule::arg_list => args = parse_arg_list(inner)?,
1607            _ => {}
1608        }
1609    }
1610
1611    Ok(Expr::New(Box::new(NewExpr {
1612        ty: ty.unwrap(),
1613        args,
1614        span,
1615    })))
1616}
1617
1618fn parse_if_expr(pair: Pair) -> Result<Expr, ParseError> {
1619    let span = span_from_pair(&pair);
1620    let mut condition = None;
1621    let mut then_block = None;
1622    let mut else_branch = None;
1623
1624    for inner in pair.into_inner() {
1625        match inner.as_rule() {
1626            Rule::expr => condition = Some(parse_expr(inner)?),
1627            Rule::block => {
1628                if then_block.is_none() {
1629                    then_block = Some(parse_block(inner)?);
1630                } else {
1631                    else_branch = Some(IfExprElse::Else(parse_block(inner)?));
1632                }
1633            }
1634            Rule::if_expr => {
1635                let inner_if = parse_if_expr(inner)?;
1636                if let Expr::If(if_expr) = inner_if {
1637                    else_branch = Some(IfExprElse::ElseIf(*if_expr));
1638                }
1639            }
1640            _ => {}
1641        }
1642    }
1643
1644    Ok(Expr::If(Box::new(IfExpr {
1645        condition: condition.unwrap(),
1646        then_block: then_block.unwrap(),
1647        else_branch: Box::new(else_branch.unwrap()),
1648        span,
1649    })))
1650}
1651
1652fn parse_array_literal(pair: Pair) -> Result<Expr, ParseError> {
1653    let span = span_from_pair(&pair);
1654    let mut elements = Vec::new();
1655
1656    for inner in pair.into_inner() {
1657        if inner.as_rule() == Rule::expr {
1658            elements.push(parse_expr(inner)?);
1659        }
1660    }
1661
1662    Ok(Expr::Array(ArrayExpr { elements, span }))
1663}
1664
1665fn parse_tuple_expr(pair: Pair) -> Result<Expr, ParseError> {
1666    let span = span_from_pair(&pair);
1667    let mut elements = Vec::new();
1668
1669    for inner in pair.into_inner() {
1670        if inner.as_rule() == Rule::expr {
1671            elements.push(parse_expr(inner)?);
1672        }
1673    }
1674
1675    Ok(Expr::Tuple(TupleExpr { elements, span }))
1676}
1677
1678fn parse_arg_list(pair: Pair) -> Result<Vec<Arg>, ParseError> {
1679    let mut args = Vec::new();
1680    for inner in pair.into_inner() {
1681        if inner.as_rule() == Rule::arg {
1682            args.push(parse_arg(inner)?);
1683        }
1684    }
1685    Ok(args)
1686}
1687
1688fn parse_arg(pair: Pair) -> Result<Arg, ParseError> {
1689    let span = span_from_pair(&pair);
1690    let mut name = None;
1691    let mut value = None;
1692
1693    for inner in pair.into_inner() {
1694        match inner.as_rule() {
1695            Rule::ident => name = Some(parse_ident(inner)),
1696            Rule::expr => value = Some(parse_expr(inner)?),
1697            _ => {}
1698        }
1699    }
1700
1701    // If we have both name and value, check if name is actually the value
1702    if name.is_some() && value.is_none() {
1703        let ident = name.take().unwrap();
1704        value = Some(Expr::Ident(ident));
1705    }
1706
1707    Ok(Arg {
1708        name,
1709        value: value.unwrap(),
1710        span,
1711    })
1712}
1713
1714// =============================================================================
1715// Literal parsing
1716// =============================================================================
1717
1718fn parse_literal(pair: Pair) -> Result<Literal, ParseError> {
1719    let inner = pair.into_inner().next().unwrap();
1720    let span = span_from_pair(&inner);
1721
1722    match inner.as_rule() {
1723        Rule::bool_lit => {
1724            let value = inner.as_str() == "true";
1725            Ok(Literal::Bool(value, span))
1726        }
1727        Rule::hex_string_lit => {
1728            // hex"..." format
1729            let s = inner.as_str();
1730            let hex_content = &s[4..s.len() - 1]; // Remove hex" and "
1731            Ok(Literal::HexString(SmolStr::new(hex_content), span))
1732        }
1733        Rule::string_lit => {
1734            let s = parse_string_content(inner.as_str());
1735            Ok(Literal::String(s, span))
1736        }
1737        Rule::hex_number_lit => {
1738            // 0x... format
1739            let s = inner.as_str();
1740            Ok(Literal::HexInt(SmolStr::new(s), span))
1741        }
1742        Rule::number_lit => {
1743            let s = inner.as_str();
1744            // Handle number with possible unit (wei, gwei, ether, etc.)
1745            let value: u128 = s
1746                .chars()
1747                .take_while(|c| c.is_ascii_digit())
1748                .collect::<String>()
1749                .parse()
1750                .unwrap_or(0);
1751            Ok(Literal::Int(value, span))
1752        }
1753        Rule::address_lit => {
1754            // 0x followed by 40 hex digits
1755            let s = inner.as_str();
1756            Ok(Literal::Address(SmolStr::new(s), span))
1757        }
1758        _ => unreachable!("Unexpected literal rule: {:?}", inner.as_rule()),
1759    }
1760}