parse.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use super::*; 17 18 impl<N: Network> Parser for Output<N> { 19 /// Parses a string into an output statement. 20 /// The output statement is of the form `output {operand} as {register_type};`. 21 #[inline] 22 fn parse(string: &str) -> ParserResult<Self> { 23 // Parse the whitespace and comments from the string. 24 let (string, _) = Sanitizer::parse(string)?; 25 // Parse the output keyword from the string. 26 let (string, _) = tag(Self::type_name())(string)?; 27 // Parse the whitespace from the string. 28 let (string, _) = Sanitizer::parse_whitespaces(string)?; 29 // Parse the operand from the string. 30 let (string, operand) = Operand::parse(string)?; 31 // Parse the whitespace from the string. 32 let (string, _) = Sanitizer::parse_whitespaces(string)?; 33 // Parse the "as" from the string. 34 let (string, _) = tag("as")(string)?; 35 // Parse the whitespace from the string. 36 let (string, _) = Sanitizer::parse_whitespaces(string)?; 37 // Parse the register type from the string. 38 let (string, register_type) = RegisterType::parse(string)?; 39 // Parse the whitespace from the string. 40 let (string, _) = Sanitizer::parse_whitespaces(string)?; 41 // Parse the semicolon from the string. 42 let (string, _) = tag(";")(string)?; 43 // Return the output statement. 44 Ok((string, Self { operand, register_type })) 45 } 46 } 47 48 impl<N: Network> FromStr for Output<N> { 49 type Err = Error; 50 51 /// Parses a string into an output statement. 52 #[inline] 53 fn from_str(string: &str) -> Result<Self> { 54 match Self::parse(string) { 55 Ok((remainder, object)) => { 56 // Ensure the remainder is empty. 57 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 58 // Return the object. 59 Ok(object) 60 } 61 Err(error) => bail!("Failed to parse string. {error}"), 62 } 63 } 64 } 65 66 impl<N: Network> Debug for Output<N> { 67 /// Prints the output as a string. 68 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 69 Display::fmt(self, f) 70 } 71 } 72 73 impl<N: Network> Display for Output<N> { 74 /// Prints the output statement as a string. 75 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 76 write!( 77 f, 78 "{type_} {operand} as {register_type};", 79 type_ = Self::type_name(), 80 operand = self.operand, 81 register_type = self.register_type 82 ) 83 } 84 } 85 86 #[cfg(test)] 87 mod tests { 88 use super::*; 89 use console::{ 90 network::MainnetV0, 91 program::{Literal, Register, U8}, 92 }; 93 94 type CurrentNetwork = MainnetV0; 95 96 #[test] 97 fn test_output_parse() -> Result<()> { 98 // Register 99 let output = Output::<CurrentNetwork>::parse("output r0 as field;").unwrap().1; 100 assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(0))); 101 assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("field")?); 102 103 let output = Output::<CurrentNetwork>::parse("output 0u8 as u8;").unwrap().1; 104 assert_eq!(output.operand(), &Operand::Literal(Literal::<CurrentNetwork>::U8(U8::new(0)))); 105 assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("u8")?); 106 107 // Struct 108 let output = Output::<CurrentNetwork>::parse("output r1 as signature;").unwrap().1; 109 assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(1))); 110 assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("signature")?); 111 112 // Record 113 let output = Output::<CurrentNetwork>::parse("output r2 as token.record;").unwrap().1; 114 assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(2))); 115 assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("token.record")?); 116 117 Ok(()) 118 } 119 120 #[test] 121 fn test_output_display() { 122 // Register 123 let output = Output::<CurrentNetwork>::parse("output r0 as field;").unwrap().1; 124 assert_eq!(format!("{output}"), "output r0 as field;"); 125 126 // Literal 127 let output = Output::<CurrentNetwork>::parse("output 0u8 as u8;").unwrap().1; 128 assert_eq!(format!("{output}"), "output 0u8 as u8;"); 129 130 // Struct 131 let output = Output::<CurrentNetwork>::parse("output r1 as signature;").unwrap().1; 132 assert_eq!(format!("{output}"), "output r1 as signature;"); 133 134 // Record 135 let output = Output::<CurrentNetwork>::parse("output r2 as token.record;").unwrap().1; 136 assert_eq!(format!("{output}"), "output r2 as token.record;"); 137 } 138 }