vb6parse/parsers/module.rs
1use crate::{
2 errors::{VB6Error, VB6ErrorKind},
3 language::VB6Token,
4 parsers::VB6Stream,
5 vb6::{keyword_parse, vb6_parse},
6};
7
8use serde::Serialize;
9use winnow::{
10 ascii::{line_ending, space0, space1},
11 token::take_until,
12 Parser,
13};
14
15/// Represents a VB6 module file.
16/// A VB6 module file contains a header and a list of tokens.
17///
18/// The tokens contain the token stream of the code of the class file.
19#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
20pub struct VB6ModuleFile<'a> {
21 pub name: &'a [u8], // Attribute VB_Name = "Module1"
22 pub tokens: Vec<VB6Token<'a>>,
23}
24
25impl<'a> VB6ModuleFile<'a> {
26 /// Parses a VB6 module file from a byte slice.
27 ///
28 /// # Arguments
29 ///
30 /// * `input` The byte slice to parse.
31 ///
32 /// # Returns
33 ///
34 /// A result containing the parsed VB6 module file or an error.
35 ///
36 /// # Errors
37 ///
38 /// An error will be returned if the input is not a valid VB6 module file.
39 ///
40 /// # Panics
41 ///
42 /// This function will panic if the source code is not a valid module file.
43 ///
44 /// # Example
45 ///
46 /// ```rust
47 /// use vb6parse::parsers::VB6ModuleFile;
48 ///
49 /// let input = b"Attribute VB_Name = \"Module1\"
50 /// Option Explicit
51 ///
52 /// Private Sub Class_Initialize()
53 /// End Sub
54 /// ";
55 ///
56 /// let result = VB6ModuleFile::parse("module.bas".to_owned(), input);
57 ///
58 /// assert!(result.is_ok());
59 /// ```
60 pub fn parse(file_name: String, source_code: &'a [u8]) -> Result<Self, VB6Error> {
61 let mut input = VB6Stream::new(file_name, source_code);
62
63 match (
64 space0,
65 keyword_parse("Attribute"),
66 space1,
67 keyword_parse("VB_Name"),
68 space0,
69 "=",
70 space0,
71 )
72 .parse_next(&mut input)
73 {
74 Ok(_) => {}
75 Err(e) => {
76 return Err(input.error(e.into_inner().unwrap()));
77 }
78 }
79
80 let name = match (
81 "\"",
82 take_until(0.., "\""),
83 "\"",
84 space0::<VB6Stream, VB6ErrorKind>,
85 line_ending,
86 )
87 .take()
88 .parse_next(&mut input)
89 {
90 Ok(name) => name,
91 Err(e) => {
92 return Err(input.error(e));
93 }
94 };
95
96 let tokens = match vb6_parse(&mut input) {
97 Ok(tokens) => tokens,
98 Err(e) => {
99 return Err(input.error(e.into_inner().unwrap()));
100 }
101 };
102
103 Ok(VB6ModuleFile { name, tokens })
104 }
105}