1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3#![warn(unused_extern_crates)]
4#![forbid(unsafe_code)]
5
6use alloy_primitives::{U256, hex, keccak256};
7use huff_neo_utils::ast::abi::{Argument, ArgumentLocation, EventDefinition, FunctionDefinition, FunctionType};
8use huff_neo_utils::ast::huff::*;
9use huff_neo_utils::ast::span::AstSpan;
10use huff_neo_utils::bytecode::Bytes;
11use huff_neo_utils::file::remapper;
12use huff_neo_utils::{
13 error::*,
14 opcodes::Opcode,
15 prelude::{Span, str_to_bytes32},
16 token::{Token, TokenKind},
17 types::*,
18};
19
20#[derive(Debug, Clone)]
22pub struct Parser {
23 pub tokens: Vec<Token>,
25 pub cursor: usize,
27 pub current_token: Token,
29 pub base: Option<String>,
31 pub spans: Vec<Span>,
33 pub remapper: remapper::Remapper,
35 loop_variables: Vec<String>,
37}
38
39impl Parser {
40 pub fn new(tokens: Vec<Token>, base: Option<String>) -> Self {
42 let initial_token = tokens.first().unwrap().clone();
43 let remapper = remapper::Remapper::new("./");
44 Self { tokens, cursor: 0, current_token: initial_token, base, spans: vec![], remapper, loop_variables: vec![] }
45 }
46
47 pub fn reset(&mut self) {
51 self.current_token = self.tokens.first().unwrap().clone();
52 self.cursor = 0;
53 }
54
55 pub fn parse(&mut self) -> Result<Contract, ParserError> {
57 self.tokens.retain(|token| !matches!(token.kind, TokenKind::Whitespace | TokenKind::Comment(_)));
59
60 self.reset();
62
63 let mut contract = Contract::default();
65
66 while !self.check(TokenKind::Eof) {
68 self.spans = vec![];
70
71 if self.check(TokenKind::Include) {
73 contract.imports.push(self.parse_imports()?);
74 }
75 else if self.check(TokenKind::Pound) {
77 let m = self.parse_macro(&mut contract)?;
78 tracing::info!(target: "parser", "SUCCESSFULLY PARSED MACRO {}", m.name);
79 contract.macros.insert(m.name.clone(), m);
80 }
81 else if self.check(TokenKind::Define) {
83 self.match_kind(TokenKind::Define)?;
85
86 match self.current_token.kind {
88 TokenKind::Function => {
89 let func = self.parse_function()?;
90 tracing::info!(target: "parser", "SUCCESSFULLY PARSED FUNCTION {}", func.name);
91 contract.functions.push(func);
92 }
93 TokenKind::Event => {
94 let ev = self.parse_event()?;
95 tracing::info!(target: "parser", "SUCCESSFULLY PARSED EVENT {}", ev.name);
96 contract.events.push(ev);
97 }
98 TokenKind::Constant => {
99 let c = self.parse_constant()?;
100 tracing::info!(target: "parser", "SUCCESSFULLY PARSED CONSTANT {}", c.name);
101 contract.constants.lock().unwrap().push(c);
102 }
103 TokenKind::Error => {
104 let e = self.parse_custom_error()?;
105 tracing::info!(target: "parser", "SUCCESSFULLY PARSED ERROR {}", e.name);
106 contract.errors.push(e);
107 }
108 TokenKind::Macro | TokenKind::Fn => {
109 let m = self.parse_macro(&mut contract)?;
110 tracing::info!(target: "parser", "SUCCESSFULLY PARSED MACRO {}", m.name);
111 contract.macros.insert(m.name.clone(), m);
112 }
113 TokenKind::Test => {
114 let m = self.parse_macro(&mut contract)?;
115 tracing::info!(target: "parser", "SUCCESSFULLY PARSED TEST {}", m.name);
116 contract.macros.insert(m.name.clone(), m);
117 }
118 TokenKind::JumpTable | TokenKind::JumpTablePacked | TokenKind::CodeTable => {
119 contract.tables.push(self.parse_table()?);
120 }
121 _ => {
122 tracing::error!(
123 target: "parser",
124 "Invalid definition. Must be a function, event, constant, error, or macro. Got: {}",
125 self.current_token.kind
126 );
127 return Err(ParserError {
128 kind: ParserErrorKind::InvalidDefinition(self.current_token.kind.clone()),
129 hint: Some(
130 "Definition must be one of: `function`, `event`, `constant`, `error`, `macro`, `fn`, or `test`."
131 .to_string(),
132 ),
133 spans: AstSpan(vec![self.current_token.span.clone()]),
134 cursor: self.cursor,
135 });
136 }
137 };
138 } else {
139 return Err(ParserError {
141 kind: ParserErrorKind::UnexpectedType(self.current_token.kind.clone()),
142 hint: Some(format!("Expected either \"{}\" or \"{}\"", TokenKind::Define, TokenKind::Include)),
143 spans: AstSpan(vec![self.current_token.span.clone()]),
144 cursor: self.cursor,
145 });
146 }
147 }
148
149 Ok(contract)
150 }
151
152 pub fn parse_imports(&mut self) -> Result<FilePath, ParserError> {
154 self.match_kind(TokenKind::Include)?;
156
157 self.match_kind(TokenKind::Str("x".to_string()))?;
159 let tok = self.peek_behind().unwrap().kind;
160 let p = match tok {
161 TokenKind::Str(file_path) => file_path,
162 _ => {
163 tracing::error!(target: "parser", "INVALID IMPORT PATH: {}", tok);
164 let new_spans = self.spans.clone();
165 self.spans = vec![];
166 return Err(ParserError {
167 kind: ParserErrorKind::InvalidName(tok.clone()),
168 hint: Some(format!("Expected import string. Got: \"{tok}\"")),
169 spans: AstSpan(new_spans),
170 cursor: self.cursor,
171 });
172 }
173 };
174
175 Ok(std::path::PathBuf::from(p))
176 }
177
178 pub fn match_kind(&mut self, kind: TokenKind) -> Result<TokenKind, ParserError> {
180 if std::mem::discriminant(&self.current_token.kind) == std::mem::discriminant(&kind) {
181 let curr_kind: TokenKind = self.current_token.kind.clone();
182 self.consume();
183 Ok(curr_kind)
184 } else {
185 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED: {}, GOT: {}", kind, self.current_token.kind);
186 Err(ParserError {
187 kind: ParserErrorKind::UnexpectedType(self.current_token.kind.clone()),
188 hint: Some(format!("Expected: \"{kind}\"")),
189 spans: AstSpan(self.spans.clone()),
190 cursor: self.cursor,
191 })
192 }
193 }
194
195 pub fn check(&mut self, kind: TokenKind) -> bool {
197 std::mem::discriminant(&self.current_token.kind) == std::mem::discriminant(&kind)
198 }
199
200 fn check_duplicate_label(&self, contract: &mut Contract, macro_name: &str, label: String, span: Span) -> Result<(), ParserError> {
202 let key = format!("{}{macro_name}{label}", span.clone().file.map(|f| f.path.clone()).unwrap_or_default());
203
204 if contract.labels.contains(&key) {
205 tracing::error!(target: "parser", "DUPLICATED LABEL NAME: {}", label);
206 Err(ParserError {
207 kind: ParserErrorKind::DuplicateLabel(label.clone()),
208 hint: Some(format!("Duplicated label name: \"{label}\" in macro: \"{macro_name}\"")),
209 spans: AstSpan(vec![span]),
210 cursor: self.cursor,
211 })
212 } else {
213 contract.labels.insert(key);
214 Ok(())
215 }
216 }
217
218 pub fn consume(&mut self) {
220 self.spans.push(self.current_token.span.clone());
221 self.current_token = self.peek().unwrap();
222 self.cursor += 1;
223 }
224
225 pub fn consume_all(&mut self, kinds: Vec<TokenKind>) {
227 loop {
228 let token = self.peek().unwrap();
229 if !kinds.contains(&token.kind) {
230 break;
231 }
232 self.current_token = token;
233 self.cursor += 1;
234 }
235 }
236
237 pub fn peek(&mut self) -> Option<Token> {
239 if self.cursor >= self.tokens.len() { None } else { Some(self.tokens.get(self.cursor + 1).unwrap().clone()) }
240 }
241
242 pub fn peek_behind(&self) -> Option<Token> {
244 if self.cursor == 0 || self.cursor > self.tokens.len() { None } else { Some(self.tokens.get(self.cursor - 1).unwrap().clone()) }
245 }
246
247 pub fn parse_function(&mut self) -> Result<FunctionDefinition, ParserError> {
250 self.match_kind(TokenKind::Function)?;
252 self.match_kind(TokenKind::Ident("x".to_string()))?;
254 let tok = self.peek_behind().unwrap().kind;
255 let name = match tok {
256 TokenKind::Ident(fn_name) => fn_name,
257 _ => {
258 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED IDENT, GOT: {}", tok);
259 return Err(ParserError {
260 kind: ParserErrorKind::InvalidName(tok.clone()),
261 hint: Some(format!("Expected function name, found: \"{tok}\"")),
262 spans: AstSpan(self.spans.clone()),
263 cursor: self.cursor,
264 });
265 }
266 };
267
268 let inputs = self.parse_args(true, true, false)?;
270 let fn_type = match self.current_token.kind.clone() {
272 TokenKind::View => FunctionType::View,
273 TokenKind::Pure => FunctionType::Pure,
274 TokenKind::Payable => FunctionType::Payable,
275 TokenKind::NonPayable => FunctionType::NonPayable,
276 tok => {
277 return Err(ParserError {
278 kind: ParserErrorKind::UnexpectedType(tok),
279 hint: Some("Expected one of: `view`, `pure`, `payable`, `nonpayable`.".to_string()),
280 spans: AstSpan(vec![self.current_token.span.clone()]),
281 cursor: self.cursor,
282 });
283 }
284 };
285 self.consume();
287
288 self.match_kind(TokenKind::Returns)?;
290 let outputs = self.parse_args(true, true, false)?;
292
293 let input_types = inputs.iter().map(|i| i.arg_type.as_ref().unwrap().clone()).collect::<Vec<_>>();
294 let method_signature = format!("{name}({})", input_types.join(","));
295 let selector = keccak256(method_signature)[..4].try_into().unwrap();
296
297 Ok(FunctionDefinition { name, signature: selector, inputs, fn_type, outputs, span: AstSpan(self.spans.clone()) })
298 }
299
300 pub fn parse_event(&mut self) -> Result<EventDefinition, ParserError> {
302 self.match_kind(TokenKind::Event)?;
304
305 self.match_kind(TokenKind::Ident("x".to_string()))?;
307 let tok = self.peek_behind().unwrap().kind;
308
309 let name = match tok {
310 TokenKind::Ident(event_name) => event_name,
311 _ => {
312 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED IDENT, GOT: {}", tok);
313 return Err(ParserError {
314 kind: ParserErrorKind::InvalidName(tok.clone()),
315 hint: Some(format!("Expected event name, found: \"{tok}\"")),
316 spans: AstSpan(self.spans.clone()),
317 cursor: self.cursor,
318 });
319 }
320 };
321
322 let parameters = self.parse_args(true, true, true)?;
324
325 let input_types = parameters.iter().map(|i| i.arg_type.as_ref().unwrap().clone()).collect::<Vec<_>>();
326 let event_signature = format!("{name}({})", input_types.join(","));
327 let event_selector = keccak256(event_signature).0;
328
329 Ok(EventDefinition { name, parameters, span: AstSpan(self.spans.clone()), hash: event_selector })
330 }
331
332 pub fn parse_constant(&mut self) -> Result<ConstantDefinition, ParserError> {
334 self.match_kind(TokenKind::Constant)?;
336
337 if matches!(self.current_token.kind, TokenKind::Noop) {
340 tracing::error!(target: "parser", "RESERVED CONSTANT NAME: __NOOP");
341 return Err(ParserError {
342 kind: ParserErrorKind::InvalidConstantName,
343 hint: Some("__NOOP is a reserved built-in constant and cannot be used as a constant name.".to_string()),
344 spans: AstSpan(self.spans.clone()),
345 cursor: self.cursor,
346 });
347 }
348
349 self.match_kind(TokenKind::Ident("x".to_string()))?;
350 let tok = self.peek_behind().unwrap().kind;
351 let name = match tok {
352 TokenKind::Ident(const_name) => const_name,
353 _ => {
354 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED IDENT, GOT: {}", tok);
355 return Err(ParserError {
356 kind: ParserErrorKind::UnexpectedType(tok),
357 hint: Some("Expected constant name.".to_string()),
358 spans: AstSpan(self.spans.clone()),
359 cursor: self.cursor,
360 });
361 }
362 };
363
364 self.match_kind(TokenKind::Assign)?;
366
367 let value: ConstVal = match self.current_token.kind.clone() {
368 TokenKind::FreeStoragePointer => {
369 self.consume();
370 ConstVal::FreeStoragePointer(FreeStoragePointer {})
371 }
372 TokenKind::Noop => {
373 self.consume();
374 ConstVal::Noop
375 }
376 TokenKind::Str(s) => {
377 self.consume();
378 ConstVal::String(s)
379 }
380 TokenKind::BuiltinFunction(f) => {
381 let curr_spans = vec![self.current_token.span.clone()];
382 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
383 let args = self.parse_builtin_args()?;
384 ConstVal::BuiltinFunctionCall(BuiltinFunctionCall { kind: BuiltinFunctionKind::from(f), args, span: AstSpan(curr_spans) })
385 }
386 TokenKind::HexLiteral(hex_str) if !self.is_expression_context() => {
388 self.consume();
389 ConstVal::Bytes(Bytes::Raw(hex_str))
390 }
391 TokenKind::HexLiteral(_)
394 | TokenKind::Integer(_)
395 | TokenKind::OpenParen
396 | TokenKind::Sub
397 | TokenKind::Not
398 | TokenKind::OpenBracket => {
399 let expr = self.parse_constant_expression()?;
400 ConstVal::Expression(expr)
401 }
402 kind => {
403 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED FreeStoragePointer OR Hex, GOT: {}", self.current_token.kind);
404 return Err(ParserError {
405 kind: ParserErrorKind::InvalidConstantValue(kind),
406 hint: Some(
407 "Expected constant value to be Hex, decimal, arithmetic expression, or `FREE_STORAGE_POINTER()`".to_string(),
408 ),
409 spans: AstSpan(vec![self.current_token.span.clone()]),
410 cursor: self.cursor,
411 });
412 }
413 };
414
415 let new_spans = self.spans.clone();
417 self.spans = vec![];
418
419 Ok(ConstantDefinition { name, value, span: AstSpan(new_spans) })
421 }
422
423 pub fn parse_custom_error(&mut self) -> Result<ErrorDefinition, ParserError> {
425 self.match_kind(TokenKind::Error)?;
427
428 self.match_kind(TokenKind::Ident("x".to_string()))?;
430 let tok = self.peek_behind().unwrap().kind;
431 let name = match tok {
432 TokenKind::Ident(err_name) => err_name,
433 _ => {
434 tracing::error!(target: "parser", "TOKEN MISMATCH - EXPECTED IDENT, GOT: {}", tok);
435 return Err(ParserError {
436 kind: ParserErrorKind::UnexpectedType(tok),
437 hint: Some("Expected error name.".to_string()),
438 spans: AstSpan(self.spans.clone()),
439 cursor: self.cursor,
440 });
441 }
442 };
443
444 let parameters = self.parse_args(true, true, false)?;
446
447 let input_types = parameters.iter().map(|i| i.arg_type.as_ref().unwrap().clone()).collect::<Vec<_>>();
448 let method_signature = format!("{name}({})", input_types.join(","));
449 let selector = keccak256(method_signature)[..4].try_into().unwrap();
450
451 let new_spans = self.spans.clone();
453 self.spans = vec![];
454
455 Ok(ErrorDefinition { name, selector, parameters, span: AstSpan(new_spans) })
456 }
457
458 pub fn parse_decorator(&mut self) -> Result<Decorator, ParserError> {
463 let mut flags: Vec<DecoratorFlag> = Vec::default();
464
465 while self.check(TokenKind::Pound) {
466 self.match_kind(TokenKind::Pound)?;
467 self.match_kind(TokenKind::OpenBracket)?;
468
469 while !self.check(TokenKind::CloseBracket) {
470 flags.push(self.parse_decorator_flag()?);
471
472 if self.check(TokenKind::Comma) {
475 self.consume();
476 }
477 }
478
479 self.match_kind(TokenKind::CloseBracket)?;
480 }
481
482 Ok(Decorator { flags })
483 }
484
485 fn parse_decorator_flag(&mut self) -> Result<DecoratorFlag, ParserError> {
487 let TokenKind::Ident(name) = self.current_token.kind.clone() else {
488 return Err(self.decorator_error(String::from("Expected a decorator flag name")));
489 };
490 let span = AstSpan(vec![self.current_token.span.clone()]);
491 self.consume();
492
493 let mut args: Vec<DecoratorArg> = Vec::new();
494 if self.check(TokenKind::OpenParen) {
495 self.consume();
496 while !self.check(TokenKind::CloseParen) {
497 args.push(self.parse_decorator_arg(&name)?);
498
499 if self.check(TokenKind::Comma) {
500 self.consume();
501 } else if !self.check(TokenKind::CloseParen) {
502 return Err(self.decorator_error(format!("Expected `,` or `)` in the arguments of decorator flag: {name}")));
503 }
504 }
505 self.match_kind(TokenKind::CloseParen)?;
506 }
507
508 Ok(DecoratorFlag { name, args, span })
509 }
510
511 fn parse_decorator_arg(&mut self, flag: &str) -> Result<DecoratorArg, ParserError> {
513 let start_span = self.current_token.span.clone();
514
515 let mut key = None;
516 if let TokenKind::Ident(ident) = self.current_token.kind.clone()
517 && self.peek().is_some_and(|t| t.kind == TokenKind::Assign)
518 {
519 key = Some(ident);
520 self.consume();
521 self.match_kind(TokenKind::Assign)?;
522 }
523
524 let value_span = self.current_token.span.clone();
525 let value = match self.current_token.kind.clone() {
526 TokenKind::HexLiteral(hex) => {
527 self.consume();
528 DecoratorValue::Hex(hex)
529 }
530 TokenKind::Integer(int) => {
531 self.consume();
532 DecoratorValue::Int(int)
533 }
534 TokenKind::Str(s) => {
535 self.consume();
536 DecoratorValue::Str(s)
537 }
538 TokenKind::Ident(ident) => {
539 self.consume();
540 match ident.as_str() {
541 "true" => DecoratorValue::Bool(true),
542 "false" => DecoratorValue::Bool(false),
543 _ => DecoratorValue::Ident(ident),
544 }
545 }
546 TokenKind::OpenBracket => {
547 let (constant, _) = self.parse_constant_push()?;
548 DecoratorValue::Constant(constant)
549 }
550 TokenKind::BuiltinFunction(f) => {
551 self.consume();
552 let args = self.parse_builtin_args()?;
553 DecoratorValue::Builtin(BuiltinFunctionCall {
554 kind: BuiltinFunctionKind::from(f),
555 args,
556 span: AstSpan(vec![value_span.clone()]),
557 })
558 }
559 kind => {
560 return Err(ParserError {
561 kind: ParserErrorKind::InvalidDecoratorFlagArg(kind),
562 hint: Some(format!(
563 "Expected a hex or decimal literal, string, boolean, identifier, [CONSTANT] or builtin call for decorator flag: {flag}"
564 )),
565 spans: AstSpan(vec![value_span]),
566 cursor: self.cursor,
567 });
568 }
569 };
570
571 Ok(DecoratorArg { key, value, span: AstSpan(vec![self.span_from(&start_span)]) })
572 }
573
574 fn span_from(&self, start: &Span) -> Span {
576 let end = self.peek_behind().map_or(start.end, |t| t.span.end);
577 Span { start: start.start, end, file: start.file.clone() }
578 }
579
580 fn decorator_error(&self, hint: String) -> ParserError {
582 ParserError {
583 kind: ParserErrorKind::InvalidDecoratorFlag(self.current_token.kind.to_string()),
584 hint: Some(hint),
585 spans: AstSpan(vec![self.current_token.span.clone()]),
586 cursor: self.cursor,
587 }
588 }
589
590 pub fn parse_macro(&mut self, contract: &mut Contract) -> Result<MacroDefinition, ParserError> {
594 let mut decorator: Option<Decorator> = None;
595 let mut decorator_span = None;
596 if self.check(TokenKind::Pound) {
597 let start = self.current_token.span.clone();
598 decorator = Some(self.parse_decorator()?);
599 decorator_span = Some(self.span_from(&start));
600
601 self.consume();
603 }
604
605 let outlined = self.check(TokenKind::Fn);
606 let test = self.check(TokenKind::Test);
607 if !test && let Some(span) = decorator_span {
608 let name = self.peek().map(|t| t.kind.to_string()).unwrap_or_default();
609 return Err(ParserError {
610 kind: ParserErrorKind::DecoratorOnNonTest(name),
611 hint: Some(String::from("Decorators only apply to `#define test` definitions")),
612 spans: AstSpan(vec![span]),
613 cursor: self.cursor,
614 });
615 }
616
617 self.match_kind(if outlined {
618 TokenKind::Fn
619 } else if test {
620 TokenKind::Test
621 } else {
622 TokenKind::Macro
623 })?;
624
625 let macro_name: String = self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?.to_string();
626
627 if contract.macros.contains_key(¯o_name) {
629 tracing::error!(target: "parser", "DUPLICATE MACRO NAME FOUND: {}", macro_name);
630 return Err(ParserError {
631 kind: ParserErrorKind::DuplicateMacro(macro_name),
632 hint: Some("Macros, fns and tests share their names, which must be unique".to_string()),
633 spans: AstSpan(self.peek_behind().map(|token| token.span).into_iter().collect()),
634 cursor: self.cursor,
635 });
636 }
637
638 if BuiltinFunctionKind::is_reserved_name(¯o_name) {
640 tracing::error!(target: "parser", "RESERVED MACRO NAME: {}", macro_name);
641 return Err(ParserError {
642 kind: ParserErrorKind::InvalidMacroName,
643 hint: Some(format!("{} is a reserved built-in function name and cannot be used as a macro name.", macro_name)),
644 spans: AstSpan(self.spans.clone()),
645 cursor: self.cursor,
646 });
647 }
648
649 if macro_name == RUNTIME_CODESIZE_ARG {
651 tracing::error!(target: "parser", "RESERVED MACRO NAME: {RUNTIME_CODESIZE_ARG}");
652 return Err(ParserError {
653 kind: ParserErrorKind::InvalidMacroName,
654 hint: Some(format!(
655 "{RUNTIME_CODESIZE_ARG} is reserved (used by __codesize({RUNTIME_CODESIZE_ARG})) and cannot be used as a macro name."
656 )),
657 spans: AstSpan(self.spans.clone()),
658 cursor: self.cursor,
659 });
660 }
661
662 tracing::info!(target: "parser", "PARSING MACRO: \"{}\"", macro_name);
663
664 let macro_arguments = self.parse_args(true, false, false)?;
665 self.match_kind(TokenKind::Assign)?;
666
667 let macro_takes = self.match_kind(TokenKind::Takes).map_or(Ok(0), |_| self.parse_single_arg())?;
668 let macro_returns = self.match_kind(TokenKind::Returns).map_or(Ok(0), |_| self.parse_single_arg())?;
669
670 let macro_statements: Vec<Statement> = self.parse_body(¯o_name, contract)?;
671
672 Ok(MacroDefinition::new(
673 macro_name,
674 decorator,
675 macro_arguments,
676 macro_statements,
677 macro_takes,
678 macro_returns,
679 self.spans.clone(),
680 outlined,
681 test,
682 ))
683 }
684
685 fn at_opcode_operand(&self) -> bool {
687 matches!(
688 self.current_token.kind,
689 TokenKind::Integer(_) | TokenKind::HexLiteral(_) | TokenKind::OpenBracket | TokenKind::LeftAngle | TokenKind::OpenParen
690 )
691 }
692
693 fn takes_opcode_operands(&self, o: Opcode) -> bool {
696 o.has_stack_immediate() || (o.is_value_push() && !matches!(self.current_token.kind, TokenKind::HexLiteral(_)))
697 }
698
699 fn parse_opcode_operands(&mut self, o: Opcode, opcode_span: Span) -> Result<Statement, ParserError> {
706 let (operand_count, kind, hint) = if o.is_value_push() {
707 (1, ParserErrorKind::InvalidPush(o), format!("\"{o:?}\" takes one value: a literal, [CONSTANT], <arg>, or (expression)"))
708 } else {
709 (o.stack_immediate_operands(), ParserErrorKind::InvalidStackImmediate(o), o.stack_immediate_hint())
710 };
711
712 let mut operands = Vec::with_capacity(operand_count);
713 let mut spans = vec![opcode_span];
714 for _ in 0..operand_count {
715 if !self.at_opcode_operand() {
716 let found = match &self.current_token.kind {
718 TokenKind::Opcode(op) => op.as_ref().to_string(),
719 other => other.to_string(),
720 };
721 return Err(ParserError {
722 kind,
723 hint: Some(format!("{hint}, found \"{found}\"")),
724 spans: AstSpan(vec![self.current_token.span.clone()]),
725 cursor: self.cursor,
726 });
727 }
728 let operand = self.parse_primary_expression()?;
729 spans.extend_from_slice(operand.span().inner_ref());
730 operands.push(operand);
731 }
732
733 let literals: Option<Vec<U256>> = operands
735 .iter()
736 .map(|e| if let Expression::Literal { value, .. } = e { Some(U256::from_be_bytes(*value)) } else { None })
737 .collect();
738 if let Some(values) = literals
739 && let Err(hint) = o.encode_immediate(&values)
740 {
741 return Err(ParserError { kind, hint: Some(hint), spans: AstSpan(spans[1..].to_vec()), cursor: self.cursor });
742 }
743
744 tracing::info!(target: "parser", "PARSED OPCODE OPERANDS: [{:?} with {} operands]", o, operands.len());
745 Ok(Statement { ty: StatementType::ImmediateOpcode { opcode: o, operands }, span: AstSpan(spans) })
746 }
747
748 pub fn parse_body(&mut self, macro_name: &str, contract: &mut Contract) -> Result<Vec<Statement>, ParserError> {
752 let mut statements: Vec<Statement> = Vec::new();
753 self.match_kind(TokenKind::OpenBrace)?;
754 tracing::info!(target: "parser", "PARSING MACRO BODY");
755 while !self.check(TokenKind::CloseBrace) {
756 match self.current_token.kind.clone() {
757 TokenKind::HexLiteral(hex_str) => {
758 let curr_spans = vec![self.current_token.span.clone()];
759 let val = str_to_bytes32(&hex_str);
760 tracing::info!(target: "parser", "PARSING MACRO BODY: [HEX LITERAL: {}]", hex::encode(val));
761 self.consume();
762 statements.push(Statement { ty: StatementType::Literal(val), span: AstSpan(curr_spans) });
763 }
764 TokenKind::Opcode(o) => {
765 let curr_spans = vec![self.current_token.span.clone()];
766 tracing::info!(target: "parser", "PARSING MACRO BODY: [OPCODE: {}]", o);
767 self.consume();
768 if self.takes_opcode_operands(o) {
769 statements.push(self.parse_opcode_operands(o, curr_spans[0].clone())?);
770 continue;
771 }
772 statements.push(Statement { ty: StatementType::Opcode(o), span: AstSpan(curr_spans) });
773 if o.is_value_push() {
776 match self.current_token.kind.clone() {
777 TokenKind::HexLiteral(hex_str) => {
778 let curr_spans = vec![self.current_token.span.clone()];
779 let val = str_to_bytes32(&hex_str);
780 tracing::info!(target: "parser", "PARSING MACRO BODY: [HEX LITERAL: {}]", hex::encode(val));
781
782 if o.push_overflows(&hex_str) {
784 return Err(ParserError {
785 kind: ParserErrorKind::InvalidPush(o),
786 hint: Some(format!("Literal {hex_str:?} contains too many bytes for opcode \"{o:?}\"")),
787 spans: AstSpan(curr_spans),
788 cursor: self.cursor,
789 });
790 }
791
792 self.consume();
793 statements.push(Statement { ty: StatementType::Literal(val), span: AstSpan(curr_spans) });
795 }
796 _ => {
797 return Err(ParserError {
798 kind: ParserErrorKind::InvalidPush(o),
799 hint: Some(format!("Expected literal following \"{:?}\", found \"{:?}\"", o, self.current_token.kind)),
800 spans: AstSpan(vec![self.current_token.span.clone()]),
801 cursor: self.cursor,
802 });
803 }
804 }
805 }
806 }
807 TokenKind::Ident(ident_str) => {
808 let mut curr_spans = vec![self.current_token.span.clone()];
809 tracing::info!(target: "parser", "PARSING MACRO BODY: [IDENT: {}]", ident_str);
810 self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?;
811 match self.current_token.kind {
813 TokenKind::OpenParen => {
814 let lit_args = self.parse_macro_call_args(macro_name.to_owned())?;
816 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
818 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
819 }
820 statements.push(Statement {
821 ty: StatementType::MacroInvocation(MacroInvocation {
822 macro_name: ident_str.to_string(),
823 args: lit_args,
824 span: AstSpan(curr_spans.clone()),
825 }),
826 span: AstSpan(curr_spans),
827 });
828 }
829 _ => {
830 tracing::info!(target: "parser", "LABEL CALL TO: {}", ident_str);
831 statements.push(Statement { ty: StatementType::LabelCall(ident_str), span: AstSpan(curr_spans) });
832 }
833 }
834 }
835 TokenKind::If | TokenKind::Else | TokenKind::For if !matches!(self.peek(), Some(t) if matches!(t.kind, TokenKind::OpenParen | TokenKind::OpenBrace)) =>
838 {
839 let keyword_str = match &self.current_token.kind {
840 TokenKind::If => "if",
841 TokenKind::Else => "else",
842 TokenKind::For => "for",
843 _ => unreachable!(),
844 };
845 let curr_spans = vec![self.current_token.span.clone()];
846 tracing::info!(target: "parser", "PARSING MACRO BODY: [KEYWORD AS LABEL: {}]", keyword_str);
847 self.consume();
848 tracing::info!(target: "parser", "LABEL CALL TO: {}", keyword_str);
850 statements.push(Statement { ty: StatementType::LabelCall(keyword_str.to_string()), span: AstSpan(curr_spans) });
851 }
852 TokenKind::Label(l) => {
853 let mut curr_spans = vec![self.current_token.span.clone()];
854 self.consume();
855 self.check_duplicate_label(contract, macro_name, l.to_string(), self.current_token.span.clone())?;
856 let inner_statements: Vec<Statement> = self.parse_label(macro_name.to_owned())?;
857 inner_statements.iter().for_each(|a| curr_spans.extend_from_slice(a.span.inner_ref()));
858 tracing::info!(target: "parser", "PARSED LABEL \"{}\" INSIDE MACRO WITH {} STATEMENTS.", l, inner_statements.len());
859 statements.push(Statement {
860 ty: StatementType::Label(Label { name: l, inner: inner_statements, span: AstSpan(curr_spans.clone()) }),
861 span: AstSpan(curr_spans),
862 });
863 }
864 TokenKind::OpenBracket => {
865 let (constant, const_span) = self.parse_constant_push()?;
866 tracing::info!(target: "parser", "PARSING MACRO BODY: [CONSTANT: {}]", constant);
867 statements.push(Statement { ty: StatementType::Constant(constant), span: AstSpan(vec![const_span]) });
868 }
869 TokenKind::LeftAngle => {
870 let stmt = self.parse_arg_call_or_invocation(macro_name.to_owned())?;
871 statements.push(stmt);
872 }
873 TokenKind::BuiltinFunction(f) => {
874 let mut curr_spans = vec![self.current_token.span.clone()];
875 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
876 let args = self.parse_builtin_args()?;
877 args.iter().for_each(|a| curr_spans.extend_from_slice(a.span().inner_ref()));
878 tracing::info!(target: "parser", "PARSING MACRO BODY: [BUILTIN FN: {}({:?})]", f, args);
879 statements.push(Statement {
880 ty: StatementType::BuiltinFunctionCall(BuiltinFunctionCall {
881 kind: BuiltinFunctionKind::from(f),
882 args,
883 span: AstSpan(curr_spans.clone()),
884 }),
885 span: AstSpan(curr_spans),
886 });
887 }
888 TokenKind::Noop => {
889 tracing::info!(target: "parser", "PARSING MACRO BODY: [__NOOP] - Skipping (no bytecode)");
890 self.consume();
891 }
893 TokenKind::For => {
894 let for_loop = self.parse_for_loop(macro_name)?;
895 statements.push(for_loop);
896 }
897 TokenKind::If => {
898 let if_statement = self.parse_if_statement(macro_name)?;
899 statements.push(if_statement);
900 }
901 kind => {
902 tracing::error!(target: "parser", "TOKEN MISMATCH - MACRO BODY: {}", kind);
903 return Err(ParserError {
904 kind: ParserErrorKind::InvalidTokenInMacroBody(kind),
905 hint: None,
906 spans: AstSpan(vec![self.current_token.span.clone()]),
907 cursor: self.cursor,
908 });
909 }
910 };
911 }
912 self.match_kind(TokenKind::CloseBrace)?;
914 Ok(statements)
915 }
916
917 pub fn parse_for_loop(&mut self, macro_name: &str) -> Result<Statement, ParserError> {
921 let mut curr_spans = vec![];
922
923 curr_spans.push(self.current_token.span.clone());
925 self.match_kind(TokenKind::For)?;
926
927 curr_spans.push(self.current_token.span.clone());
929 self.match_kind(TokenKind::OpenParen)?;
930
931 let variable = match self.current_token.kind.clone() {
933 TokenKind::Ident(name) => {
934 curr_spans.push(self.current_token.span.clone());
935 self.consume();
936 name
937 }
938 _ => {
939 return Err(ParserError {
940 kind: ParserErrorKind::InvalidName(self.current_token.kind.clone()),
941 hint: Some("Expected loop variable name after 'for('".to_string()),
942 spans: AstSpan(vec![self.current_token.span.clone()]),
943 cursor: self.cursor,
944 });
945 }
946 };
947
948 curr_spans.push(self.current_token.span.clone());
950 self.match_kind(TokenKind::In)?;
951
952 let start = self.parse_constant_expression()?;
954 curr_spans.extend_from_slice(start.span().inner_ref());
955
956 curr_spans.push(self.current_token.span.clone());
958 self.match_kind(TokenKind::DoubleDot)?;
959
960 let end = self.parse_constant_expression()?;
962 curr_spans.extend_from_slice(end.span().inner_ref());
963
964 let step = if self.check(TokenKind::Step) {
966 curr_spans.push(self.current_token.span.clone());
967 self.match_kind(TokenKind::Step)?;
968 let step_expr = self.parse_constant_expression()?;
969 curr_spans.extend_from_slice(step_expr.span().inner_ref());
970 Some(step_expr)
971 } else {
972 None
973 };
974
975 curr_spans.push(self.current_token.span.clone());
977 self.match_kind(TokenKind::CloseParen)?;
978
979 curr_spans.push(self.current_token.span.clone());
981
982 self.loop_variables.push(variable.clone());
984
985 let body = self.parse_for_body(macro_name)?;
987
988 self.loop_variables.pop();
990
991 body.iter().for_each(|s| curr_spans.extend_from_slice(s.span.inner_ref()));
993
994 if let Some(close_brace_token) = self.peek_behind() {
996 curr_spans.push(close_brace_token.span);
997 }
998
999 tracing::info!(target: "parser", "PARSED FOR LOOP: {} in {}..{} step {:?} with {} statements",
1000 variable, "start", "end", step, body.len());
1001
1002 Ok(Statement { ty: StatementType::ForLoop { variable, start, end, step, body }, span: AstSpan(curr_spans) })
1003 }
1004
1005 pub fn parse_if_statement(&mut self, macro_name: &str) -> Result<Statement, ParserError> {
1007 let mut curr_spans = vec![];
1008
1009 curr_spans.push(self.current_token.span.clone());
1011 self.match_kind(TokenKind::If)?;
1012
1013 curr_spans.push(self.current_token.span.clone());
1015 self.match_kind(TokenKind::OpenParen)?;
1016
1017 let condition = self.parse_constant_expression()?;
1019 curr_spans.extend_from_slice(condition.span().inner_ref());
1020
1021 curr_spans.push(self.current_token.span.clone());
1023 self.match_kind(TokenKind::CloseParen)?;
1024
1025 curr_spans.push(self.current_token.span.clone());
1027 let then_branch = self.parse_if_body(macro_name)?;
1028 then_branch.iter().for_each(|s| curr_spans.extend_from_slice(s.span.inner_ref()));
1029
1030 if let Some(close_brace_token) = self.peek_behind() {
1032 curr_spans.push(close_brace_token.span);
1033 }
1034
1035 let mut else_if_branches = Vec::new();
1037 while self.check(TokenKind::Else) {
1038 let next_is_if = self.peek().map(|t| matches!(t.kind, TokenKind::If)).unwrap_or(false);
1040
1041 if !next_is_if {
1042 break; }
1044
1045 curr_spans.push(self.current_token.span.clone());
1047 self.match_kind(TokenKind::Else)?;
1048
1049 curr_spans.push(self.current_token.span.clone());
1051 self.match_kind(TokenKind::If)?;
1052
1053 curr_spans.push(self.current_token.span.clone());
1055 self.match_kind(TokenKind::OpenParen)?;
1056
1057 let else_if_condition = self.parse_constant_expression()?;
1059 curr_spans.extend_from_slice(else_if_condition.span().inner_ref());
1060
1061 curr_spans.push(self.current_token.span.clone());
1063 self.match_kind(TokenKind::CloseParen)?;
1064
1065 curr_spans.push(self.current_token.span.clone());
1067 let else_if_body = self.parse_if_body(macro_name)?;
1068 else_if_body.iter().for_each(|s| curr_spans.extend_from_slice(s.span.inner_ref()));
1069
1070 if let Some(close_brace_token) = self.peek_behind() {
1072 curr_spans.push(close_brace_token.span);
1073 }
1074
1075 else_if_branches.push((else_if_condition, else_if_body));
1076 }
1077
1078 let else_branch = if self.check(TokenKind::Else) {
1080 curr_spans.push(self.current_token.span.clone());
1081 self.match_kind(TokenKind::Else)?;
1082
1083 curr_spans.push(self.current_token.span.clone());
1085 let else_body = self.parse_if_body(macro_name)?;
1086 else_body.iter().for_each(|s| curr_spans.extend_from_slice(s.span.inner_ref()));
1087
1088 if let Some(close_brace_token) = self.peek_behind() {
1090 curr_spans.push(close_brace_token.span);
1091 }
1092
1093 Some(else_body)
1094 } else {
1095 None
1096 };
1097
1098 tracing::info!(target: "parser", "PARSED IF STATEMENT with {} else-if branches and else: {}",
1099 else_if_branches.len(), else_branch.is_some());
1100
1101 Ok(Statement {
1102 ty: StatementType::IfStatement { condition, then_branch, else_if_branches, else_branch },
1103 span: AstSpan(curr_spans),
1104 })
1105 }
1106
1107 fn parse_if_body(&mut self, macro_name: &str) -> Result<Vec<Statement>, ParserError> {
1109 self.parse_for_body(macro_name)
1112 }
1113
1114 fn parse_for_body(&mut self, macro_name: &str) -> Result<Vec<Statement>, ParserError> {
1116 let mut statements: Vec<Statement> = Vec::new();
1117 self.match_kind(TokenKind::OpenBrace)?;
1118
1119 while !self.check(TokenKind::CloseBrace) {
1120 match self.current_token.kind.clone() {
1121 TokenKind::HexLiteral(hex_str) => {
1122 let curr_spans = vec![self.current_token.span.clone()];
1123 let val = str_to_bytes32(&hex_str);
1124 self.consume();
1125 statements.push(Statement { ty: StatementType::Literal(val), span: AstSpan(curr_spans) });
1126 }
1127 TokenKind::Opcode(o) => {
1128 let curr_spans = vec![self.current_token.span.clone()];
1129 self.consume();
1130 if self.takes_opcode_operands(o) {
1131 statements.push(self.parse_opcode_operands(o, curr_spans[0].clone())?);
1132 continue;
1133 }
1134 statements.push(Statement { ty: StatementType::Opcode(o), span: AstSpan(curr_spans) });
1135 if o.is_value_push() {
1136 match self.current_token.kind.clone() {
1138 TokenKind::HexLiteral(hex_str) => {
1139 let curr_spans = vec![self.current_token.span.clone()];
1140 let val = str_to_bytes32(&hex_str);
1141 self.consume();
1142 statements.push(Statement { ty: StatementType::Literal(val), span: AstSpan(curr_spans) });
1143 }
1144 _ => {
1145 return Err(ParserError {
1146 kind: ParserErrorKind::InvalidPush(o),
1147 hint: Some(format!("Expected literal or interpolation following \"{:?}\"", o)),
1148 spans: AstSpan(vec![self.current_token.span.clone()]),
1149 cursor: self.cursor,
1150 });
1151 }
1152 }
1153 }
1154 }
1155 TokenKind::Ident(ident_str) => {
1156 let mut curr_spans = vec![self.current_token.span.clone()];
1157 self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?;
1158 match self.current_token.kind {
1160 TokenKind::OpenParen => {
1161 let lit_args = self.parse_macro_call_args(macro_name.to_owned())?;
1163 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1164 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1165 }
1166 statements.push(Statement {
1167 ty: StatementType::MacroInvocation(MacroInvocation {
1168 macro_name: ident_str.to_string(),
1169 args: lit_args,
1170 span: AstSpan(curr_spans.clone()),
1171 }),
1172 span: AstSpan(curr_spans),
1173 });
1174 }
1175 _ => {
1176 statements.push(Statement { ty: StatementType::LabelCall(ident_str), span: AstSpan(curr_spans) });
1177 }
1178 }
1179 }
1180 TokenKind::OpenBracket => {
1181 let (constant, const_span) = self.parse_constant_push()?;
1182 statements.push(Statement { ty: StatementType::Constant(constant), span: AstSpan(vec![const_span]) });
1183 }
1184 TokenKind::LeftAngle => {
1185 let angle_span = self.current_token.span.clone(); self.consume(); if let TokenKind::Ident(ref ident_name) = self.current_token.kind {
1190 if self.loop_variables.contains(ident_name) {
1192 let var_name = ident_name.clone();
1194 self.consume(); self.match_kind(TokenKind::RightAngle)?; tracing::info!(target: "parser", "PARSING FOR BODY: [LOOP VAR: <{}>]", var_name);
1198 statements.push(Statement {
1199 ty: StatementType::Constant(format!("__LOOP_VAR_{}", var_name)),
1200 span: AstSpan(vec![angle_span]),
1201 });
1202 continue;
1203 }
1204 }
1205
1206 let stmt = self.parse_arg_call_or_invocation_after_angle(macro_name.to_owned(), angle_span)?;
1209 statements.push(stmt);
1210 }
1211 TokenKind::BuiltinFunction(f) => {
1212 let mut curr_spans = vec![self.current_token.span.clone()];
1213 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
1214 let args = self.parse_builtin_args()?;
1215 args.iter().for_each(|a| curr_spans.extend_from_slice(a.span().inner_ref()));
1216 statements.push(Statement {
1217 ty: StatementType::BuiltinFunctionCall(BuiltinFunctionCall {
1218 kind: BuiltinFunctionKind::from(f),
1219 args,
1220 span: AstSpan(curr_spans.clone()),
1221 }),
1222 span: AstSpan(curr_spans),
1223 });
1224 }
1225 TokenKind::Label(l) => {
1226 let mut curr_spans = vec![self.current_token.span.clone()];
1227 self.consume();
1228 let inner_statements: Vec<Statement> = self.parse_label(macro_name.to_owned())?;
1229 inner_statements.iter().for_each(|a| curr_spans.extend_from_slice(a.span.inner_ref()));
1230 tracing::info!(target: "parser", "PARSED LABEL \"{}\" INSIDE FOR LOOP WITH {} STATEMENTS.", l, inner_statements.len());
1231 statements.push(Statement {
1232 ty: StatementType::Label(Label { name: l, inner: inner_statements, span: AstSpan(curr_spans.clone()) }),
1233 span: AstSpan(curr_spans),
1234 });
1235 }
1236 TokenKind::Noop => {
1237 tracing::info!(target: "parser", "PARSING FOR BODY: [__NOOP] - Skipping (no bytecode)");
1238 self.consume();
1239 }
1241 TokenKind::For => {
1242 let nested_for_loop = self.parse_for_loop(macro_name)?;
1244 statements.push(nested_for_loop);
1245 }
1246 TokenKind::If => {
1247 let if_statement = self.parse_if_statement(macro_name)?;
1249 statements.push(if_statement);
1250 }
1251 kind => {
1252 return Err(ParserError {
1253 kind: ParserErrorKind::InvalidTokenInMacroBody(kind),
1254 hint: Some("Unexpected token in for loop body".to_string()),
1255 spans: AstSpan(vec![self.current_token.span.clone()]),
1256 cursor: self.cursor,
1257 });
1258 }
1259 }
1260 }
1261
1262 self.match_kind(TokenKind::CloseBrace)?;
1263 Ok(statements)
1264 }
1265
1266 pub fn parse_label(&mut self, parent_macro_name: String) -> Result<Vec<Statement>, ParserError> {
1278 let mut statements: Vec<Statement> = Vec::new();
1279 self.match_kind(TokenKind::Colon)?;
1280 while !self.check(TokenKind::Label("NEXT_LABEL".to_string()))
1281 && !self.check(TokenKind::CloseBrace)
1282 && !self.check(TokenKind::For)
1283 && !self.check(TokenKind::If)
1284 {
1285 match self.current_token.kind.clone() {
1286 TokenKind::HexLiteral(hex_str) => {
1287 let curr_spans = vec![self.current_token.span.clone()];
1288 let val = str_to_bytes32(&hex_str);
1289 tracing::info!(target: "parser", "PARSING LABEL BODY: [HEX LITERAL: {}]", hex::encode(val));
1290 self.consume();
1291 statements.push(Statement { ty: StatementType::Literal(val), span: AstSpan(curr_spans) });
1292 }
1293 TokenKind::Opcode(o) => {
1294 let curr_spans = vec![self.current_token.span.clone()];
1295 tracing::info!(target: "parser", "PARSING LABEL BODY: [OPCODE: {}]", o);
1296 self.consume();
1297 if self.takes_opcode_operands(o) {
1298 statements.push(self.parse_opcode_operands(o, curr_spans[0].clone())?);
1299 continue;
1300 }
1301 statements.push(Statement { ty: StatementType::Opcode(o), span: AstSpan(curr_spans) });
1302 }
1303 TokenKind::Ident(ident_str) => {
1304 let mut curr_spans = vec![self.current_token.span.clone()];
1305 tracing::info!(target: "parser", "PARSING LABEL BODY: [IDENT: {}]", ident_str);
1306 self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?;
1307 match self.current_token.kind.clone() {
1309 TokenKind::OpenParen => {
1310 let lit_args = self.parse_macro_call_args(ident_str.to_string())?;
1312 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1314 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1315 }
1316 statements.push(Statement {
1317 ty: StatementType::MacroInvocation(MacroInvocation {
1318 macro_name: ident_str.to_string(),
1319 args: lit_args,
1320 span: AstSpan(curr_spans.clone()),
1321 }),
1322 span: AstSpan(curr_spans),
1323 });
1324 }
1325 _ => {
1326 tracing::info!(target: "parser", "LABEL CALL TO: {}", ident_str);
1327 statements.push(Statement { ty: StatementType::LabelCall(ident_str), span: AstSpan(curr_spans) });
1328 }
1329 }
1330 }
1331 TokenKind::OpenBracket => {
1332 let (constant, const_span) = self.parse_constant_push()?;
1333 tracing::info!(target: "parser", "PARSING LABEL BODY: [CONSTANT: {}]", constant);
1334 statements.push(Statement { ty: StatementType::Constant(constant), span: AstSpan(vec![const_span]) });
1335 }
1336 TokenKind::LeftAngle => {
1337 let angle_span = self.current_token.span.clone(); self.consume(); if let TokenKind::Ident(ref ident_name) = self.current_token.kind {
1342 if self.loop_variables.contains(ident_name) {
1344 let var_name = ident_name.clone();
1346 self.consume(); self.match_kind(TokenKind::RightAngle)?; tracing::info!(target: "parser", "PARSING LABEL BODY: [LOOP VAR: <{}>]", var_name);
1350 statements.push(Statement {
1351 ty: StatementType::Constant(format!("__LOOP_VAR_{}", var_name)),
1352 span: AstSpan(vec![angle_span]),
1353 });
1354 continue;
1355 }
1356 }
1357
1358 let stmt = self.parse_arg_call_or_invocation_after_angle(parent_macro_name.clone(), angle_span)?;
1360 statements.push(stmt);
1361 }
1362 TokenKind::BuiltinFunction(f) => {
1363 let mut curr_spans = vec![self.current_token.span.clone()];
1364 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
1365 let args = self.parse_builtin_args()?;
1366 args.iter().for_each(|a| curr_spans.extend_from_slice(a.span().inner_ref()));
1367 tracing::info!(target: "parser", "PARSING LABEL BODY: [BUILTIN FN: {}({:?})]", f, args);
1368 statements.push(Statement {
1369 ty: StatementType::BuiltinFunctionCall(BuiltinFunctionCall {
1370 kind: BuiltinFunctionKind::from(f),
1371 args,
1372 span: AstSpan(curr_spans.clone()),
1373 }),
1374 span: AstSpan(curr_spans),
1375 });
1376 }
1377 TokenKind::Noop => {
1378 tracing::info!(target: "parser", "PARSING LABEL BODY: [__NOOP] - Skipping (no bytecode)");
1379 self.consume();
1380 }
1382 TokenKind::If | TokenKind::Else | TokenKind::For if !matches!(self.peek(), Some(t) if matches!(t.kind, TokenKind::OpenParen | TokenKind::OpenBrace)) =>
1385 {
1386 let keyword_str = match &self.current_token.kind {
1387 TokenKind::If => "if",
1388 TokenKind::Else => "else",
1389 TokenKind::For => "for",
1390 _ => unreachable!(),
1391 };
1392 let curr_spans = vec![self.current_token.span.clone()];
1393 tracing::info!(target: "parser", "PARSING LABEL BODY: [KEYWORD AS LABEL: {}]", keyword_str);
1394 self.consume();
1395 tracing::info!(target: "parser", "LABEL CALL TO: {}", keyword_str);
1397 statements.push(Statement { ty: StatementType::LabelCall(keyword_str.to_string()), span: AstSpan(curr_spans) });
1398 }
1399 kind => {
1400 tracing::error!(target: "parser", "TOKEN MISMATCH - LABEL BODY: {}", kind);
1401 return Err(ParserError {
1402 kind: ParserErrorKind::InvalidTokenInLabelDefinition(kind),
1403 hint: None,
1404 spans: AstSpan(vec![self.current_token.span.clone()]),
1405 cursor: self.cursor,
1406 });
1407 }
1408 };
1409 }
1410 Ok(statements)
1411 }
1412
1413 pub fn parse_newline(&mut self) -> Result<(), ParserError> {
1417 self.match_kind(TokenKind::Whitespace)?;
1418 while self.check(TokenKind::Whitespace) {
1419 self.consume();
1420 }
1421 Ok(())
1422 }
1423
1424 fn at_builtin_expression_arg(&self) -> bool {
1427 let ends_arg = |offset: usize| {
1428 self.tokens.get(self.cursor + offset).is_some_and(|t| matches!(t.kind, TokenKind::Comma | TokenKind::CloseParen))
1429 };
1430 match self.current_token.kind {
1431 TokenKind::LeftAngle | TokenKind::OpenParen | TokenKind::Integer(_) => true,
1432 TokenKind::HexLiteral(_) => !ends_arg(1),
1433 TokenKind::OpenBracket => !ends_arg(3),
1434 _ => false,
1435 }
1436 }
1437
1438 pub fn parse_builtin_args(&mut self) -> Result<Vec<BuiltinFunctionArg>, ParserError> {
1440 let mut args: Vec<BuiltinFunctionArg> = Vec::new();
1441 self.match_kind(TokenKind::OpenParen)?;
1442
1443 tracing::debug!(target: "parser", "PARSING ARGs: {:?}", self.current_token.kind);
1444 while !self.check(TokenKind::CloseParen) {
1445 let mut is_builtin = false;
1446 let mut builtin = "".to_string();
1447
1448 if self.at_builtin_expression_arg() {
1449 args.push(BuiltinFunctionArg::Expression(self.parse_constant_expression()?));
1450 if self.check(TokenKind::Comma) {
1451 self.consume();
1452 }
1453 continue;
1454 }
1455
1456 match &self.current_token.kind {
1457 TokenKind::Str(s) => {
1458 args.push(BuiltinFunctionArg::StringLiteral(s.to_owned(), AstSpan(vec![self.current_token.span.clone()])));
1459 self.consume();
1460 }
1461 TokenKind::HexLiteral(bytes) => {
1462 args.push(BuiltinFunctionArg::HexLiteral(bytes.to_owned(), AstSpan(vec![self.current_token.span.clone()])));
1463 self.consume();
1464 }
1465 TokenKind::Ident(ident) => {
1466 args.push(BuiltinFunctionArg::Identifier(ident.to_owned(), AstSpan(vec![self.current_token.span.clone()])));
1467 self.consume();
1468 }
1469 TokenKind::BuiltinFunction(builtin_ref) => {
1470 is_builtin = true;
1471 builtin = builtin_ref.clone();
1472 self.consume();
1473 }
1474 TokenKind::OpenBracket => {
1475 let (constant_name, span) = self.parse_constant_push()?;
1476 args.push(BuiltinFunctionArg::Constant(constant_name, AstSpan(vec![span])));
1477 }
1478 _ => {
1479 return Err(ParserError {
1480 kind: ParserErrorKind::UnexpectedType(self.current_token.kind.clone()),
1481 hint: Some("Expected string, literal, hex, identifier or build-in".to_string()),
1482 spans: AstSpan(vec![self.current_token.span.clone()]),
1483 cursor: self.cursor,
1484 });
1485 }
1486 }
1487
1488 if is_builtin {
1489 args.push(BuiltinFunctionArg::BuiltinFunctionCall(BuiltinFunctionCall {
1490 kind: BuiltinFunctionKind::from(builtin.clone()),
1491 args: self.parse_builtin_args()?, span: AstSpan(vec![self.current_token.span.clone()]),
1493 }));
1494 }
1495
1496 if self.check(TokenKind::Comma) {
1497 self.consume();
1498 }
1499 }
1500
1501 self.match_kind(TokenKind::CloseParen)?;
1503 Ok(args)
1504 }
1505
1506 pub fn parse_args(&mut self, select_name: bool, select_type: bool, has_indexed: bool) -> Result<Vec<Argument>, ParserError> {
1512 let mut args: Vec<Argument> = Vec::new();
1513 self.match_kind(TokenKind::OpenParen)?;
1514 let mut on_type = true;
1515 tracing::debug!(target: "parser", "PARSING ABI ARGs: {:?}", self.current_token.kind);
1516 while !self.check(TokenKind::CloseParen) {
1517 let mut arg = Argument::default();
1518 let mut arg_spans = vec![];
1519
1520 if select_type {
1522 arg_spans.push(self.current_token.span.clone());
1523 arg.arg_type = Some(self.parse_arg_type()?);
1524 if has_indexed && self.check(TokenKind::Indexed) {
1526 arg.indexed = true;
1527 arg_spans.push(self.current_token.span.clone());
1528 self.consume(); }
1530 on_type = false;
1531 }
1532
1533 match &self.current_token.kind {
1535 TokenKind::Calldata => {
1536 arg.arg_location = Some(ArgumentLocation::Calldata);
1537 arg_spans.push(self.current_token.span.clone());
1538 self.consume();
1539 }
1540 TokenKind::Memory => {
1541 arg.arg_location = Some(ArgumentLocation::Memory);
1542 arg_spans.push(self.current_token.span.clone());
1543 self.consume();
1544 }
1545 TokenKind::Storage => {
1546 arg.arg_location = Some(ArgumentLocation::Storage);
1547 arg_spans.push(self.current_token.span.clone());
1548 self.consume();
1549 }
1550 _ => {}
1551 }
1552
1553 if select_name
1555 && (self.check(TokenKind::Ident("x".to_string())) || self.check(TokenKind::PrimitiveType(PrimitiveEVMType::Address)))
1556 {
1557 if !on_type {
1559 match self.current_token.kind.clone() {
1561 TokenKind::Ident(arg_str) if PrimitiveEVMType::try_from(&arg_str).is_ok() => {
1562 return Err(ParserError {
1563 kind: ParserErrorKind::InvalidTypeAsArgumentName(self.current_token.kind.clone()),
1564 hint: Some(format!("Argument names cannot be EVM types: {arg_str}")),
1565 spans: AstSpan(vec![self.current_token.span.clone()]),
1566 cursor: self.cursor,
1567 });
1568 }
1569 TokenKind::PrimitiveType(ty) => {
1570 return Err(ParserError {
1571 kind: ParserErrorKind::InvalidTypeAsArgumentName(self.current_token.kind.clone()),
1572 hint: Some(format!("Argument names cannot be EVM types: {ty}")),
1573 spans: AstSpan(vec![self.current_token.span.clone()]),
1574 cursor: self.cursor,
1575 });
1576 }
1577 _ => { }
1578 }
1579 }
1580 arg_spans.push(self.current_token.span.clone());
1581 arg.name = Some(self.match_kind(TokenKind::Ident("x".to_string()))?.to_string());
1582 on_type = !on_type;
1583 }
1584
1585 if self.check(TokenKind::Comma) {
1587 self.consume();
1588 on_type = true;
1589 }
1590
1591 if arg.arg_type.is_none() && arg.name.is_none() {
1593 tracing::error!(target: "parser", "INVALID ARGUMENT TOKEN: {:?}", self.current_token.kind);
1594 return Err(ParserError {
1595 kind: ParserErrorKind::InvalidArgs(self.current_token.kind.clone()),
1596 hint: None,
1597 spans: AstSpan(vec![self.current_token.span.clone()]),
1598 cursor: self.cursor,
1599 });
1600 }
1601
1602 arg.span = AstSpan(arg_spans);
1603
1604 args.push(arg);
1605 }
1606 self.match_kind(TokenKind::CloseParen)?;
1608 Ok(args)
1609 }
1610
1611 pub fn parse_single_arg(&mut self) -> Result<usize, ParserError> {
1613 self.match_kind(TokenKind::OpenParen)?;
1614 let single_arg_span = vec![self.current_token.span.clone()];
1615 let value: usize = match self.match_kind(TokenKind::Integer(0)) {
1616 Ok(TokenKind::Integer(value)) => value,
1617 _ => {
1618 return Err(ParserError {
1619 kind: ParserErrorKind::InvalidSingleArg(self.current_token.kind.clone()),
1620 hint: Some("Expected number representing stack item count.".to_string()),
1621 spans: AstSpan(single_arg_span),
1622 cursor: self.cursor,
1623 });
1624 }
1625 };
1626 self.match_kind(TokenKind::CloseParen)?;
1627 Ok(value)
1628 }
1629
1630 fn parse_single_macro_argument(&mut self) -> Result<MacroArg, ParserError> {
1632 match self.current_token.kind.clone() {
1633 TokenKind::HexLiteral(hex_str) => {
1634 let lit = str_to_bytes32(&hex_str);
1635 self.consume();
1636 Ok(MacroArg::HexLiteral(lit))
1637 }
1638 TokenKind::Integer(n) => {
1639 self.consume();
1640 Ok(MacroArg::HexLiteral(str_to_bytes32(&format!("{n:x}"))))
1641 }
1642 TokenKind::Opcode(o) => {
1643 self.consume();
1644 Ok(MacroArg::Opcode(o))
1645 }
1646 TokenKind::Noop => {
1647 self.consume();
1648 Ok(MacroArg::Noop)
1649 }
1650 TokenKind::BuiltinFunction(f) => {
1651 let mut curr_spans = vec![self.current_token.span.clone()];
1652 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
1653 let args = self.parse_builtin_args()?;
1654 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1655 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1656 }
1657 Ok(MacroArg::BuiltinFunctionCall(BuiltinFunctionCall {
1658 kind: BuiltinFunctionKind::from(f),
1659 args,
1660 span: AstSpan(curr_spans),
1661 }))
1662 }
1663 TokenKind::Ident(ident) => {
1664 if self.peek().is_some() && self.peek().unwrap().kind == TokenKind::OpenParen {
1665 let mut curr_spans = vec![self.current_token.span.clone()];
1667 self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?;
1668 let lit_args = self.parse_macro_call_args(String::new())?;
1670 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1672 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1673 }
1674 Ok(MacroArg::MacroCall(MacroInvocation { macro_name: ident, args: lit_args, span: AstSpan(curr_spans.clone()) }))
1675 } else {
1676 self.consume();
1677 Ok(MacroArg::Ident(ident))
1678 }
1679 }
1680 TokenKind::Calldata => {
1681 self.consume();
1682 Ok(MacroArg::Ident("calldata".to_string()))
1683 }
1684 TokenKind::LeftAngle => {
1685 self.consume();
1687 let arg_name = self.match_kind(TokenKind::Ident("ARG_CALL".to_string()))?.to_string();
1688 let span = AstSpan(vec![self.current_token.span.clone()]);
1689 self.match_kind(TokenKind::RightAngle)?;
1690
1691 if self.current_token.kind == TokenKind::OpenParen {
1693 self.consume(); let mut args = Vec::new();
1697 while self.current_token.kind != TokenKind::CloseParen {
1698 args.push(self.parse_single_macro_argument()?);
1699
1700 if self.current_token.kind == TokenKind::Comma {
1701 self.consume();
1702 } else if self.current_token.kind != TokenKind::CloseParen {
1703 break; }
1705 }
1706
1707 self.match_kind(TokenKind::CloseParen)?; Ok(MacroArg::ArgCallMacroInvocation(arg_name, args))
1710 } else if self.loop_variables.contains(&arg_name) {
1711 Ok(MacroArg::Ident(format!("__LOOP_VAR_{arg_name}")))
1713 } else {
1714 Ok(MacroArg::ArgCall(ArgCall {
1716 macro_name: String::new(), name: arg_name,
1718 span,
1719 }))
1720 }
1721 }
1722 arg => Err(ParserError {
1723 kind: ParserErrorKind::InvalidMacroArgs(arg),
1724 hint: Some("Expected literal, identifier, opcode, builtin function, __NOOP, or argument call".to_string()),
1725 spans: AstSpan(vec![self.current_token.span.clone()]),
1726 cursor: self.cursor,
1727 }),
1728 }
1729 }
1730
1731 pub fn parse_macro_call_args(&mut self, macro_name: String) -> Result<Vec<MacroArg>, ParserError> {
1733 let mut args = vec![];
1734 self.match_kind(TokenKind::OpenParen)?;
1735 while !self.check(TokenKind::CloseParen) {
1736 match self.current_token.kind.clone() {
1737 TokenKind::HexLiteral(hex_str) => {
1738 let lit = str_to_bytes32(&hex_str);
1739 args.push(MacroArg::HexLiteral(lit));
1740 self.consume();
1741 }
1742 TokenKind::Integer(n) => {
1743 args.push(MacroArg::HexLiteral(str_to_bytes32(&format!("{n:x}"))));
1744 self.consume();
1745 }
1746 TokenKind::Opcode(o) => {
1747 args.push(MacroArg::Opcode(o));
1748 self.consume();
1749 }
1750 TokenKind::Ident(ident) => {
1751 if self.peek().unwrap().kind == TokenKind::OpenParen {
1752 let mut curr_spans = vec![self.current_token.span.clone()];
1754 self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?;
1755 let lit_args = self.parse_macro_call_args(macro_name.clone())?;
1757 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1759 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1760 }
1761 args.push(MacroArg::MacroCall(MacroInvocation {
1762 macro_name: ident,
1763 args: lit_args,
1764 span: AstSpan(curr_spans.clone()),
1765 }));
1766 } else {
1767 args.push(MacroArg::Ident(ident));
1768 self.consume();
1769 }
1770 }
1771 TokenKind::Calldata => {
1772 args.push(MacroArg::Ident("calldata".to_string()));
1773 self.consume();
1774 }
1775 TokenKind::Noop => {
1776 args.push(MacroArg::Noop);
1777 self.consume();
1778 }
1779 TokenKind::BuiltinFunction(f) => {
1780 let mut curr_spans = vec![self.current_token.span.clone()];
1781 self.match_kind(TokenKind::BuiltinFunction(String::default()))?;
1782 let builtin_args = self.parse_builtin_args()?;
1783 if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) {
1784 curr_spans.append(&mut self.spans[(i + 1)..].to_vec());
1785 }
1786 args.push(MacroArg::BuiltinFunctionCall(BuiltinFunctionCall {
1787 kind: BuiltinFunctionKind::from(f),
1788 args: builtin_args,
1789 span: AstSpan(curr_spans),
1790 }));
1791 }
1792 TokenKind::LeftAngle => {
1793 self.consume();
1797 let arg_name = self.match_kind(TokenKind::Ident("ARG_CALL".to_string()))?.to_string();
1798 let closing_angle_span = self.current_token.span.clone(); self.match_kind(TokenKind::RightAngle)?;
1800
1801 if self.check(TokenKind::OpenParen) {
1803 let invoc_args = self.parse_macro_call_args(macro_name.clone())?;
1804 args.push(MacroArg::ArgCallMacroInvocation(arg_name, invoc_args));
1805 } else if self.loop_variables.contains(&arg_name) {
1806 args.push(MacroArg::Ident(format!("__LOOP_VAR_{arg_name}")));
1808 } else {
1809 args.push(MacroArg::ArgCall(ArgCall {
1810 macro_name: macro_name.clone(),
1811 name: arg_name,
1812 span: AstSpan(vec![closing_angle_span]),
1813 }));
1814 }
1815 }
1816 arg => {
1817 tracing::error!(
1818 target: "parser",
1819 "Invalid macro call arguments. Must be of kind Ident, Literal, Builtin Function, etc. Got: {}",
1820 self.current_token.kind
1821 );
1822 let new_spans = self.spans.clone();
1823 self.spans = vec![];
1824 return Err(ParserError {
1825 kind: ParserErrorKind::InvalidMacroArgs(arg),
1826 hint: Some("Expected literal, identifier (string), builtin function, or an argument call".to_string()),
1827 spans: AstSpan(new_spans),
1828 cursor: self.cursor,
1829 });
1830 }
1831 }
1832 if self.check(TokenKind::Comma) {
1833 self.consume();
1834 }
1835 }
1836 self.consume();
1838 Ok(args)
1839 }
1840
1841 pub fn parse_table(&mut self) -> Result<TableDefinition, ParserError> {
1845 let is_code_table = self.current_token.kind == TokenKind::CodeTable;
1846 let kind = TableKind::from(self.match_kind(self.current_token.kind.clone())?);
1847 let table_name: String = self.match_kind(TokenKind::Ident("TABLE_NAME".to_string()))?.to_string();
1848
1849 let _ = self.match_kind(TokenKind::OpenParen);
1851 let _ = self.match_kind(TokenKind::CloseParen);
1852 let _ = self.match_kind(TokenKind::Assign);
1853
1854 let table_statements: Vec<Statement> = self.parse_table_body(is_code_table)?;
1856 let size = match kind {
1857 TableKind::JumpTablePacked => Some(table_statements.len() * 0x02),
1858 TableKind::JumpTable => Some(table_statements.len() * 0x20),
1859 TableKind::CodeTable => {
1860 let mut table_size = 0;
1861 let mut unknown_size = false;
1863 for s in &table_statements {
1864 if let StatementType::Code(c) = &s.ty {
1865 table_size += c.len().div_ceil(2);
1869 } else if let StatementType::BuiltinFunctionCall(_) = &s.ty {
1870 unknown_size = true;
1871 } else if let StatementType::Constant(_) = &s.ty {
1872 unknown_size = true;
1873 } else {
1874 return Err(ParserError {
1875 kind: ParserErrorKind::InvalidTableStatement(format!("{}", s.ty)),
1876 hint: Some(format!("Invalid table statement. Must be valid hex bytecode. Got: {s:?}")),
1877 spans: AstSpan(s.span.inner_ref().to_vec()),
1878 cursor: self.cursor,
1879 });
1880 }
1881 }
1882 if unknown_size { None } else { Some(table_size) }
1883 }
1884 };
1885
1886 let table_size = size.map(|s| str_to_bytes32(format!("{s:02x}").as_str()));
1887 Ok(TableDefinition::new(table_name, kind, table_statements, table_size, AstSpan(self.spans.clone())))
1888 }
1889
1890 pub fn parse_table_body(&mut self, is_code_table: bool) -> Result<Vec<Statement>, ParserError> {
1894 let mut statements: Vec<Statement> = Vec::new();
1895
1896 self.match_kind(TokenKind::OpenBrace)?;
1897 while !self.check(TokenKind::CloseBrace) {
1898 let new_spans = vec![self.current_token.span.clone()];
1899 match self.current_token.kind.clone() {
1900 TokenKind::Ident(ident_str) => {
1901 if is_code_table {
1902 tracing::error!("Invalid CodeTable Body Token: {:?}", self.current_token.kind);
1903 return Err(ParserError {
1904 kind: ParserErrorKind::InvalidTableBodyToken(self.current_token.kind.clone()),
1905 hint: Some("Expected valid hex bytecode.".to_string()),
1906 spans: AstSpan(new_spans),
1907 cursor: self.cursor,
1908 });
1909 }
1910 statements.push(Statement { ty: StatementType::LabelCall(ident_str.to_string()), span: AstSpan(new_spans) });
1911 self.consume();
1912 }
1913 TokenKind::HexLiteral(bytes) => {
1914 if !is_code_table {
1915 tracing::error!("Invalid JumpTable Body Token: {:?}", self.current_token.kind);
1916 return Err(ParserError {
1917 kind: ParserErrorKind::InvalidTableBodyToken(self.current_token.kind.clone()),
1918 hint: Some("Expected an identifier string.".to_string()),
1919 spans: AstSpan(new_spans),
1920 cursor: self.cursor,
1921 });
1922 }
1923 let curr_spans = vec![self.current_token.span.clone()];
1924 tracing::info!(target: "parser", "PARSING CODE TABLE BODY: [BYTES: {}]", hex::encode(&bytes));
1925 self.consume();
1926 statements.push(Statement { ty: StatementType::Code(bytes), span: AstSpan(curr_spans) });
1927 }
1928 TokenKind::BuiltinFunction(f) => {
1929 if !is_code_table {
1930 tracing::error!("Invalid JumpTable Body Token: {:?}", self.current_token.kind);
1931 return Err(ParserError {
1932 kind: ParserErrorKind::InvalidTableBodyToken(self.current_token.kind.clone()),
1933 hint: Some("Expected an identifier string.".to_string()),
1934 spans: AstSpan(new_spans),
1935 cursor: self.cursor,
1936 });
1937 }
1938 let mut curr_spans = vec![self.current_token.span.clone()];
1939 self.consume();
1940 let args = self.parse_builtin_args()?;
1941 args.iter().for_each(|a| curr_spans.extend_from_slice(a.span().inner_ref()));
1942 tracing::info!(target: "parser", "PARSING CODE TABLE BODY: [BUILTIN FN: {}({:?})]", f, args);
1943 statements.push(Statement {
1944 ty: StatementType::BuiltinFunctionCall(BuiltinFunctionCall {
1945 kind: BuiltinFunctionKind::from(f.clone()),
1946 args,
1947 span: AstSpan(curr_spans.clone()),
1948 }),
1949 span: AstSpan(curr_spans),
1950 });
1951 }
1952 TokenKind::OpenBracket => {
1953 let (constant, const_span) = self.parse_constant_push()?;
1954 tracing::info!(target: "parser", "PARSING CODE TABLE BODY: [CONSTANT: {}]", constant);
1955 statements.push(Statement { ty: StatementType::Constant(constant), span: AstSpan(vec![const_span]) });
1956 }
1957 kind => {
1958 tracing::error!("Invalid Table Body Token: {:?}", kind);
1959 return Err(ParserError {
1960 kind: ParserErrorKind::InvalidTableBodyToken(kind.clone()),
1961 hint: Some("Expected an identifier string.".to_string()),
1962 spans: AstSpan(new_spans),
1963 cursor: self.cursor,
1964 });
1965 }
1966 };
1967 }
1968 self.match_kind(TokenKind::CloseBrace)?;
1970 Ok(statements)
1971 }
1972
1973 pub fn parse_constant_push(&mut self) -> Result<(String, Span), ParserError> {
1975 let start_span = self.current_token.span.clone();
1977 self.match_kind(TokenKind::OpenBracket)?;
1978 match self.current_token.kind.clone() {
1979 TokenKind::Ident(const_str) => {
1980 self.consume();
1982 let end_span = self.current_token.span.clone();
1983 self.match_kind(TokenKind::CloseBracket)?;
1984 let full_span = Span { start: start_span.start, end: end_span.end, file: start_span.file };
1986 Ok((const_str, full_span))
1987 }
1988 kind => {
1989 let new_spans = self.spans.clone();
1990 self.spans = vec![];
1991 Err(ParserError {
1992 kind: ParserErrorKind::InvalidConstant(kind),
1993 hint: None,
1994 spans: AstSpan(new_spans),
1995 cursor: self.cursor,
1996 })
1997 }
1998 }
1999 }
2000
2001 pub fn parse_arg_call(&mut self) -> Result<(String, Span), ParserError> {
2013 let start_span = self.current_token.span.clone();
2015 self.match_kind(TokenKind::LeftAngle)?;
2016 match self.current_token.kind.clone() {
2017 TokenKind::Ident(arg_str) => {
2018 self.consume();
2019 let end_span = self.current_token.span.clone();
2020 self.match_kind(TokenKind::RightAngle)?;
2021 let full_span = Span { start: start_span.start, end: end_span.end, file: start_span.file };
2023 Ok((arg_str, full_span))
2024 }
2025 kind => {
2026 let new_spans = self.spans.clone();
2027 self.spans = vec![];
2028 Err(ParserError {
2029 kind: ParserErrorKind::InvalidArgCallIdent(kind),
2030 hint: None,
2031 spans: AstSpan(new_spans),
2032 cursor: self.cursor,
2033 })
2034 }
2035 }
2036 }
2037
2038 fn parse_arg_call_or_invocation(&mut self, parent_macro_name: String) -> Result<Statement, ParserError> {
2041 let (arg_call, arg_span) = self.parse_arg_call()?;
2042
2043 if self.current_token.kind == TokenKind::OpenParen {
2045 tracing::info!(target: "parser", "PARSING ARG MACRO INVOCATION: {}()", arg_call);
2046 self.consume(); let mut args = Vec::new();
2050 while self.current_token.kind != TokenKind::CloseParen {
2051 let arg = self.parse_single_macro_argument()?;
2053 let arg = if let MacroArg::ArgCall(mut ac) = arg {
2055 ac.macro_name = parent_macro_name.clone();
2056 MacroArg::ArgCall(ac)
2057 } else {
2058 arg
2059 };
2060 args.push(arg);
2061
2062 if self.current_token.kind == TokenKind::Comma {
2064 self.consume();
2065 } else if self.current_token.kind != TokenKind::CloseParen {
2066 return Err(ParserError {
2067 kind: ParserErrorKind::InvalidTokenInMacroBody(self.current_token.kind.clone()),
2068 hint: Some("Expected ',' or ')' in macro argument list".to_string()),
2069 spans: AstSpan(vec![self.current_token.span.clone()]),
2070 cursor: self.cursor,
2071 });
2072 }
2073 }
2074
2075 self.match_kind(TokenKind::CloseParen)?; Ok(Statement { ty: StatementType::ArgMacroInvocation(parent_macro_name, arg_call, args), span: AstSpan(vec![arg_span]) })
2078 } else {
2079 tracing::info!(target: "parser", "PARSING ARG CALL: {}", arg_call);
2080 Ok(Statement { ty: StatementType::ArgCall(parent_macro_name, arg_call), span: AstSpan(vec![arg_span]) })
2081 }
2082 }
2083
2084 fn parse_arg_call_or_invocation_after_angle(&mut self, parent_macro_name: String, angle_span: Span) -> Result<Statement, ParserError> {
2087 match self.current_token.kind.clone() {
2089 TokenKind::Ident(arg_str) => {
2090 self.consume();
2091 let end_span = self.current_token.span.clone();
2092 self.match_kind(TokenKind::RightAngle)?;
2093 let full_span = Span { start: angle_span.start, end: end_span.end, file: angle_span.file };
2094
2095 if self.current_token.kind == TokenKind::OpenParen {
2097 tracing::info!(target: "parser", "PARSING ARG MACRO INVOCATION: {}()", arg_str);
2098 self.consume(); let mut args = Vec::new();
2102 while self.current_token.kind != TokenKind::CloseParen {
2103 let arg = self.parse_single_macro_argument()?;
2104 let arg = if let MacroArg::ArgCall(mut ac) = arg {
2105 ac.macro_name = parent_macro_name.clone();
2106 MacroArg::ArgCall(ac)
2107 } else {
2108 arg
2109 };
2110 args.push(arg);
2111
2112 if self.current_token.kind == TokenKind::Comma {
2113 self.consume();
2114 } else if self.current_token.kind != TokenKind::CloseParen {
2115 return Err(ParserError {
2116 kind: ParserErrorKind::InvalidTokenInMacroBody(self.current_token.kind.clone()),
2117 hint: Some("Expected ',' or ')' in macro argument list".to_string()),
2118 spans: AstSpan(vec![self.current_token.span.clone()]),
2119 cursor: self.cursor,
2120 });
2121 }
2122 }
2123
2124 self.match_kind(TokenKind::CloseParen)?; Ok(Statement {
2126 ty: StatementType::ArgMacroInvocation(parent_macro_name, arg_str, args),
2127 span: AstSpan(vec![full_span]),
2128 })
2129 } else {
2130 tracing::info!(target: "parser", "PARSING ARG CALL: {}", arg_str);
2131 Ok(Statement { ty: StatementType::ArgCall(parent_macro_name, arg_str), span: AstSpan(vec![full_span]) })
2132 }
2133 }
2134 kind => Err(ParserError {
2135 kind: ParserErrorKind::InvalidArgCallIdent(kind),
2136 hint: None,
2137 spans: AstSpan(vec![self.current_token.span.clone()]),
2138 cursor: self.cursor,
2139 }),
2140 }
2141 }
2142
2143 pub fn parse_nl_or_whitespace(&mut self) -> Result<(), ParserError> {
2145 while self.check(TokenKind::Whitespace) {
2146 self.consume();
2147 }
2148 Ok(())
2149 }
2150
2151 pub fn parse_arg_type(&mut self) -> Result<String, ParserError> {
2154 match self.current_token.kind.clone() {
2155 TokenKind::PrimitiveType(prim) => Ok(self.parse_primitive_type(prim)?.to_string()),
2156 TokenKind::ArrayType(prim, _) => {
2157 let token = self.current_token.kind.clone();
2161 let _ = self.parse_primitive_type(prim);
2162 Ok(token.to_string())
2163 }
2164 TokenKind::OpenParen => {
2165 self.consume();
2166 let mut components = vec![self.parse_tuple_component()?];
2167 while self.check(TokenKind::Comma) {
2168 self.consume();
2169 components.push(self.parse_tuple_component()?);
2170 }
2171 self.match_kind(TokenKind::CloseParen)?;
2172 let mut tuple = format!("({})", components.join(","));
2173 while self.check(TokenKind::OpenBracket) {
2175 self.consume();
2176 let size = match self.current_token.kind {
2177 TokenKind::Integer(size) => {
2178 self.consume();
2179 size.to_string()
2180 }
2181 _ => String::new(),
2182 };
2183 self.match_kind(TokenKind::CloseBracket)?;
2184 tuple.push('[');
2185 tuple.push_str(&size);
2186 tuple.push(']');
2187 }
2188 Ok(tuple)
2189 }
2190 kind => Err(ParserError {
2191 kind: ParserErrorKind::InvalidArgs(kind),
2192 hint: None,
2193 spans: AstSpan(vec![self.current_token.span.clone()]),
2194 cursor: self.cursor,
2195 }),
2196 }
2197 }
2198
2199 fn parse_tuple_component(&mut self) -> Result<String, ParserError> {
2201 let component = self.parse_arg_type()?;
2202 if matches!(self.current_token.kind, TokenKind::Ident(_)) {
2203 self.consume();
2204 }
2205 Ok(component)
2206 }
2207
2208 pub fn parse_primitive_type(&mut self, prim: PrimitiveEVMType) -> Result<TokenKind, ParserError> {
2211 match prim {
2212 PrimitiveEVMType::Uint(size) => {
2213 if !(8..=256).contains(&size) || size % 8 != 0 {
2214 return Err(ParserError {
2215 kind: ParserErrorKind::InvalidUint256(size),
2216 hint: None,
2217 spans: AstSpan(vec![self.current_token.span.clone()]),
2218 cursor: self.cursor,
2219 });
2220 }
2221 Ok(self.match_kind(self.current_token.kind.clone())?)
2222 }
2223 PrimitiveEVMType::Bytes(size) => {
2224 if !(1..=32).contains(&size) {
2225 return Err(ParserError {
2226 kind: ParserErrorKind::InvalidBytes(size),
2227 hint: None,
2228 spans: AstSpan(vec![self.current_token.span.clone()]),
2229 cursor: self.cursor,
2230 });
2231 }
2232 Ok(self.match_kind(self.current_token.kind.clone())?)
2233 }
2234 PrimitiveEVMType::Bool => Ok(self.match_kind(self.current_token.kind.clone())?),
2235 PrimitiveEVMType::Address => Ok(self.match_kind(self.current_token.kind.clone())?),
2236 PrimitiveEVMType::String => Ok(self.match_kind(self.current_token.kind.clone())?),
2237 PrimitiveEVMType::DynBytes => Ok(self.match_kind(self.current_token.kind.clone())?),
2238 PrimitiveEVMType::Int(size) => {
2239 if !(8..=256).contains(&size) || size % 8 != 0 {
2240 return Err(ParserError {
2241 kind: ParserErrorKind::InvalidInt(size),
2242 hint: None,
2243 spans: AstSpan(vec![self.current_token.span.clone()]),
2244 cursor: self.cursor,
2245 });
2246 }
2247 let curr_token_kind = self.current_token.kind.clone();
2248 self.consume();
2249 Ok(curr_token_kind)
2250 }
2251 }
2252 }
2253
2254 fn is_expression_context(&mut self) -> bool {
2257 if let Some(next_token) = self.peek() {
2258 matches!(next_token.kind, TokenKind::Add | TokenKind::Sub | TokenKind::Mul | TokenKind::Div | TokenKind::Mod)
2259 } else {
2260 false
2261 }
2262 }
2263
2264 fn parse_constant_expression(&mut self) -> Result<Expression, ParserError> {
2272 self.parse_comparison_expression()
2273 }
2274
2275 fn parse_comparison_expression(&mut self) -> Result<Expression, ParserError> {
2277 let mut left = self.parse_additive_expression()?;
2278
2279 while matches!(
2280 self.current_token.kind,
2281 TokenKind::EqualEqual
2282 | TokenKind::NotEqual
2283 | TokenKind::LeftAngle
2284 | TokenKind::RightAngle
2285 | TokenKind::LessEqual
2286 | TokenKind::GreaterEqual
2287 ) {
2288 let op = match self.current_token.kind {
2289 TokenKind::EqualEqual => BinaryOp::Eq,
2290 TokenKind::NotEqual => BinaryOp::NotEq,
2291 TokenKind::LeftAngle => BinaryOp::Lt,
2292 TokenKind::RightAngle => BinaryOp::Gt,
2293 TokenKind::LessEqual => BinaryOp::LtEq,
2294 TokenKind::GreaterEqual => BinaryOp::GtEq,
2295 _ => unreachable!(),
2296 };
2297 let op_span = self.current_token.span.clone();
2298 self.consume();
2299 let right = self.parse_additive_expression()?;
2300 let mut spans = left.span().inner_ref().to_vec();
2302 spans.push(op_span);
2303 spans.extend_from_slice(right.span().inner_ref());
2304 let span = AstSpan(spans);
2305 left = Expression::Binary { left: Box::new(left), op, right: Box::new(right), span };
2306 }
2307
2308 Ok(left)
2309 }
2310
2311 fn parse_additive_expression(&mut self) -> Result<Expression, ParserError> {
2313 let mut left = self.parse_multiplicative_expression()?;
2314
2315 while matches!(self.current_token.kind, TokenKind::Add | TokenKind::Sub) {
2316 let op = match self.current_token.kind {
2317 TokenKind::Add => BinaryOp::Add,
2318 TokenKind::Sub => BinaryOp::Sub,
2319 _ => unreachable!(),
2320 };
2321 let op_span = self.current_token.span.clone();
2322 self.consume();
2323 let right = self.parse_multiplicative_expression()?;
2324 let mut spans = left.span().inner_ref().to_vec();
2326 spans.push(op_span);
2327 spans.extend_from_slice(right.span().inner_ref());
2328 let span = AstSpan(spans);
2329 left = Expression::Binary { left: Box::new(left), op, right: Box::new(right), span };
2330 }
2331
2332 Ok(left)
2333 }
2334
2335 fn parse_multiplicative_expression(&mut self) -> Result<Expression, ParserError> {
2337 let mut left = self.parse_unary_expression()?;
2338
2339 while matches!(self.current_token.kind, TokenKind::Mul | TokenKind::Div | TokenKind::Mod) {
2340 let op = match self.current_token.kind {
2341 TokenKind::Mul => BinaryOp::Mul,
2342 TokenKind::Div => BinaryOp::Div,
2343 TokenKind::Mod => BinaryOp::Mod,
2344 _ => unreachable!(),
2345 };
2346 let op_span = self.current_token.span.clone();
2347 self.consume();
2348 let right = self.parse_unary_expression()?;
2349 let mut spans = left.span().inner_ref().to_vec();
2351 spans.push(op_span);
2352 spans.extend_from_slice(right.span().inner_ref());
2353 let span = AstSpan(spans);
2354 left = Expression::Binary { left: Box::new(left), op, right: Box::new(right), span };
2355 }
2356
2357 Ok(left)
2358 }
2359
2360 fn parse_unary_expression(&mut self) -> Result<Expression, ParserError> {
2362 if matches!(self.current_token.kind, TokenKind::Sub | TokenKind::Not) {
2363 let op = match self.current_token.kind {
2364 TokenKind::Sub => UnaryOp::Neg,
2365 TokenKind::Not => UnaryOp::Not,
2366 _ => unreachable!(),
2367 };
2368 let start_span = self.current_token.span.clone();
2369 self.consume();
2370 let expr = self.parse_unary_expression()?;
2371 let end_span = expr.span().inner_ref().last().cloned().unwrap_or_else(|| start_span.clone());
2373 let span = AstSpan(vec![start_span, end_span]);
2374 Ok(Expression::Unary { op, expr: Box::new(expr), span })
2375 } else {
2376 self.parse_primary_expression()
2377 }
2378 }
2379
2380 fn parse_primary_expression(&mut self) -> Result<Expression, ParserError> {
2382 match self.current_token.kind.clone() {
2383 TokenKind::HexLiteral(hex_str) => {
2384 let span = AstSpan(vec![self.current_token.span.clone()]);
2386 self.consume();
2387 Ok(Expression::Literal { value: str_to_bytes32(&hex_str), span })
2388 }
2389 TokenKind::Integer(n) => {
2390 let span = AstSpan(vec![self.current_token.span.clone()]);
2393 self.consume();
2394 let value = str_to_bytes32(&format!("{:x}", n));
2395 Ok(Expression::Literal { value, span })
2396 }
2397 TokenKind::OpenParen => {
2398 let start_span = self.current_token.span.clone();
2399 self.consume();
2400 let expr = self.parse_constant_expression()?;
2401 let end_span = self.current_token.span.clone();
2402 self.match_kind(TokenKind::CloseParen)?;
2403 let span = AstSpan(vec![start_span, end_span]);
2405 Ok(Expression::Grouped { expr: Box::new(expr), span })
2406 }
2407 TokenKind::OpenBracket => {
2408 let (name, full_span) = self.parse_constant_push()?;
2410 Ok(Expression::Constant { name, span: AstSpan(vec![full_span]) })
2411 }
2412 TokenKind::LeftAngle => {
2413 let start_span = self.current_token.span.clone();
2415 self.consume(); let arg_name = match self.current_token.kind.clone() {
2418 TokenKind::Ident(name) => {
2419 self.consume();
2420 name
2421 }
2422 _ => {
2423 return Err(ParserError {
2424 kind: ParserErrorKind::InvalidExpression(self.current_token.kind.clone()),
2425 hint: Some("Expected identifier after '<' in argument reference".to_string()),
2426 spans: AstSpan(vec![self.current_token.span.clone()]),
2427 cursor: self.cursor,
2428 });
2429 }
2430 };
2431
2432 let end_span = self.current_token.span.clone();
2433 self.match_kind(TokenKind::RightAngle)?; let span = AstSpan(vec![Span { start: start_span.start, end: end_span.end, file: start_span.file.clone() }]);
2437 if self.loop_variables.contains(&arg_name) {
2439 return Ok(Expression::Constant { name: format!("__LOOP_VAR_{arg_name}"), span });
2440 }
2441 Ok(Expression::ArgCall {
2442 macro_name: String::new(), name: arg_name,
2444 span,
2445 })
2446 }
2447 _ => Err(ParserError {
2448 kind: ParserErrorKind::InvalidExpression(self.current_token.kind.clone()),
2449 hint: Some("Expected literal, bracketed constant [NAME], arg call <name>, or '('".to_string()),
2450 spans: AstSpan(vec![self.current_token.span.clone()]),
2451 cursor: self.cursor,
2452 }),
2453 }
2454 }
2455}