1use crate::expr::op_code::parse_instruction;
2use crate::{Parse, ParseResult, ParseToEnd, Parser, ParserConsumed};
3
4use core::str::FromStr;
5use num_bigint::BigUint;
6
7use sway_ast::expr::asm::{
8 AsmBlock, AsmBlockContents, AsmFinalExpr, AsmImmediate, AsmRegisterDeclaration,
9};
10use sway_error::parser_error::ParseErrorKind;
11use sway_types::{Ident, Spanned};
12
13impl Parse for AsmBlock {
14 fn parse(parser: &mut Parser) -> ParseResult<AsmBlock> {
15 let asm_token = parser.parse()?;
16 let registers = parser.parse()?;
17 let contents = parser.parse()?;
18 Ok(AsmBlock {
19 asm_token,
20 registers,
21 contents,
22 })
23 }
24}
25
26impl Parse for AsmRegisterDeclaration {
27 fn parse(parser: &mut Parser) -> ParseResult<AsmRegisterDeclaration> {
28 let register = parser.parse()?;
29 let value_opt = match parser.take() {
30 Some(colon_token) => {
31 let value = parser.parse()?;
32 Some((colon_token, value))
33 }
34 None => None,
35 };
36 Ok(AsmRegisterDeclaration {
37 register,
38 value_opt,
39 })
40 }
41}
42
43impl ParseToEnd for AsmBlockContents {
44 fn parse_to_end<'a, 'e>(
45 mut parser: Parser<'a, '_>,
46 ) -> ParseResult<(AsmBlockContents, ParserConsumed<'a>)> {
47 let mut instructions = Vec::new();
48 let (final_expr_opt, consumed) = loop {
49 if let Some(consumed) = parser.check_empty() {
50 break (None, consumed);
51 }
52
53 let ident = match parser.take::<Ident>() {
57 Some(ident) => ident,
58 None => return Err(parser.emit_error(ParseErrorKind::ExpectedIdent)),
59 };
60
61 if let Some(consumed) = parser.check_empty() {
62 let final_expr = AsmFinalExpr {
63 register: ident,
64 ty_opt: None,
65 };
66 break (Some(final_expr), consumed);
67 }
68 if let Some(colon_token) = parser.take() {
69 let ty = parser.parse()?;
70 let consumed = match parser.check_empty() {
71 Some(consumed) => consumed,
72 None => {
73 return Err(
74 parser.emit_error(ParseErrorKind::UnexpectedTokenAfterAsmReturnType)
75 );
76 }
77 };
78 let final_expr = AsmFinalExpr {
79 register: ident,
80 ty_opt: Some((colon_token, ty)),
81 };
82 break (Some(final_expr), consumed);
83 }
84 let instruction = parse_instruction(ident, &mut parser)?;
85 let semicolon_token = parser.parse()?;
86 instructions.push((instruction, semicolon_token));
87 };
88 let contents = AsmBlockContents {
89 instructions,
90 final_expr_opt,
91 };
92 Ok((contents, consumed))
93 }
94}
95
96impl Parse for AsmImmediate {
97 fn parse(parser: &mut Parser) -> ParseResult<AsmImmediate> {
98 let ident = parser.parse::<Ident>()?;
99 let digits = ident
100 .as_str()
101 .strip_prefix('i')
102 .ok_or_else(|| parser.emit_error(ParseErrorKind::MalformedAsmImmediate))?;
103 let parsed = BigUint::from_str(digits)
104 .ok()
105 .ok_or_else(|| parser.emit_error(ParseErrorKind::MalformedAsmImmediate))?;
106 Ok(AsmImmediate {
107 span: ident.span(),
108 parsed,
109 })
110 }
111}