devalang_wasm/language/syntax/parser/driver/statements/
core.rs1use super::super::duration::parse_duration_token;
2use super::super::helpers::{parse_array_value, parse_synth_definition};
3use crate::language::syntax::ast::{Statement, StatementKind, Value};
4use anyhow::{Result, anyhow};
6use std::iter::Iterator;
7
8pub fn parse_tempo(
10 mut parts: impl Iterator<Item = impl AsRef<str>>,
11 line_number: usize,
12) -> Result<Statement> {
13 let value = parts
14 .next()
15 .ok_or_else(|| anyhow!("tempo declaration requires a value"))?;
16 let bpm: f32 = value
17 .as_ref()
18 .parse()
19 .map_err(|_| anyhow!("invalid tempo value: '{}'", value.as_ref()))?;
20 Ok(Statement::tempo(bpm, line_number, 1))
21}
22
23pub fn parse_print(line: &str, line_number: usize) -> Result<Statement> {
25 let message = line
26 .strip_prefix("print")
27 .ok_or_else(|| anyhow!("Invalid print statement: expected 'print' keyword at line {}", line_number))?
28 .trim();
29
30 if message.starts_with('"') && message.ends_with('"') && message.len() >= 2 {
33 let cleaned = message[1..message.len()-1].to_string();
34 Ok(Statement::new(StatementKind::Print, Value::String(cleaned), 0, line_number, 1))
35 } else if let Ok(num) = message.parse::<f32>() {
36 Ok(Statement::new(StatementKind::Print, Value::Number(num), 0, line_number, 1))
37 } else {
38 Ok(Statement::new(StatementKind::Print, Value::Identifier(message.to_string()), 0, line_number, 1))
40 }
41}
42
43pub fn parse_sleep(
45 mut parts: impl Iterator<Item = impl AsRef<str>>,
46 line_number: usize,
47) -> Result<Statement> {
48 let value = parts
49 .next()
50 .ok_or_else(|| anyhow!("sleep instruction requires a duration"))?;
51 let duration = parse_duration_token(value.as_ref())?;
52 Ok(Statement::new(
53 StatementKind::Sleep,
54 Value::Duration(duration),
55 0,
56 line_number,
57 1,
58 ))
59}
60
61pub fn parse_bank(
63 mut parts: impl Iterator<Item = impl AsRef<str>>,
64 line_number: usize,
65) -> Result<Statement> {
66 let name = parts
67 .next()
68 .ok_or_else(|| anyhow!("bank declaration requires a name"))?
69 .as_ref()
70 .to_string();
71
72 let alias = if let Some(word) = parts.next() {
73 if word.as_ref() == "as" {
74 parts.next().map(|v| v.as_ref().to_string())
75 } else {
76 None
77 }
78 } else {
79 None
80 };
81
82 Ok(Statement::new(
83 StatementKind::Bank { name, alias },
84 Value::Null,
85 0,
86 line_number,
87 1,
88 ))
89}
90
91pub fn parse_let(
93 line: &str,
94 mut parts: impl Iterator<Item = impl AsRef<str>>,
95 line_number: usize,
96) -> Result<Statement> {
97 let name = parts
98 .next()
99 .ok_or_else(|| anyhow!("let statement requires a name"))?
100 .as_ref()
101 .to_string();
102
103 let remainder = line
104 .splitn(2, '=')
105 .nth(1)
106 .map(|r| r.trim().to_string())
107 .unwrap_or_default();
108
109 let value = if remainder.is_empty() {
110 None
111 } else if remainder.starts_with("synth ") {
112 Some(parse_synth_definition(&remainder)?)
114 } else if remainder.starts_with('[') && remainder.ends_with(']') {
115 Some(parse_array_value(&remainder)?)
117 } else {
118 if let Ok(num) = remainder.parse::<f32>() {
120 Some(Value::Number(num))
121 } else {
122 Some(Value::Identifier(remainder))
124 }
125 };
126
127 Ok(Statement::new(
128 StatementKind::Let { name, value },
129 Value::Null,
130 0,
131 line_number,
132 1,
133 ))
134}
135
136pub fn parse_var(
138 line: &str,
139 mut parts: impl Iterator<Item = impl AsRef<str>>,
140 line_number: usize,
141) -> Result<Statement> {
142 let name = parts
143 .next()
144 .ok_or_else(|| anyhow!("var statement requires a name"))?
145 .as_ref()
146 .to_string();
147
148 let remainder = line
149 .splitn(2, '=')
150 .nth(1)
151 .map(|r| r.trim().to_string())
152 .unwrap_or_default();
153
154 let value = if remainder.is_empty() {
155 None
156 } else {
157 if let Ok(num) = remainder.parse::<f32>() {
159 Some(Value::Number(num))
160 } else {
161 Some(Value::Identifier(remainder))
163 }
164 };
165
166 Ok(Statement::new(
167 StatementKind::Var { name, value },
168 Value::Null,
169 0,
170 line_number,
171 1,
172 ))
173}
174
175pub fn parse_const(
177 line: &str,
178 mut parts: impl Iterator<Item = impl AsRef<str>>,
179 line_number: usize,
180) -> Result<Statement> {
181 let name = parts
182 .next()
183 .ok_or_else(|| anyhow!("const statement requires a name"))?
184 .as_ref()
185 .to_string();
186
187 let remainder = line
188 .splitn(2, '=')
189 .nth(1)
190 .map(|r| r.trim().to_string())
191 .unwrap_or_default();
192
193 if remainder.is_empty() {
194 return Err(anyhow!("const declaration requires initialization"));
195 }
196
197 let value = if let Ok(num) = remainder.parse::<f32>() {
199 Some(Value::Number(num))
200 } else {
201 Some(Value::Identifier(remainder))
203 };
204
205 Ok(Statement::new(
206 StatementKind::Const { name, value },
207 Value::Null,
208 0,
209 line_number,
210 1,
211 ))
212}