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 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 }
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 if full_text != operand_text {
610 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 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, };
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 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 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 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 }
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 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 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 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 } 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 } 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 } 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 let source = "1 + 2 * 3";
1061 let result = parse_expression(source);
1062 assert!(result.is_ok());
1063
1064 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}