traverse_solidity/
parser.rs

1use crate::ast::*;
2use pest::iterators::Pair;
3use pest::Parser;
4use pest_derive::Parser;
5use std::fmt;
6use tracing::warn;
7
8#[derive(Parser)]
9#[grammar = "solidity.pest"]
10pub struct SolidityParser;
11
12#[derive(Debug)]
13pub enum SolidityParseError {
14    PestError(String),
15    EmptyInput,
16    ParseError(String),
17}
18
19impl fmt::Display for SolidityParseError {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        match self {
22            SolidityParseError::PestError(err) => write!(f, "Parser error: {}", err),
23            SolidityParseError::EmptyInput => write!(f, "Input is empty"),
24            SolidityParseError::ParseError(err) => write!(f, "Parse error: {}", err),
25        }
26    }
27}
28
29impl std::error::Error for SolidityParseError {}
30
31impl From<pest::error::Error<Rule>> for SolidityParseError {
32    fn from(error: pest::error::Error<Rule>) -> Self {
33        SolidityParseError::PestError(error.to_string())
34    }
35}
36
37pub fn parse_solidity(source: &str) -> Result<SourceUnit, SolidityParseError> {
38    if source.trim().is_empty() {
39        return Err(SolidityParseError::EmptyInput);
40    }
41
42    let pairs = SolidityParser::parse(Rule::source_unit, source)?;
43    let source_unit = pairs.peek().map(SourceUnit::from).unwrap_or_default();
44
45    Ok(source_unit)
46}
47
48pub fn parse_expression(source: &str) -> Result<Expression, SolidityParseError> {
49    if source.trim().is_empty() {
50        return Err(SolidityParseError::EmptyInput);
51    }
52
53    let pairs = SolidityParser::parse(Rule::complete_expression, source)?;
54    let expression = pairs
55        .peek()
56        .map(|pair| {
57            pair.into_inner()
58                .next()
59                .map(Expression::from)
60                .unwrap_or(Expression::Literal(Literal::Boolean(false)))
61        })
62        .ok_or_else(|| {
63            SolidityParseError::ParseError("Failed to parse complete expression".to_string())
64        })?;
65
66    Ok(expression)
67}
68
69impl From<Pair<'_, Rule>> for SourceUnit {
70    fn from(pair: Pair<'_, Rule>) -> Self {
71        let mut items = Vec::new();
72
73        for inner_pair in pair.into_inner() {
74            if inner_pair.as_rule() == Rule::EOI {
75                break;
76            }
77
78            if let Some(item) = SourceUnitItem::from_pair(inner_pair) {
79                items.push(item);
80            }
81        }
82
83        SourceUnit { items }
84    }
85}
86
87impl SourceUnitItem {
88    pub fn from_pair(pair: Pair<'_, Rule>) -> Option<Self> {
89        match pair.as_rule() {
90            Rule::pragma_directive => Some(SourceUnitItem::Pragma(PragmaDirective::from(pair))),
91            Rule::contract_definition => {
92                Some(SourceUnitItem::Contract(ContractDefinition::from(pair)))
93            }
94            Rule::struct_definition => Some(SourceUnitItem::Struct(StructDefinition::from(pair))),
95            Rule::enum_definition => Some(SourceUnitItem::Enum(EnumDefinition::from(pair))),
96            _ => None,
97        }
98    }
99}
100
101impl From<Pair<'_, Rule>> for PragmaDirective {
102    fn from(pair: Pair<'_, Rule>) -> Self {
103        let tokens = pair
104            .into_inner()
105            .filter(|p| p.as_rule() == Rule::pragma_token)
106            .map(|p| p.as_str().to_string())
107            .collect();
108
109        PragmaDirective { tokens }
110    }
111}
112
113impl From<Pair<'_, Rule>> for ContractDefinition {
114    fn from(pair: Pair<'_, Rule>) -> Self {
115        let mut is_abstract = false;
116        let mut name = String::new();
117        let inheritance = Vec::new();
118        let body = Vec::new();
119
120        if pair.as_str().trim_start().starts_with("abstract") {
121            is_abstract = true;
122        }
123
124        for inner_pair in pair.into_inner() {
125            if inner_pair.as_rule() == Rule::identifier && name.is_empty() {
126                name = inner_pair.as_str().to_string();
127            }
128        }
129
130        ContractDefinition {
131            is_abstract,
132            name,
133            inheritance,
134            body,
135        }
136    }
137}
138
139impl From<Pair<'_, Rule>> for StructDefinition {
140    fn from(pair: Pair<'_, Rule>) -> Self {
141        let mut name = String::new();
142        let mut members = Vec::new();
143
144        for inner_pair in pair.into_inner() {
145            match inner_pair.as_rule() {
146                Rule::identifier => {
147                    if name.is_empty() {
148                        name = inner_pair.as_str().to_string();
149                    }
150                }
151                Rule::struct_member => {
152                    members.push(StructMember::from(inner_pair));
153                }
154                _ => {}
155            }
156        }
157
158        StructDefinition { name, members }
159    }
160}
161
162impl From<Pair<'_, Rule>> for StructMember {
163    fn from(pair: Pair<'_, Rule>) -> Self {
164        let mut type_name = TypeName::Elementary(ElementaryTypeName::Bool);
165        let mut name = String::new();
166
167        for inner_pair in pair.into_inner() {
168            match inner_pair.as_rule() {
169                Rule::type_name => {
170                    type_name = TypeName::from(inner_pair);
171                }
172                Rule::identifier => {
173                    name = inner_pair.as_str().to_string();
174                }
175                _ => {}
176            }
177        }
178
179        StructMember { type_name, name }
180    }
181}
182
183impl From<Pair<'_, Rule>> for EnumDefinition {
184    fn from(pair: Pair<'_, Rule>) -> Self {
185        let mut name = String::new();
186        let mut values = Vec::new();
187
188        for inner_pair in pair.into_inner() {
189            if let Rule::identifier = inner_pair.as_rule() {
190                if name.is_empty() {
191                    name = inner_pair.as_str().to_string();
192                } else {
193                    values.push(inner_pair.as_str().to_string());
194                }
195            }
196        }
197
198        EnumDefinition { name, values }
199    }
200}
201
202impl From<Pair<'_, Rule>> for TypeName {
203    fn from(pair: Pair<'_, Rule>) -> Self {
204        for inner_pair in pair.into_inner() {
205            match inner_pair.as_rule() {
206                Rule::base_type_name => {
207                    return TypeName::from(inner_pair);
208                }
209                Rule::array_suffix => {
210                    // This is simplified - in a real implementation you'd handle array types properly
211                    return TypeName::Array(
212                        Box::new(TypeName::Elementary(ElementaryTypeName::Bool)),
213                        None,
214                    );
215                }
216                _ => {}
217            }
218        }
219
220        TypeName::Elementary(ElementaryTypeName::Bool)
221    }
222}
223
224impl From<Pair<'_, Rule>> for ElementaryTypeName {
225    fn from(pair: Pair<'_, Rule>) -> Self {
226        let text = pair.as_str();
227
228        if text == "address" {
229            ElementaryTypeName::Address
230        } else if text == "bool" {
231            ElementaryTypeName::Bool
232        } else if text == "string" {
233            ElementaryTypeName::String
234        } else if text == "bytes" {
235            ElementaryTypeName::Bytes
236        } else if text.starts_with("uint") {
237            let size = if text == "uint" {
238                None
239            } else {
240                text[4..].parse().ok()
241            };
242            ElementaryTypeName::UnsignedInteger(size)
243        } else if text.starts_with("int") {
244            let size = if text == "int" {
245                None
246            } else {
247                text[3..].parse().ok()
248            };
249            ElementaryTypeName::SignedInteger(size)
250        } else {
251            ElementaryTypeName::Bool // default
252        }
253    }
254}
255
256impl From<Pair<'_, Rule>> for IdentifierPath {
257    fn from(pair: Pair<'_, Rule>) -> Self {
258        let parts = pair
259            .into_inner()
260            .filter(|p| p.as_rule() == Rule::identifier)
261            .map(|p| p.as_str().to_string())
262            .collect();
263
264        IdentifierPath { parts }
265    }
266}
267
268fn parse_call_arguments(pair: Pair<'_, Rule>) -> Vec<Expression> {
269    let mut arguments = Vec::new();
270
271    for inner_pair in pair.into_inner() {
272        match inner_pair.as_rule() {
273            Rule::expression_list => {
274                for expr_pair in inner_pair.into_inner() {
275                    if expr_pair.as_rule() == Rule::expression {
276                        arguments.push(Expression::from(expr_pair));
277                    }
278                }
279            }
280            Rule::expression => {
281                arguments.push(Expression::from(inner_pair));
282            }
283            _ => {}
284        }
285    }
286
287    arguments
288}
289
290impl From<Pair<'_, Rule>> for Expression {
291    fn from(pair: Pair<'_, Rule>) -> Self {
292        match pair.as_rule() {
293            Rule::expression => {
294                if let Some(inner) = pair.into_inner().next() {
295                    Expression::from(inner)
296                } else {
297                    Expression::Literal(Literal::Boolean(false))
298                }
299            }
300            Rule::assignment_expression => {
301                let mut inner_pairs = pair.into_inner();
302                let first = inner_pairs
303                    .next()
304                    .map(Expression::from)
305                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
306
307                if let Some(op_pair) = inner_pairs.next() {
308                    let operator = AssignmentOperator::from(op_pair);
309                    let right = inner_pairs
310                        .next()
311                        .map(Expression::from)
312                        .unwrap_or(Expression::Literal(Literal::Boolean(false)));
313
314                    Expression::Assignment(AssignmentExpression {
315                        left: Box::new(first),
316                        operator,
317                        right: Box::new(right),
318                    })
319                } else {
320                    first
321                }
322            }
323            Rule::conditional_expression => {
324                let mut inner_pairs = pair.into_inner();
325                let condition = inner_pairs
326                    .next()
327                    .map(Expression::from)
328                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
329
330                if inner_pairs.peek().is_some() {
331                    let true_expr = inner_pairs
332                        .next()
333                        .map(Expression::from)
334                        .unwrap_or(Expression::Literal(Literal::Boolean(false)));
335                    let false_expr = inner_pairs
336                        .next()
337                        .map(Expression::from)
338                        .unwrap_or(Expression::Literal(Literal::Boolean(false)));
339
340                    Expression::Conditional(ConditionalExpression {
341                        condition: Box::new(condition),
342                        true_expr: Box::new(true_expr),
343                        false_expr: Box::new(false_expr),
344                    })
345                } else {
346                    condition
347                }
348            }
349            Rule::additive_expression => {
350                let mut inner_pairs = pair.into_inner();
351                let mut left = inner_pairs
352                    .next()
353                    .map(Expression::from)
354                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
355
356                while let Some(op_pair) = inner_pairs.next() {
357                    if let Some(right_pair) = inner_pairs.next() {
358                        let operator = match op_pair.as_str() {
359                            "+" => BinaryOperator::Add,
360                            "-" => BinaryOperator::Sub,
361                            _ => BinaryOperator::Add,
362                        };
363                        let right = Expression::from(right_pair);
364
365                        left = Expression::Binary(BinaryExpression {
366                            left: Box::new(left),
367                            operator,
368                            right: Box::new(right),
369                        });
370                    }
371                }
372
373                left
374            }
375            Rule::multiplicative_expression => {
376                let mut inner_pairs = pair.into_inner();
377                let mut left = inner_pairs
378                    .next()
379                    .map(Expression::from)
380                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
381
382                while let Some(op_pair) = inner_pairs.next() {
383                    if let Some(right_pair) = inner_pairs.next() {
384                        let operator = match op_pair.as_str() {
385                            "*" => BinaryOperator::Mul,
386                            "/" => BinaryOperator::Div,
387                            "%" => BinaryOperator::Mod,
388                            _ => BinaryOperator::Mul,
389                        };
390                        let right = Expression::from(right_pair);
391
392                        left = Expression::Binary(BinaryExpression {
393                            left: Box::new(left),
394                            operator,
395                            right: Box::new(right),
396                        });
397                    }
398                }
399
400                left
401            }
402            Rule::relational_expression => {
403                let mut inner_pairs = pair.into_inner();
404                let mut left = inner_pairs
405                    .next()
406                    .map(Expression::from)
407                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
408
409                while let Some(op_pair) = inner_pairs.next() {
410                    if let Some(right_pair) = inner_pairs.next() {
411                        let operator = match op_pair.as_str() {
412                            "<" => BinaryOperator::LessThan,
413                            ">" => BinaryOperator::GreaterThan,
414                            "<=" => BinaryOperator::LessThanOrEqual,
415                            ">=" => BinaryOperator::GreaterThanOrEqual,
416                            _ => BinaryOperator::GreaterThan,
417                        };
418                        let right = Expression::from(right_pair);
419
420                        left = Expression::Binary(BinaryExpression {
421                            left: Box::new(left),
422                            operator,
423                            right: Box::new(right),
424                        });
425                    }
426                }
427
428                left
429            }
430            Rule::equality_expression => {
431                let mut inner_pairs = pair.into_inner();
432                let mut left = inner_pairs
433                    .next()
434                    .map(Expression::from)
435                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
436
437                while let Some(op_pair) = inner_pairs.next() {
438                    if let Some(right_pair) = inner_pairs.next() {
439                        let operator = match op_pair.as_str() {
440                            "==" => BinaryOperator::Equal,
441                            "!=" => BinaryOperator::NotEqual,
442                            _ => BinaryOperator::Equal,
443                        };
444                        let right = Expression::from(right_pair);
445
446                        left = Expression::Binary(BinaryExpression {
447                            left: Box::new(left),
448                            operator,
449                            right: Box::new(right),
450                        });
451                    }
452                }
453
454                left
455            }
456            Rule::logical_and_expression => {
457                let mut inner_pairs = pair.into_inner();
458                let mut left = inner_pairs
459                    .next()
460                    .map(Expression::from)
461                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
462
463                while let Some(_op_pair) = inner_pairs.next() {
464                    if let Some(right_pair) = inner_pairs.next() {
465                        let right = Expression::from(right_pair);
466                        left = Expression::Binary(BinaryExpression {
467                            left: Box::new(left),
468                            operator: BinaryOperator::And,
469                            right: Box::new(right),
470                        });
471                    }
472                }
473
474                left
475            }
476            Rule::logical_or_expression => {
477                let mut inner_pairs = pair.into_inner();
478                let mut left = inner_pairs
479                    .next()
480                    .map(Expression::from)
481                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
482
483                while let Some(_op_pair) = inner_pairs.next() {
484                    if let Some(right_pair) = inner_pairs.next() {
485                        let right = Expression::from(right_pair);
486                        left = Expression::Binary(BinaryExpression {
487                            left: Box::new(left),
488                            operator: BinaryOperator::Or,
489                            right: Box::new(right),
490                        });
491                    }
492                }
493
494                left
495            }
496            Rule::bitwise_and_expression => {
497                let mut inner_pairs = pair.into_inner();
498                let mut left = inner_pairs
499                    .next()
500                    .map(Expression::from)
501                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
502
503                while let Some(_op_pair) = inner_pairs.next() {
504                    if let Some(right_pair) = inner_pairs.next() {
505                        let right = Expression::from(right_pair);
506                        left = Expression::Binary(BinaryExpression {
507                            left: Box::new(left),
508                            operator: BinaryOperator::BitAnd,
509                            right: Box::new(right),
510                        });
511                    }
512                }
513
514                left
515            }
516            Rule::bitwise_xor_expression => {
517                let mut inner_pairs = pair.into_inner();
518                let mut left = inner_pairs
519                    .next()
520                    .map(Expression::from)
521                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
522
523                while let Some(_op_pair) = inner_pairs.next() {
524                    if let Some(right_pair) = inner_pairs.next() {
525                        let right = Expression::from(right_pair);
526                        left = Expression::Binary(BinaryExpression {
527                            left: Box::new(left),
528                            operator: BinaryOperator::BitXor,
529                            right: Box::new(right),
530                        });
531                    }
532                }
533
534                left
535            }
536            Rule::bitwise_or_expression => {
537                let mut inner_pairs = pair.into_inner();
538                let mut left = inner_pairs
539                    .next()
540                    .map(Expression::from)
541                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
542
543                while let Some(_op_pair) = inner_pairs.next() {
544                    if let Some(right_pair) = inner_pairs.next() {
545                        let right = Expression::from(right_pair);
546                        left = Expression::Binary(BinaryExpression {
547                            left: Box::new(left),
548                            operator: BinaryOperator::BitOr,
549                            right: Box::new(right),
550                        });
551                    }
552                }
553
554                left
555            }
556            Rule::shift_expression => {
557                let mut inner_pairs = pair.into_inner();
558                let mut left = inner_pairs
559                    .next()
560                    .map(Expression::from)
561                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
562
563                while let Some(op_pair) = inner_pairs.next() {
564                    if let Some(right_pair) = inner_pairs.next() {
565                        let operator = match op_pair.as_str() {
566                            "<<" => BinaryOperator::ShiftLeft,
567                            ">>" => BinaryOperator::ShiftRight,
568                            ">>>" => BinaryOperator::ShiftRightArithmetic,
569                            _ => BinaryOperator::ShiftLeft,
570                        };
571                        let right = Expression::from(right_pair);
572
573                        left = Expression::Binary(BinaryExpression {
574                            left: Box::new(left),
575                            operator,
576                            right: Box::new(right),
577                        });
578                    }
579                }
580
581                left
582            }
583            Rule::exponential_expression => {
584                let mut inner_pairs = pair.into_inner();
585                let left = inner_pairs
586                    .next()
587                    .map(Expression::from)
588                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
589
590                if let Some(right_pair) = inner_pairs.next() {
591                    let right = Expression::from(right_pair);
592                    Expression::Binary(BinaryExpression {
593                        left: Box::new(left),
594                        operator: BinaryOperator::Exp,
595                        right: Box::new(right),
596                    })
597                } else {
598                    left
599                }
600            }
601            Rule::unary_expression => {
602                let full_text = pair.as_str();
603                let mut inner_pairs = pair.into_inner();
604
605                if let Some(operand_pair) = inner_pairs.next() {
606                    let operand_text = operand_pair.as_str();
607
608                    // Check if this is a prefix unary expression by comparing texts
609                    if full_text != operand_text {
610                        // This is a prefix unary expression
611                        // Extract the operator by finding what comes before the operand
612                        let operator_str = if full_text.starts_with("++")
613                            && full_text[2..].trim_start() == operand_text
614                        {
615                            "++"
616                        } else if full_text.starts_with("--")
617                            && full_text[2..].trim_start() == operand_text
618                        {
619                            "--"
620                        } else if full_text.starts_with("!")
621                            && full_text[1..].trim_start() == operand_text
622                        {
623                            "!"
624                        } else if full_text.starts_with("~")
625                            && full_text[1..].trim_start() == operand_text
626                        {
627                            "~"
628                        } else if full_text.starts_with("delete ")
629                            && full_text[7..].trim_start() == operand_text
630                        {
631                            "delete"
632                        } else if full_text.starts_with("-")
633                            && full_text[1..].trim_start() == operand_text
634                        {
635                            "-"
636                        } else if full_text.starts_with("+")
637                            && full_text[1..].trim_start() == operand_text
638                        {
639                            "+"
640                        } else {
641                            // Fallback: couldn't determine operator, treat as regular expression
642                            return Expression::from(operand_pair);
643                        };
644
645                        let operator = match operator_str {
646                            "+" => UnaryOperator::Plus,
647                            "-" => UnaryOperator::Minus,
648                            "!" => UnaryOperator::Not,
649                            "~" => UnaryOperator::BitNot,
650                            "++" => UnaryOperator::Increment,
651                            "--" => UnaryOperator::Decrement,
652                            "delete" => UnaryOperator::Delete,
653                            _ => UnaryOperator::Plus, // fallback
654                        };
655
656                        let operand = Expression::from(operand_pair);
657
658                        Expression::Unary(UnaryExpression {
659                            operator,
660                            operand: Box::new(operand),
661                            is_prefix: true,
662                        })
663                    } else {
664                        // This is not a prefix unary expression, just parse the operand
665                        Expression::from(operand_pair)
666                    }
667                } else {
668                    Expression::Literal(Literal::Boolean(false))
669                }
670            }
671            Rule::postfix_expression => {
672                let mut inner_pairs = pair.into_inner();
673                let mut expr = inner_pairs
674                    .next()
675                    .map(Expression::from)
676                    .unwrap_or(Expression::Literal(Literal::Boolean(false)));
677
678                for suffix_pair in inner_pairs {
679                    match suffix_pair.as_rule() {
680                        Rule::identifier => {
681                            expr = Expression::MemberAccess(MemberAccessExpression {
682                                object: Box::new(expr),
683                                member: suffix_pair.as_str().to_string(),
684                            });
685                        }
686                        Rule::call_argument_list => {
687                            // This is a function call: expr(args)
688                            let arguments = parse_call_arguments(suffix_pair);
689                            expr = Expression::FunctionCall(FunctionCallExpression {
690                                function: Box::new(expr),
691                                arguments,
692                            });
693                        }
694                        Rule::expression => {
695                            // This is array access: expr[index]
696                            let index = Expression::from(suffix_pair);
697                            expr = Expression::IndexAccess(IndexAccessExpression {
698                                object: Box::new(expr),
699                                index: Some(Box::new(index)),
700                            });
701                        }
702                        _ => {
703                            match suffix_pair.as_str() {
704                                "++" => {
705                                    expr = Expression::Unary(UnaryExpression {
706                                        operator: UnaryOperator::Increment,
707                                        operand: Box::new(expr),
708                                        is_prefix: false,
709                                    });
710                                }
711                                "--" => {
712                                    expr = Expression::Unary(UnaryExpression {
713                                        operator: UnaryOperator::Decrement,
714                                        operand: Box::new(expr),
715                                        is_prefix: false,
716                                    });
717                                }
718                                _ => {
719                                    // Handle other postfix operations
720                                    // For now, we'll ignore unknown postfix operations
721                                }
722                            }
723                        }
724                    }
725                }
726
727                expr
728            }
729            Rule::primary_expression => {
730                let mut inner_pairs = pair.into_inner();
731
732                if let Some(inner_pair) = inner_pairs.next() {
733                    match inner_pair.as_rule() {
734                        Rule::identifier => Expression::Identifier(inner_pair.as_str().to_string()),
735                        Rule::literal => Expression::Literal(Literal::from(inner_pair)),
736                        Rule::literal_with_sub_denomination => {
737                            Expression::Literal(Literal::from(inner_pair))
738                        }
739                        Rule::elementary_type_name => {
740                            // Type name used as expression (e.g., in type() calls)
741                            Expression::Identifier(inner_pair.as_str().to_string())
742                        }
743                        Rule::tuple_expression => {
744                            Expression::Tuple(TupleExpression::from(inner_pair))
745                        }
746                        Rule::inline_array_expression => {
747                            Expression::Array(ArrayExpression::from(inner_pair))
748                        }
749                        _ => Expression::Literal(Literal::Boolean(false)),
750                    }
751                } else {
752                    Expression::Literal(Literal::Boolean(false))
753                }
754            }
755            Rule::identifier => Expression::Identifier(pair.as_str().to_string()),
756            Rule::literal => Expression::Literal(Literal::from(pair)),
757            _ => Expression::Literal(Literal::Boolean(false)),
758        }
759    }
760}
761
762impl From<Pair<'_, Rule>> for AssignmentOperator {
763    fn from(pair: Pair<'_, Rule>) -> Self {
764        match pair.as_str() {
765            "=" => AssignmentOperator::Assign,
766            "+=" => AssignmentOperator::AddAssign,
767            "-=" => AssignmentOperator::SubAssign,
768            "*=" => AssignmentOperator::MulAssign,
769            "/=" => AssignmentOperator::DivAssign,
770            "%=" => AssignmentOperator::ModAssign,
771            "&=" => AssignmentOperator::BitAndAssign,
772            "|=" => AssignmentOperator::BitOrAssign,
773            "^=" => AssignmentOperator::BitXorAssign,
774            "<<=" => AssignmentOperator::ShiftLeftAssign,
775            ">>=" => AssignmentOperator::ShiftRightAssign,
776            ">>>=" => AssignmentOperator::ShiftRightArithmeticAssign,
777            _ => AssignmentOperator::Assign,
778        }
779    }
780}
781
782impl From<Pair<'_, Rule>> for UnaryOperator {
783    fn from(pair: Pair<'_, Rule>) -> Self {
784        match pair.as_str() {
785            "+" => UnaryOperator::Plus,
786            "-" => UnaryOperator::Minus,
787            "!" => UnaryOperator::Not,
788            "~" => UnaryOperator::BitNot,
789            "++" => UnaryOperator::Increment,
790            "--" => UnaryOperator::Decrement,
791            "delete" => UnaryOperator::Delete,
792            _ => UnaryOperator::Plus,
793        }
794    }
795}
796
797impl From<Pair<'_, Rule>> for TupleExpression {
798    fn from(pair: Pair<'_, Rule>) -> Self {
799        let elements = pair
800            .into_inner()
801            .filter(|p| p.as_rule() == Rule::expression)
802            .map(|p| Some(Expression::from(p)))
803            .collect();
804
805        TupleExpression { elements }
806    }
807}
808
809impl From<Pair<'_, Rule>> for ArrayExpression {
810    fn from(pair: Pair<'_, Rule>) -> Self {
811        let elements = pair
812            .into_inner()
813            .filter(|p| p.as_rule() == Rule::expression)
814            .map(Expression::from)
815            .collect();
816
817        ArrayExpression { elements }
818    }
819}
820
821impl Literal {
822    fn from_specific_literal_rule(pair: Pair<'_, Rule>) -> Self {
823        match pair.as_rule() {
824            Rule::boolean_literal => Literal::Boolean(pair.as_str() == "true"),
825            Rule::number_literal => Literal::Number(NumberLiteral::from(pair)),
826            Rule::string_literal => Literal::String(StringLiteral::from(pair)),
827            Rule::hex_string_literal => Literal::HexString(HexStringLiteral::from(pair)),
828            Rule::unicode_string_literal => {
829                Literal::UnicodeString(UnicodeStringLiteral::from(pair))
830            }
831            _ => {
832                warn!(
833                    "Unexpected rule in from_specific_literal_rule: {:?}",
834                    pair.as_rule()
835                );
836                Literal::Boolean(false)
837            }
838        }
839    }
840}
841
842impl From<Pair<'_, Rule>> for Literal {
843    fn from(pair: Pair<'_, Rule>) -> Self {
844        match pair.as_rule() {
845            Rule::literal => {
846                let pair_str = pair.as_str();
847                if let Some(specific_literal_pair) = pair.into_inner().next() {
848                    Literal::from_specific_literal_rule(specific_literal_pair)
849                } else {
850                    warn!("Rule::literal had no inner pair: {:?}", pair_str);
851                    Literal::Boolean(false)
852                }
853            }
854            Rule::literal_with_sub_denomination => {
855                let mut number_value = String::new();
856                let mut sub_denomination = None;
857
858                for inner_pair in pair.into_inner() {
859                    match inner_pair.as_rule() {
860                        Rule::number_literal => {
861                            number_value = inner_pair.as_str().to_string();
862                        }
863                        Rule::sub_denomination => {
864                            sub_denomination = Some(inner_pair.as_str().to_string());
865                        }
866                        _ => {}
867                    }
868                }
869
870                Literal::Number(NumberLiteral {
871                    value: number_value,
872                    sub_denomination,
873                })
874            }
875            Rule::boolean_literal => Literal::Boolean(pair.as_str() == "true"),
876            Rule::number_literal => Literal::Number(NumberLiteral::from(pair)),
877            Rule::string_literal => Literal::String(StringLiteral::from(pair)),
878            Rule::hex_string_literal => Literal::HexString(HexStringLiteral::from(pair)),
879            Rule::unicode_string_literal => {
880                Literal::UnicodeString(UnicodeStringLiteral::from(pair))
881            }
882            _ => {
883                warn!("Unexpected rule in Literal::from: {:?}", pair.as_rule());
884                Literal::Boolean(false)
885            }
886        }
887    }
888}
889
890impl From<Pair<'_, Rule>> for NumberLiteral {
891    fn from(pair: Pair<'_, Rule>) -> Self {
892        NumberLiteral {
893            value: pair.as_str().to_string(),
894            sub_denomination: None,
895        }
896    }
897}
898
899impl From<Pair<'_, Rule>> for StringLiteral {
900    fn from(pair: Pair<'_, Rule>) -> Self {
901        let value = pair.as_str().trim_matches('"').to_string();
902        StringLiteral { value }
903    }
904}
905
906impl From<Pair<'_, Rule>> for HexStringLiteral {
907    fn from(pair: Pair<'_, Rule>) -> Self {
908        let value = pair.as_str().to_string();
909        HexStringLiteral { value }
910    }
911}
912
913impl From<Pair<'_, Rule>> for UnicodeStringLiteral {
914    fn from(pair: Pair<'_, Rule>) -> Self {
915        let value = pair.as_str().to_string();
916        UnicodeStringLiteral { value }
917    }
918}
919
920#[cfg(test)]
921mod tests {
922    use super::*;
923
924    #[test]
925    fn test_parse_pragma() {
926        let source = "pragma solidity ^0.8.0;";
927        let result = SolidityParser::parse(Rule::pragma_directive, source);
928        assert!(result.is_ok());
929    }
930
931    #[test]
932    fn test_parse_simple_expression() {
933        let source = "a + b";
934        let result = parse_expression(source);
935        assert!(result.is_ok());
936
937        if let Ok(Expression::Binary(binary)) = result {
938            assert!(matches!(binary.operator, BinaryOperator::Add));
939        } else {
940            panic!("Expected binary expression");
941        }
942    }
943
944    #[test]
945    fn test_parse_complex_expression() {
946        let source = "a + b * c";
947        let result = parse_expression(source);
948        assert!(result.is_ok());
949
950        // Should parse as: a + (b * c) due to operator precedence
951        if let Ok(Expression::Binary(binary)) = result {
952            assert!(matches!(binary.operator, BinaryOperator::Add));
953            if let Expression::Binary(right_binary) = *binary.right {
954                assert!(matches!(right_binary.operator, BinaryOperator::Mul));
955            } else {
956                panic!("Expected multiplication on the right side");
957            }
958        } else {
959            panic!("Expected binary expression");
960        }
961    }
962
963    #[test]
964    fn test_parse_comparison_expression() {
965        let source = "x > 10";
966        let result = parse_expression(source);
967        assert!(result.is_ok());
968
969        if let Ok(Expression::Binary(binary)) = result {
970            assert!(matches!(binary.operator, BinaryOperator::GreaterThan));
971        } else {
972            panic!("Expected comparison expression");
973        }
974    }
975
976    #[test]
977    fn test_parse_logical_expression() {
978        let source = "a && b || c";
979        let result = parse_expression(source);
980        assert!(result.is_ok());
981
982        // Should parse as: (a && b) || c due to operator precedence
983        if let Ok(Expression::Binary(binary)) = result {
984            assert!(matches!(binary.operator, BinaryOperator::Or));
985        } else {
986            panic!("Expected logical expression");
987        }
988    }
989
990    #[test]
991    fn test_parse_assignment_expression() {
992        let source = "x = y + z";
993        let result = parse_expression(source);
994        assert!(result.is_ok());
995
996        if let Ok(Expression::Assignment(assignment)) = result {
997            assert!(matches!(assignment.operator, AssignmentOperator::Assign));
998        } else {
999            panic!("Expected assignment expression");
1000        }
1001    }
1002
1003    #[test]
1004    fn test_parse_unary_expression() {
1005        let source = "!flag";
1006        let result = parse_expression(source);
1007        assert!(result.is_ok());
1008
1009        if let Ok(Expression::Unary(unary)) = result {
1010            assert!(matches!(unary.operator, UnaryOperator::Not));
1011            assert!(unary.is_prefix);
1012        } else {
1013            panic!("Expected unary expression");
1014        }
1015    }
1016
1017    #[test]
1018    fn test_parse_literal_expressions() {
1019        let result = parse_expression("true");
1020        assert!(result.is_ok());
1021        if let Ok(Expression::Literal(Literal::Boolean(true))) = result {
1022            // Success
1023        } else {
1024            panic!("Expected boolean literal");
1025        }
1026
1027        let result = parse_expression("42");
1028        assert!(result.is_ok());
1029        if let Ok(Expression::Literal(Literal::Number(_))) = result {
1030            // Success
1031        } else {
1032            panic!("Expected number literal");
1033        }
1034
1035        let result = parse_expression("\"hello\"");
1036        assert!(result.is_ok());
1037        if let Ok(Expression::Literal(Literal::String(_))) = result {
1038            // Success
1039        } else {
1040            panic!("Expected string literal");
1041        }
1042    }
1043
1044    #[test]
1045    fn test_parse_identifier_expression() {
1046        let source = "myVariable";
1047        let result = parse_expression(source);
1048        assert!(result.is_ok());
1049
1050        if let Ok(Expression::Identifier(name)) = result {
1051            assert_eq!(name, "myVariable");
1052        } else {
1053            panic!("Expected identifier expression");
1054        }
1055    }
1056
1057    #[test]
1058    fn test_operator_precedence() {
1059        // Test that multiplication has higher precedence than addition
1060        let source = "1 + 2 * 3";
1061        let result = parse_expression(source);
1062        assert!(result.is_ok());
1063
1064        // Should parse as: 1 + (2 * 3)
1065        if let Ok(Expression::Binary(binary)) = result {
1066            assert!(matches!(binary.operator, BinaryOperator::Add));
1067            if let Expression::Binary(right_binary) = *binary.right {
1068                assert!(matches!(right_binary.operator, BinaryOperator::Mul));
1069            } else {
1070                panic!("Expected multiplication on the right side");
1071            }
1072        } else {
1073            panic!("Expected binary expression");
1074        }
1075    }
1076
1077    #[test]
1078    fn test_parse_empty_input() {
1079        let result = parse_expression("");
1080        assert!(result.is_err());
1081        assert!(matches!(result, Err(SolidityParseError::EmptyInput)));
1082    }
1083}