yarnspinner_compiler/
compiler.rs1use crate::prelude::*;
5use std::path::Path;
6use yarnspinner_core::prelude::*;
7
8mod add_tags_to_lines;
9pub(crate) mod antlr_rust_ext;
10pub(crate) mod run_compilation;
11pub(crate) mod utils;
12
13#[allow(missing_docs)]
14pub type Result<T> = std::result::Result<T, CompilerError>;
15
16#[derive(Debug, Clone, PartialEq, Default)]
25#[cfg_attr(feature = "bevy", derive(Reflect))]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27#[cfg_attr(feature = "bevy", reflect(Debug, PartialEq))]
28#[cfg_attr(
29 all(feature = "bevy", feature = "serde"),
30 reflect(Serialize, Deserialize)
31)]
32pub struct Compiler {
33 pub files: Vec<File>,
35
36 #[cfg_attr(feature = "bevy", reflect(ignore))]
38 #[cfg_attr(feature = "serde", serde(skip))]
39 pub library: Library,
40
41 pub compilation_type: CompilationType,
43
44 pub variable_declarations: Vec<Declaration>,
46}
47
48impl Compiler {
49 pub fn new() -> Self {
51 Self::default()
52 }
53
54 pub fn add_file(&mut self, file: File) -> &mut Self {
56 self.files.push(file);
57 self
58 }
59
60 pub fn add_files(&mut self, files: impl IntoIterator<Item = File>) -> &mut Self {
62 self.files.extend(files);
63 self
64 }
65
66 pub fn try_read_file(&mut self, file_path: impl AsRef<Path>) -> std::io::Result<&mut Self> {
68 let file_name = file_path.as_ref().to_string_lossy().to_string();
69 let file_content = std::fs::read_to_string(file_path)?;
70 self.files.push(File {
71 file_name,
72 source: file_content,
73 });
74 Ok(self)
75 }
76
77 pub fn read_file(&mut self, file_path: impl AsRef<Path>) -> &mut Self {
79 self.try_read_file(file_path).unwrap()
80 }
81
82 pub fn extend_library(&mut self, library: Library) -> &mut Self {
84 self.library.extend(library);
85 self
86 }
87
88 pub fn with_compilation_type(&mut self, compilation_type: CompilationType) -> &mut Self {
90 self.compilation_type = compilation_type;
91 self
92 }
93
94 pub fn declare_variable(&mut self, declaration: Declaration) -> &mut Self {
96 self.variable_declarations.push(declaration);
97 self
98 }
99
100 pub fn compile(&self) -> Result<Compilation> {
102 run_compilation::compile(self)
103 }
104}
105
106#[derive(Debug, Clone, Eq, PartialEq, Hash)]
108#[cfg_attr(feature = "bevy", derive(Reflect))]
109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
110#[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Hash))]
111#[cfg_attr(
112 all(feature = "bevy", feature = "serde"),
113 reflect(Serialize, Deserialize)
114)]
115pub struct File {
116 pub file_name: String,
122
123 pub source: String,
125}
126
127#[derive(Debug, Clone, Default, Eq, PartialEq, Hash)]
129#[cfg_attr(feature = "bevy", derive(Reflect))]
130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131#[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Hash, Default))]
132#[cfg_attr(
133 all(feature = "bevy", feature = "serde"),
134 reflect(Serialize, Deserialize)
135)]
136pub enum CompilationType {
137 #[default]
140 FullCompilation,
141
142 DeclarationsOnly,
145
146 StringsOnly,
148}
149
150#[cfg(test)]
151mod test {
152 use super::*;
153
154 #[test]
155 fn can_call_compile_empty_without_crash() {
156 Compiler::new().compile().unwrap();
157 }
158
159 #[test]
160 fn can_call_compile_file_without_crash() {
161 let file = File {
162 file_name: "test.yarn".to_string(),
163 source: "title: test
164---
165foo
166bar
167a {1 + 3} cool expression
168==="
169 .to_string(),
170 };
171 Compiler::new().add_file(file).compile().unwrap();
172 }
173}