1use super::ast::{
33 BinaryOp, ContractNode, Expression, MethodNode, ParamNode, PrimitiveTypeName, PropertyNode,
34 SourceLocation, Statement, TypeNode, UnaryOp, Visibility,
35};
36use super::diagnostic::Diagnostic;
37use super::parser::ParseResult;
38
39pub fn parse_solidity(source: &str, file_name: Option<&str>) -> ParseResult {
45 let file = file_name.unwrap_or("contract.runar.sol");
46 let mut errors: Vec<Diagnostic> = Vec::new();
47
48 let tokens = tokenize(source);
49 let mut parser = SolParser::new(tokens, file, &mut errors);
50
51 let contract = parser.parse_contract();
52
53 ParseResult {
54 contract,
55 errors,
56 }
57}
58
59#[derive(Debug, Clone, PartialEq)]
64enum Token {
65 Contract,
67 Is,
68 Immutable,
69 Constructor,
70 Function,
71 Public,
72 Private,
73 If,
74 Else,
75 For,
76 Return,
77 Require,
78 Let,
79 Const,
80 True,
81 False,
82
83 Ident(String),
85 NumberLit(i64),
86 StringLit(String),
87
88 Plus,
90 Minus,
91 Star,
92 Slash,
93 Percent,
94 EqEq, NotEq, EqEqEq, NotEqEq, Lt,
99 Le,
100 Gt,
101 Ge,
102 And, Or, BitAnd, BitOr, BitXor, Not, Tilde, Eq, PlusEq, MinusEq, StarEq, SlashEq, PercentEq, PlusPlus, MinusMinus, LParen,
120 RParen,
121 LBrace,
122 RBrace,
123 LBracket,
124 RBracket,
125 Semicolon,
126 Comma,
127 Dot,
128 Colon,
129 Question,
130
131 Eof,
133}
134
135fn tokenize(source: &str) -> Vec<Token> {
136 let mut tokens = Vec::new();
137 let chars: Vec<char> = source.chars().collect();
138 let len = chars.len();
139 let mut i = 0;
140
141 while i < len {
142 let ch = chars[i];
143
144 if ch.is_whitespace() {
146 i += 1;
147 continue;
148 }
149
150 if ch == '/' && i + 1 < len && chars[i + 1] == '/' {
152 while i < len && chars[i] != '\n' {
153 i += 1;
154 }
155 continue;
156 }
157
158 if ch == '/' && i + 1 < len && chars[i + 1] == '*' {
160 i += 2;
161 while i + 1 < len && !(chars[i] == '*' && chars[i + 1] == '/') {
162 i += 1;
163 }
164 if i + 1 < len {
165 i += 2;
166 }
167 continue;
168 }
169
170 if ch == '=' && i + 2 < len && chars[i + 1] == '=' && chars[i + 2] == '=' {
172 tokens.push(Token::EqEqEq);
173 i += 3;
174 continue;
175 }
176 if ch == '!' && i + 2 < len && chars[i + 1] == '=' && chars[i + 2] == '=' {
177 tokens.push(Token::NotEqEq);
178 i += 3;
179 continue;
180 }
181 if ch == '=' && i + 1 < len && chars[i + 1] == '=' {
182 tokens.push(Token::EqEq);
183 i += 2;
184 continue;
185 }
186 if ch == '!' && i + 1 < len && chars[i + 1] == '=' {
187 tokens.push(Token::NotEq);
188 i += 2;
189 continue;
190 }
191 if ch == '<' && i + 1 < len && chars[i + 1] == '=' {
192 tokens.push(Token::Le);
193 i += 2;
194 continue;
195 }
196 if ch == '>' && i + 1 < len && chars[i + 1] == '=' {
197 tokens.push(Token::Ge);
198 i += 2;
199 continue;
200 }
201 if ch == '&' && i + 1 < len && chars[i + 1] == '&' {
202 tokens.push(Token::And);
203 i += 2;
204 continue;
205 }
206 if ch == '|' && i + 1 < len && chars[i + 1] == '|' {
207 tokens.push(Token::Or);
208 i += 2;
209 continue;
210 }
211 if ch == '+' && i + 1 < len && chars[i + 1] == '+' {
212 tokens.push(Token::PlusPlus);
213 i += 2;
214 continue;
215 }
216 if ch == '-' && i + 1 < len && chars[i + 1] == '-' {
217 tokens.push(Token::MinusMinus);
218 i += 2;
219 continue;
220 }
221 if ch == '+' && i + 1 < len && chars[i + 1] == '=' {
222 tokens.push(Token::PlusEq);
223 i += 2;
224 continue;
225 }
226 if ch == '-' && i + 1 < len && chars[i + 1] == '=' {
227 tokens.push(Token::MinusEq);
228 i += 2;
229 continue;
230 }
231 if ch == '*' && i + 1 < len && chars[i + 1] == '=' {
232 tokens.push(Token::StarEq);
233 i += 2;
234 continue;
235 }
236 if ch == '/' && i + 1 < len && chars[i + 1] == '=' {
237 tokens.push(Token::SlashEq);
238 i += 2;
239 continue;
240 }
241 if ch == '%' && i + 1 < len && chars[i + 1] == '=' {
242 tokens.push(Token::PercentEq);
243 i += 2;
244 continue;
245 }
246
247 match ch {
249 '+' => { tokens.push(Token::Plus); i += 1; continue; }
250 '-' => { tokens.push(Token::Minus); i += 1; continue; }
251 '*' => { tokens.push(Token::Star); i += 1; continue; }
252 '/' => { tokens.push(Token::Slash); i += 1; continue; }
253 '%' => { tokens.push(Token::Percent); i += 1; continue; }
254 '<' => { tokens.push(Token::Lt); i += 1; continue; }
255 '>' => { tokens.push(Token::Gt); i += 1; continue; }
256 '!' => { tokens.push(Token::Not); i += 1; continue; }
257 '~' => { tokens.push(Token::Tilde); i += 1; continue; }
258 '&' => { tokens.push(Token::BitAnd); i += 1; continue; }
259 '|' => { tokens.push(Token::BitOr); i += 1; continue; }
260 '^' => { tokens.push(Token::BitXor); i += 1; continue; }
261 '=' => { tokens.push(Token::Eq); i += 1; continue; }
262 '(' => { tokens.push(Token::LParen); i += 1; continue; }
263 ')' => { tokens.push(Token::RParen); i += 1; continue; }
264 '{' => { tokens.push(Token::LBrace); i += 1; continue; }
265 '}' => { tokens.push(Token::RBrace); i += 1; continue; }
266 '[' => { tokens.push(Token::LBracket); i += 1; continue; }
267 ']' => { tokens.push(Token::RBracket); i += 1; continue; }
268 ';' => { tokens.push(Token::Semicolon); i += 1; continue; }
269 ',' => { tokens.push(Token::Comma); i += 1; continue; }
270 '.' => { tokens.push(Token::Dot); i += 1; continue; }
271 ':' => { tokens.push(Token::Colon); i += 1; continue; }
272 '?' => { tokens.push(Token::Question); i += 1; continue; }
273 _ => {}
274 }
275
276 if ch == '\'' || ch == '"' {
278 let quote = ch;
279 i += 1;
280 let start = i;
281 while i < len && chars[i] != quote {
282 if chars[i] == '\\' {
283 i += 1; }
285 i += 1;
286 }
287 let val: String = chars[start..i].iter().collect();
288 tokens.push(Token::StringLit(val));
289 if i < len {
290 i += 1;
291 }
292 continue;
293 }
294
295 if ch.is_ascii_digit() {
297 let start = i;
298 while i < len && (chars[i].is_ascii_digit() || chars[i] == 'n') {
299 i += 1;
300 }
301 let num_str: String = chars[start..i].iter().collect();
302 let num_str = num_str.trim_end_matches('n');
303 let val = num_str.parse::<i64>().unwrap_or(0);
304 tokens.push(Token::NumberLit(val));
305 continue;
306 }
307
308 if ch.is_ascii_alphabetic() || ch == '_' {
310 let start = i;
311 while i < len && (chars[i].is_ascii_alphanumeric() || chars[i] == '_') {
312 i += 1;
313 }
314 let word: String = chars[start..i].iter().collect();
315 let tok = match word.as_str() {
316 "contract" => Token::Contract,
317 "is" => Token::Is,
318 "immutable" => Token::Immutable,
319 "constructor" => Token::Constructor,
320 "function" => Token::Function,
321 "public" => Token::Public,
322 "private" => Token::Private,
323 "if" => Token::If,
324 "else" => Token::Else,
325 "for" => Token::For,
326 "return" => Token::Return,
327 "require" => Token::Require,
328 "let" => Token::Let,
329 "const" => Token::Const,
330 "true" => Token::True,
331 "false" => Token::False,
332 _ => Token::Ident(word),
333 };
334 tokens.push(tok);
335 continue;
336 }
337
338 i += 1;
340 }
341
342 tokens.push(Token::Eof);
343 tokens
344}
345
346struct SolParser<'a> {
351 tokens: Vec<Token>,
352 pos: usize,
353 file: &'a str,
354 errors: &'a mut Vec<Diagnostic>,
355}
356
357impl<'a> SolParser<'a> {
358 fn new(tokens: Vec<Token>, file: &'a str, errors: &'a mut Vec<Diagnostic>) -> Self {
359 Self {
360 tokens,
361 pos: 0,
362 file,
363 errors,
364 }
365 }
366
367 fn peek(&self) -> &Token {
368 self.tokens.get(self.pos).unwrap_or(&Token::Eof)
369 }
370
371 fn advance(&mut self) -> Token {
372 let t = self.tokens.get(self.pos).cloned().unwrap_or(Token::Eof);
373 self.pos += 1;
374 t
375 }
376
377 fn expect(&mut self, expected: &Token) -> bool {
378 if self.peek() == expected {
379 self.advance();
380 true
381 } else {
382 self.errors.push(Diagnostic::error(format!(
383 "Expected {:?}, got {:?}",
384 expected,
385 self.peek()
386 ), None));
387 false
388 }
389 }
390
391 fn expect_ident(&mut self) -> String {
392 match self.advance() {
393 Token::Ident(name) => name,
394 other => {
395 self.errors
396 .push(Diagnostic::error(format!("Expected identifier, got {:?}", other), None));
397 "_error".to_string()
398 }
399 }
400 }
401
402 fn loc(&self) -> SourceLocation {
403 SourceLocation {
404 file: self.file.to_string(),
405 line: 1,
406 column: 0,
407 }
408 }
409
410 fn parse_contract(&mut self) -> Option<ContractNode> {
415 while *self.peek() != Token::Contract && *self.peek() != Token::Eof {
417 self.advance();
418 }
419
420 if *self.peek() == Token::Eof {
421 self.errors
422 .push(Diagnostic::error("No 'contract' declaration found", None));
423 return None;
424 }
425
426 self.expect(&Token::Contract);
427 let name = self.expect_ident();
428
429 let parent_class = if *self.peek() == Token::Is {
431 self.advance();
432 self.expect_ident()
433 } else {
434 "SmartContract".to_string()
435 };
436
437 self.expect(&Token::LBrace);
438
439 let mut properties = Vec::new();
440 let mut constructor: Option<MethodNode> = None;
441 let mut methods = Vec::new();
442
443 while *self.peek() != Token::RBrace && *self.peek() != Token::Eof {
444 match self.peek().clone() {
445 Token::Constructor => {
446 constructor = Some(self.parse_constructor());
447 }
448 Token::Function => {
449 methods.push(self.parse_function());
450 }
451 Token::Immutable => {
452 properties.push(self.parse_property(true));
453 }
454 Token::Ident(_) => {
455 properties.push(self.parse_property(false));
457 }
458 _ => {
459 self.errors.push(Diagnostic::error(format!(
460 "Unexpected token in contract body: {:?}",
461 self.peek()
462 ), None));
463 self.advance();
464 }
465 }
466 }
467
468 self.expect(&Token::RBrace);
469
470 let constructor = constructor.unwrap_or_else(|| {
471 self.errors
472 .push(Diagnostic::error("Contract must have a constructor", None));
473 MethodNode {
474 name: "constructor".to_string(),
475 params: Vec::new(),
476 body: Vec::new(),
477 visibility: Visibility::Public,
478 source_location: self.loc(),
479 }
480 });
481
482 Some(ContractNode {
483 name,
484 parent_class,
485 properties,
486 constructor,
487 methods,
488 source_file: self.file.to_string(),
489 })
490 }
491
492 fn parse_property(&mut self, is_immutable: bool) -> PropertyNode {
497 if is_immutable {
498 self.advance(); }
500
501 let type_node = self.parse_type();
502 let name = self.expect_ident();
503
504 let initializer = if *self.peek() == Token::Eq {
506 self.advance(); Some(self.parse_expression())
508 } else {
509 None
510 };
511
512 self.expect(&Token::Semicolon);
513
514 PropertyNode {
515 name,
516 prop_type: type_node,
517 readonly: is_immutable,
518 initializer,
519 source_location: self.loc(),
520 }
521 }
522
523 fn parse_type(&mut self) -> TypeNode {
528 let name = self.expect_ident();
529
530 if name == "FixedArray" {
532 if *self.peek() == Token::Lt {
533 self.advance(); let element = self.parse_type();
535 self.expect(&Token::Comma);
536 let length = match self.advance() {
537 Token::NumberLit(n) => n as usize,
538 _ => {
539 self.errors
540 .push(Diagnostic::error("FixedArray requires numeric length", None));
541 0
542 }
543 };
544 self.expect(&Token::Gt);
545 return TypeNode::FixedArray {
546 element: Box::new(element),
547 length,
548 };
549 }
550 }
551
552 let mapped = match name.as_str() {
554 "uint256" | "int256" | "uint" | "int" => "bigint",
555 "bool" => "boolean",
556 "bytes" => "ByteString",
557 "address" => "Addr",
558 _ => &name,
559 };
560
561 if let Some(prim) = PrimitiveTypeName::from_str(mapped) {
562 TypeNode::Primitive(prim)
563 } else {
564 TypeNode::Custom(mapped.to_string())
565 }
566 }
567
568 fn parse_constructor(&mut self) -> MethodNode {
573 self.advance(); self.expect(&Token::LParen);
575 let params = self.parse_param_list();
576 self.expect(&Token::RParen);
577
578 if *self.peek() == Token::Public || *self.peek() == Token::Private {
580 self.advance();
581 }
582
583 let body = self.parse_block();
584
585 MethodNode {
586 name: "constructor".to_string(),
587 params,
588 body,
589 visibility: Visibility::Public,
590 source_location: self.loc(),
591 }
592 }
593
594 fn parse_function(&mut self) -> MethodNode {
599 self.advance(); let name = self.expect_ident();
601 self.expect(&Token::LParen);
602 let params = self.parse_param_list();
603 self.expect(&Token::RParen);
604
605 let visibility = match self.peek() {
607 Token::Public => {
608 self.advance();
609 Visibility::Public
610 }
611 Token::Private => {
612 self.advance();
613 Visibility::Private
614 }
615 _ => Visibility::Public,
616 };
617
618 let body = self.parse_block();
619
620 MethodNode {
621 name,
622 params,
623 body,
624 visibility,
625 source_location: self.loc(),
626 }
627 }
628
629 fn parse_param_list(&mut self) -> Vec<ParamNode> {
634 let mut params = Vec::new();
635 if *self.peek() == Token::RParen {
636 return params;
637 }
638
639 params.push(self.parse_param());
640 while *self.peek() == Token::Comma {
641 self.advance();
642 params.push(self.parse_param());
643 }
644 params
645 }
646
647 fn parse_param(&mut self) -> ParamNode {
648 let param_type = self.parse_type();
649 let name = self.expect_ident();
650 ParamNode { name, param_type }
651 }
652
653 fn parse_block(&mut self) -> Vec<Statement> {
658 self.expect(&Token::LBrace);
659 let mut stmts = Vec::new();
660 while *self.peek() != Token::RBrace && *self.peek() != Token::Eof {
661 if let Some(stmt) = self.parse_statement() {
662 stmts.push(stmt);
663 }
664 }
665 self.expect(&Token::RBrace);
666 stmts
667 }
668
669 fn parse_statement(&mut self) -> Option<Statement> {
670 match self.peek().clone() {
671 Token::Let | Token::Const => Some(self.parse_var_decl()),
672 Token::If => Some(self.parse_if()),
673 Token::For => Some(self.parse_for()),
674 Token::Return => Some(self.parse_return()),
675 Token::Require => Some(self.parse_require()),
676 _ => {
677 let expr = self.parse_expression();
679
680 match self.peek() {
682 Token::Eq => {
683 self.advance();
684 let value = self.parse_expression();
685 self.expect(&Token::Semicolon);
686 Some(Statement::Assignment {
687 target: expr,
688 value,
689 source_location: self.loc(),
690 })
691 }
692 Token::PlusEq => {
693 self.advance();
694 let rhs = self.parse_expression();
695 let value = Expression::BinaryExpr {
696 op: BinaryOp::Add,
697 left: Box::new(expr.clone()),
698 right: Box::new(rhs),
699 };
700 self.expect(&Token::Semicolon);
701 Some(Statement::Assignment {
702 target: expr,
703 value,
704 source_location: self.loc(),
705 })
706 }
707 Token::MinusEq => {
708 self.advance();
709 let rhs = self.parse_expression();
710 let value = Expression::BinaryExpr {
711 op: BinaryOp::Sub,
712 left: Box::new(expr.clone()),
713 right: Box::new(rhs),
714 };
715 self.expect(&Token::Semicolon);
716 Some(Statement::Assignment {
717 target: expr,
718 value,
719 source_location: self.loc(),
720 })
721 }
722 Token::StarEq => {
723 self.advance();
724 let rhs = self.parse_expression();
725 let value = Expression::BinaryExpr {
726 op: BinaryOp::Mul,
727 left: Box::new(expr.clone()),
728 right: Box::new(rhs),
729 };
730 self.expect(&Token::Semicolon);
731 Some(Statement::Assignment {
732 target: expr,
733 value,
734 source_location: self.loc(),
735 })
736 }
737 Token::SlashEq => {
738 self.advance();
739 let rhs = self.parse_expression();
740 let value = Expression::BinaryExpr {
741 op: BinaryOp::Div,
742 left: Box::new(expr.clone()),
743 right: Box::new(rhs),
744 };
745 self.expect(&Token::Semicolon);
746 Some(Statement::Assignment {
747 target: expr,
748 value,
749 source_location: self.loc(),
750 })
751 }
752 Token::PercentEq => {
753 self.advance();
754 let rhs = self.parse_expression();
755 let value = Expression::BinaryExpr {
756 op: BinaryOp::Mod,
757 left: Box::new(expr.clone()),
758 right: Box::new(rhs),
759 };
760 self.expect(&Token::Semicolon);
761 Some(Statement::Assignment {
762 target: expr,
763 value,
764 source_location: self.loc(),
765 })
766 }
767 _ => {
768 self.expect(&Token::Semicolon);
769 Some(Statement::ExpressionStatement {
770 expression: expr,
771 source_location: self.loc(),
772 })
773 }
774 }
775 }
776 }
777 }
778
779 fn parse_var_decl(&mut self) -> Statement {
780 let is_const = *self.peek() == Token::Const;
781 self.advance(); let (name, var_type) = if self.is_type_then_name() {
788 let type_node = self.parse_type();
789 let name = self.expect_ident();
790 (name, Some(type_node))
791 } else {
792 let name = self.expect_ident();
793 let var_type = if *self.peek() == Token::Colon {
795 self.advance();
796 Some(self.parse_type())
797 } else {
798 None
799 };
800 (name, var_type)
801 };
802
803 self.expect(&Token::Eq);
804 let init = self.parse_expression();
805 self.expect(&Token::Semicolon);
806
807 Statement::VariableDecl {
808 name,
809 var_type,
810 mutable: !is_const,
811 init,
812 source_location: self.loc(),
813 }
814 }
815
816 fn is_type_then_name(&self) -> bool {
818 matches!(
819 (self.tokens.get(self.pos), self.tokens.get(self.pos + 1)),
820 (Some(Token::Ident(_)), Some(Token::Ident(_)))
821 )
822 }
823
824 fn parse_require(&mut self) -> Statement {
825 self.advance(); self.expect(&Token::LParen);
827 let expr = self.parse_expression();
828 self.expect(&Token::RParen);
829 self.expect(&Token::Semicolon);
830
831 Statement::ExpressionStatement {
833 expression: Expression::CallExpr {
834 callee: Box::new(Expression::Identifier {
835 name: "assert".to_string(),
836 }),
837 args: vec![expr],
838 },
839 source_location: self.loc(),
840 }
841 }
842
843 fn parse_if(&mut self) -> Statement {
844 self.advance(); self.expect(&Token::LParen);
846 let condition = self.parse_expression();
847 self.expect(&Token::RParen);
848
849 let then_branch = self.parse_block();
850
851 let else_branch = if *self.peek() == Token::Else {
852 self.advance();
853 if *self.peek() == Token::If {
854 let nested = self.parse_if();
856 Some(vec![nested])
857 } else {
858 Some(self.parse_block())
859 }
860 } else {
861 None
862 };
863
864 Statement::IfStatement {
865 condition,
866 then_branch,
867 else_branch,
868 source_location: self.loc(),
869 }
870 }
871
872 fn parse_for(&mut self) -> Statement {
873 self.advance(); self.expect(&Token::LParen);
875
876 let init = if *self.peek() == Token::Let || *self.peek() == Token::Const {
878 self.parse_var_decl()
879 } else {
880 self.errors
881 .push(Diagnostic::error("For loop init must be a variable declaration", None));
882 self.expect(&Token::Semicolon);
883 Statement::VariableDecl {
884 name: "_i".to_string(),
885 var_type: None,
886 mutable: true,
887 init: Expression::BigIntLiteral { value: 0 },
888 source_location: self.loc(),
889 }
890 };
891
892 let condition = self.parse_expression();
894 self.expect(&Token::Semicolon);
895
896 let update = self.parse_for_update();
898 self.expect(&Token::RParen);
899
900 let body = self.parse_block();
901
902 Statement::ForStatement {
903 init: Box::new(init),
904 condition,
905 update: Box::new(update),
906 body,
907 source_location: self.loc(),
908 }
909 }
910
911 fn parse_for_update(&mut self) -> Statement {
912 let expr = self.parse_expression();
913
914 match self.peek() {
916 Token::Eq => {
917 self.advance();
918 let value = self.parse_expression();
919 Statement::Assignment {
920 target: expr,
921 value,
922 source_location: self.loc(),
923 }
924 }
925 Token::PlusEq => {
926 self.advance();
927 let rhs = self.parse_expression();
928 Statement::Assignment {
929 target: expr.clone(),
930 value: Expression::BinaryExpr {
931 op: BinaryOp::Add,
932 left: Box::new(expr),
933 right: Box::new(rhs),
934 },
935 source_location: self.loc(),
936 }
937 }
938 Token::MinusEq => {
939 self.advance();
940 let rhs = self.parse_expression();
941 Statement::Assignment {
942 target: expr.clone(),
943 value: Expression::BinaryExpr {
944 op: BinaryOp::Sub,
945 left: Box::new(expr),
946 right: Box::new(rhs),
947 },
948 source_location: self.loc(),
949 }
950 }
951 _ => Statement::ExpressionStatement {
952 expression: expr,
953 source_location: self.loc(),
954 },
955 }
956 }
957
958 fn parse_return(&mut self) -> Statement {
959 self.advance(); if *self.peek() == Token::Semicolon {
961 self.advance();
962 return Statement::ReturnStatement {
963 value: None,
964 source_location: self.loc(),
965 };
966 }
967 let value = self.parse_expression();
968 self.expect(&Token::Semicolon);
969 Statement::ReturnStatement {
970 value: Some(value),
971 source_location: self.loc(),
972 }
973 }
974
975 fn parse_expression(&mut self) -> Expression {
980 self.parse_ternary()
981 }
982
983 fn parse_ternary(&mut self) -> Expression {
984 let cond = self.parse_or();
985 if *self.peek() == Token::Question {
986 self.advance();
987 let cons = self.parse_ternary();
988 self.expect(&Token::Colon);
989 let alt = self.parse_ternary();
990 Expression::TernaryExpr {
991 condition: Box::new(cond),
992 consequent: Box::new(cons),
993 alternate: Box::new(alt),
994 }
995 } else {
996 cond
997 }
998 }
999
1000 fn parse_or(&mut self) -> Expression {
1001 let mut left = self.parse_and();
1002 while *self.peek() == Token::Or {
1003 self.advance();
1004 let right = self.parse_and();
1005 left = Expression::BinaryExpr {
1006 op: BinaryOp::Or,
1007 left: Box::new(left),
1008 right: Box::new(right),
1009 };
1010 }
1011 left
1012 }
1013
1014 fn parse_and(&mut self) -> Expression {
1015 let mut left = self.parse_bit_or();
1016 while *self.peek() == Token::And {
1017 self.advance();
1018 let right = self.parse_bit_or();
1019 left = Expression::BinaryExpr {
1020 op: BinaryOp::And,
1021 left: Box::new(left),
1022 right: Box::new(right),
1023 };
1024 }
1025 left
1026 }
1027
1028 fn parse_bit_or(&mut self) -> Expression {
1029 let mut left = self.parse_bit_xor();
1030 while *self.peek() == Token::BitOr {
1031 self.advance();
1032 let right = self.parse_bit_xor();
1033 left = Expression::BinaryExpr {
1034 op: BinaryOp::BitOr,
1035 left: Box::new(left),
1036 right: Box::new(right),
1037 };
1038 }
1039 left
1040 }
1041
1042 fn parse_bit_xor(&mut self) -> Expression {
1043 let mut left = self.parse_bit_and();
1044 while *self.peek() == Token::BitXor {
1045 self.advance();
1046 let right = self.parse_bit_and();
1047 left = Expression::BinaryExpr {
1048 op: BinaryOp::BitXor,
1049 left: Box::new(left),
1050 right: Box::new(right),
1051 };
1052 }
1053 left
1054 }
1055
1056 fn parse_bit_and(&mut self) -> Expression {
1057 let mut left = self.parse_equality();
1058 while *self.peek() == Token::BitAnd {
1059 self.advance();
1060 let right = self.parse_equality();
1061 left = Expression::BinaryExpr {
1062 op: BinaryOp::BitAnd,
1063 left: Box::new(left),
1064 right: Box::new(right),
1065 };
1066 }
1067 left
1068 }
1069
1070 fn parse_equality(&mut self) -> Expression {
1071 let mut left = self.parse_comparison();
1072 loop {
1073 match self.peek() {
1074 Token::EqEq | Token::EqEqEq => {
1075 self.advance();
1076 let right = self.parse_comparison();
1077 left = Expression::BinaryExpr {
1078 op: BinaryOp::StrictEq,
1079 left: Box::new(left),
1080 right: Box::new(right),
1081 };
1082 }
1083 Token::NotEq | Token::NotEqEq => {
1084 self.advance();
1085 let right = self.parse_comparison();
1086 left = Expression::BinaryExpr {
1087 op: BinaryOp::StrictNe,
1088 left: Box::new(left),
1089 right: Box::new(right),
1090 };
1091 }
1092 _ => break,
1093 }
1094 }
1095 left
1096 }
1097
1098 fn parse_comparison(&mut self) -> Expression {
1099 let mut left = self.parse_additive();
1100 loop {
1101 match self.peek() {
1102 Token::Lt => {
1103 self.advance();
1104 let right = self.parse_additive();
1105 left = Expression::BinaryExpr {
1106 op: BinaryOp::Lt,
1107 left: Box::new(left),
1108 right: Box::new(right),
1109 };
1110 }
1111 Token::Le => {
1112 self.advance();
1113 let right = self.parse_additive();
1114 left = Expression::BinaryExpr {
1115 op: BinaryOp::Le,
1116 left: Box::new(left),
1117 right: Box::new(right),
1118 };
1119 }
1120 Token::Gt => {
1121 self.advance();
1122 let right = self.parse_additive();
1123 left = Expression::BinaryExpr {
1124 op: BinaryOp::Gt,
1125 left: Box::new(left),
1126 right: Box::new(right),
1127 };
1128 }
1129 Token::Ge => {
1130 self.advance();
1131 let right = self.parse_additive();
1132 left = Expression::BinaryExpr {
1133 op: BinaryOp::Ge,
1134 left: Box::new(left),
1135 right: Box::new(right),
1136 };
1137 }
1138 _ => break,
1139 }
1140 }
1141 left
1142 }
1143
1144 fn parse_additive(&mut self) -> Expression {
1145 let mut left = self.parse_multiplicative();
1146 loop {
1147 match self.peek() {
1148 Token::Plus => {
1149 self.advance();
1150 let right = self.parse_multiplicative();
1151 left = Expression::BinaryExpr {
1152 op: BinaryOp::Add,
1153 left: Box::new(left),
1154 right: Box::new(right),
1155 };
1156 }
1157 Token::Minus => {
1158 self.advance();
1159 let right = self.parse_multiplicative();
1160 left = Expression::BinaryExpr {
1161 op: BinaryOp::Sub,
1162 left: Box::new(left),
1163 right: Box::new(right),
1164 };
1165 }
1166 _ => break,
1167 }
1168 }
1169 left
1170 }
1171
1172 fn parse_multiplicative(&mut self) -> Expression {
1173 let mut left = self.parse_unary();
1174 loop {
1175 match self.peek() {
1176 Token::Star => {
1177 self.advance();
1178 let right = self.parse_unary();
1179 left = Expression::BinaryExpr {
1180 op: BinaryOp::Mul,
1181 left: Box::new(left),
1182 right: Box::new(right),
1183 };
1184 }
1185 Token::Slash => {
1186 self.advance();
1187 let right = self.parse_unary();
1188 left = Expression::BinaryExpr {
1189 op: BinaryOp::Div,
1190 left: Box::new(left),
1191 right: Box::new(right),
1192 };
1193 }
1194 Token::Percent => {
1195 self.advance();
1196 let right = self.parse_unary();
1197 left = Expression::BinaryExpr {
1198 op: BinaryOp::Mod,
1199 left: Box::new(left),
1200 right: Box::new(right),
1201 };
1202 }
1203 _ => break,
1204 }
1205 }
1206 left
1207 }
1208
1209 fn parse_unary(&mut self) -> Expression {
1210 match self.peek() {
1211 Token::Not => {
1212 self.advance();
1213 let operand = self.parse_unary();
1214 Expression::UnaryExpr {
1215 op: UnaryOp::Not,
1216 operand: Box::new(operand),
1217 }
1218 }
1219 Token::Minus => {
1220 self.advance();
1221 let operand = self.parse_unary();
1222 Expression::UnaryExpr {
1223 op: UnaryOp::Neg,
1224 operand: Box::new(operand),
1225 }
1226 }
1227 Token::Tilde => {
1228 self.advance();
1229 let operand = self.parse_unary();
1230 Expression::UnaryExpr {
1231 op: UnaryOp::BitNot,
1232 operand: Box::new(operand),
1233 }
1234 }
1235 Token::PlusPlus => {
1236 self.advance();
1237 let operand = self.parse_postfix();
1238 Expression::IncrementExpr {
1239 operand: Box::new(operand),
1240 prefix: true,
1241 }
1242 }
1243 Token::MinusMinus => {
1244 self.advance();
1245 let operand = self.parse_postfix();
1246 Expression::DecrementExpr {
1247 operand: Box::new(operand),
1248 prefix: true,
1249 }
1250 }
1251 _ => self.parse_postfix(),
1252 }
1253 }
1254
1255 fn parse_postfix(&mut self) -> Expression {
1256 let mut expr = self.parse_primary();
1257
1258 loop {
1259 match self.peek().clone() {
1260 Token::Dot => {
1261 self.advance();
1262 let prop = self.expect_ident();
1263 if matches!(&expr, Expression::Identifier { name } if name == "this") {
1264 expr = Expression::PropertyAccess { property: prop };
1265 } else {
1266 expr = Expression::MemberExpr {
1267 object: Box::new(expr),
1268 property: prop,
1269 };
1270 }
1271 }
1272 Token::LParen => {
1273 self.advance();
1274 let mut args = Vec::new();
1275 if *self.peek() != Token::RParen {
1276 args.push(self.parse_expression());
1277 while *self.peek() == Token::Comma {
1278 self.advance();
1279 args.push(self.parse_expression());
1280 }
1281 }
1282 self.expect(&Token::RParen);
1283 expr = Expression::CallExpr {
1284 callee: Box::new(expr),
1285 args,
1286 };
1287 }
1288 Token::LBracket => {
1289 self.advance();
1290 let index = self.parse_expression();
1291 self.expect(&Token::RBracket);
1292 expr = Expression::IndexAccess {
1293 object: Box::new(expr),
1294 index: Box::new(index),
1295 };
1296 }
1297 Token::PlusPlus => {
1298 self.advance();
1299 expr = Expression::IncrementExpr {
1300 operand: Box::new(expr),
1301 prefix: false,
1302 };
1303 }
1304 Token::MinusMinus => {
1305 self.advance();
1306 expr = Expression::DecrementExpr {
1307 operand: Box::new(expr),
1308 prefix: false,
1309 };
1310 }
1311 _ => break,
1312 }
1313 }
1314
1315 expr
1316 }
1317
1318 fn parse_primary(&mut self) -> Expression {
1319 match self.advance() {
1320 Token::NumberLit(v) => Expression::BigIntLiteral { value: v },
1321 Token::True => Expression::BoolLiteral { value: true },
1322 Token::False => Expression::BoolLiteral { value: false },
1323 Token::StringLit(v) => Expression::ByteStringLiteral { value: v },
1324 Token::Ident(name) => {
1325 if name == "this" {
1326 Expression::Identifier {
1327 name: "this".to_string(),
1328 }
1329 } else if name == "super" {
1330 Expression::Identifier {
1331 name: "super".to_string(),
1332 }
1333 } else {
1334 Expression::Identifier { name }
1335 }
1336 }
1337 Token::Require => {
1338 self.expect(&Token::LParen);
1340 let arg = self.parse_expression();
1341 self.expect(&Token::RParen);
1342 Expression::CallExpr {
1343 callee: Box::new(Expression::Identifier {
1344 name: "assert".to_string(),
1345 }),
1346 args: vec![arg],
1347 }
1348 }
1349 Token::LParen => {
1350 let expr = self.parse_expression();
1351 self.expect(&Token::RParen);
1352 expr
1353 }
1354 other => {
1355 self.errors
1356 .push(Diagnostic::error(format!("Unexpected token in expression: {:?}", other), None));
1357 Expression::BigIntLiteral { value: 0 }
1358 }
1359 }
1360 }
1361}
1362
1363#[cfg(test)]
1368mod tests {
1369 use super::*;
1370
1371 #[test]
1372 fn test_parse_simple_solidity_contract() {
1373 let source = r#"
1374contract P2PKH is SmartContract {
1375 immutable Addr pubKeyHash;
1376
1377 constructor(Addr pubKeyHash) {
1378 super(pubKeyHash);
1379 this.pubKeyHash = pubKeyHash;
1380 }
1381
1382 function unlock(Sig sig, PubKey pubKey) public {
1383 require(hash160(pubKey) == this.pubKeyHash);
1384 require(checkSig(sig, pubKey));
1385 }
1386}
1387"#;
1388
1389 let result = parse_solidity(source, Some("P2PKH.runar.sol"));
1390 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1391 let contract = result.contract.unwrap();
1392 assert_eq!(contract.name, "P2PKH");
1393 assert_eq!(contract.parent_class, "SmartContract");
1394 assert_eq!(contract.properties.len(), 1);
1395 assert_eq!(contract.properties[0].name, "pubKeyHash");
1396 assert!(contract.properties[0].readonly);
1397 assert_eq!(contract.methods.len(), 1);
1398 assert_eq!(contract.methods[0].name, "unlock");
1399 assert_eq!(contract.methods[0].visibility, Visibility::Public);
1400 assert_eq!(contract.methods[0].params.len(), 2);
1401 }
1402
1403 #[test]
1404 fn test_parse_stateful_solidity_contract() {
1405 let source = r#"
1406contract Counter is StatefulSmartContract {
1407 bigint count;
1408
1409 constructor(bigint count) {
1410 super(count);
1411 this.count = count;
1412 }
1413
1414 function increment() public {
1415 this.count++;
1416 }
1417
1418 function decrement() public {
1419 require(this.count > 0);
1420 this.count--;
1421 }
1422}
1423"#;
1424
1425 let result = parse_solidity(source, Some("Counter.runar.sol"));
1426 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1427 let contract = result.contract.unwrap();
1428 assert_eq!(contract.name, "Counter");
1429 assert_eq!(contract.parent_class, "StatefulSmartContract");
1430 assert_eq!(contract.properties.len(), 1);
1431 assert!(!contract.properties[0].readonly);
1432 assert_eq!(contract.methods.len(), 2);
1433 }
1434
1435 #[test]
1436 fn test_eq_maps_to_strict_eq() {
1437 let source = r#"
1438contract Test is SmartContract {
1439 immutable bigint x;
1440
1441 constructor(bigint x) {
1442 super(x);
1443 this.x = x;
1444 }
1445
1446 function check(bigint y) public {
1447 require(this.x == y);
1448 require(this.x != y);
1449 }
1450}
1451"#;
1452
1453 let result = parse_solidity(source, Some("Test.runar.sol"));
1454 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1455 let contract = result.contract.unwrap();
1456 let body = &contract.methods[0].body;
1457 assert_eq!(body.len(), 2);
1458
1459 if let Statement::ExpressionStatement { expression, .. } = &body[0] {
1461 if let Expression::CallExpr { args, .. } = expression {
1462 if let Expression::BinaryExpr { op, .. } = &args[0] {
1463 assert_eq!(*op, BinaryOp::StrictEq);
1464 } else {
1465 panic!("Expected BinaryExpr inside assert");
1466 }
1467 } else {
1468 panic!("Expected CallExpr for assert");
1469 }
1470 }
1471 }
1472
1473 #[test]
1474 fn test_for_loop() {
1475 let source = r#"
1476contract Loop is SmartContract {
1477 immutable bigint n;
1478
1479 constructor(bigint n) {
1480 super(n);
1481 this.n = n;
1482 }
1483
1484 function run() public {
1485 let bigint sum = 0;
1486 for (let bigint i = 0; i < this.n; i++) {
1487 sum += i;
1488 }
1489 require(sum > 0);
1490 }
1491}
1492"#;
1493
1494 let result = parse_solidity(source, Some("Loop.runar.sol"));
1495 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1496 let contract = result.contract.unwrap();
1497 assert_eq!(contract.methods[0].body.len(), 3); }
1499
1500 #[test]
1505 fn test_methods_and_params() {
1506 let source = r#"
1507contract Adder is SmartContract {
1508 immutable bigint target;
1509
1510 constructor(bigint target) {
1511 super(target);
1512 this.target = target;
1513 }
1514
1515 function verify(bigint a, bigint b) public {
1516 require(a + b == this.target);
1517 }
1518}
1519"#;
1520
1521 let result = parse_solidity(source, Some("Adder.runar.sol"));
1522 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1523 let contract = result.contract.unwrap();
1524
1525 assert_eq!(contract.methods.len(), 1, "expected 1 method");
1526 let method = &contract.methods[0];
1527 assert_eq!(method.name, "verify");
1528 assert_eq!(
1529 method.visibility,
1530 Visibility::Public,
1531 "expected public visibility"
1532 );
1533 assert_eq!(method.params.len(), 2, "expected 2 params");
1534 assert_eq!(method.params[0].name, "a");
1535 assert_eq!(method.params[1].name, "b");
1536 }
1537
1538 #[test]
1543 fn test_invalid_syntax_error() {
1544 let source = r#"
1546contract {
1547 // missing name and parent
1548}
1549"#;
1550
1551 let result = parse_solidity(source, Some("bad.runar.sol"));
1552 let is_bad = !result.errors.is_empty() || result.contract.is_none();
1554 assert!(
1555 is_bad,
1556 "expected errors or no contract for invalid Solidity syntax"
1557 );
1558 }
1559
1560 #[test]
1565 fn test_multiple_properties() {
1566 let source = r#"
1567contract TwoProps is SmartContract {
1568 immutable Addr addr;
1569 immutable PubKey key;
1570
1571 constructor(Addr addr, PubKey key) {
1572 super(addr, key);
1573 this.addr = addr;
1574 this.key = key;
1575 }
1576
1577 function check(bigint x) public {
1578 require(x == 1);
1579 }
1580}
1581"#;
1582
1583 let result = parse_solidity(source, Some("TwoProps.runar.sol"));
1584 assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
1585 let contract = result.contract.unwrap();
1586 assert_eq!(
1587 contract.properties.len(),
1588 2,
1589 "expected 2 properties, got {}",
1590 contract.properties.len()
1591 );
1592 assert_eq!(contract.properties[0].name, "addr");
1593 assert_eq!(contract.properties[1].name, "key");
1594 }
1595}