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.strip_prefix("print").unwrap().trim();
26 let cleaned = message.trim_matches('"').to_string();
27 Ok(Statement::print(cleaned, line_number, 1))
28}
29
30pub fn parse_sleep(
32 mut parts: impl Iterator<Item = impl AsRef<str>>,
33 line_number: usize,
34) -> Result<Statement> {
35 let value = parts
36 .next()
37 .ok_or_else(|| anyhow!("sleep instruction requires a duration"))?;
38 let duration = parse_duration_token(value.as_ref())?;
39 Ok(Statement::new(
40 StatementKind::Sleep,
41 Value::Duration(duration),
42 0,
43 line_number,
44 1,
45 ))
46}
47
48pub fn parse_bank(
50 mut parts: impl Iterator<Item = impl AsRef<str>>,
51 line_number: usize,
52) -> Result<Statement> {
53 let name = parts
54 .next()
55 .ok_or_else(|| anyhow!("bank declaration requires a name"))?
56 .as_ref()
57 .to_string();
58
59 let alias = if let Some(word) = parts.next() {
60 if word.as_ref() == "as" {
61 parts.next().map(|v| v.as_ref().to_string())
62 } else {
63 None
64 }
65 } else {
66 None
67 };
68
69 Ok(Statement::new(
70 StatementKind::Bank { name, alias },
71 Value::Null,
72 0,
73 line_number,
74 1,
75 ))
76}
77
78pub fn parse_let(
80 line: &str,
81 mut parts: impl Iterator<Item = impl AsRef<str>>,
82 line_number: usize,
83) -> Result<Statement> {
84 let name = parts
85 .next()
86 .ok_or_else(|| anyhow!("let statement requires a name"))?
87 .as_ref()
88 .to_string();
89
90 let remainder = line
91 .splitn(2, '=')
92 .nth(1)
93 .map(|r| r.trim().to_string())
94 .unwrap_or_default();
95
96 let value = if remainder.is_empty() {
97 None
98 } else if remainder.starts_with("synth ") {
99 Some(parse_synth_definition(&remainder)?)
101 } else if remainder.starts_with('[') && remainder.ends_with(']') {
102 Some(parse_array_value(&remainder)?)
104 } else {
105 if let Ok(num) = remainder.parse::<f32>() {
107 Some(Value::Number(num))
108 } else {
109 Some(Value::Identifier(remainder))
111 }
112 };
113
114 Ok(Statement::new(
115 StatementKind::Let { name, value },
116 Value::Null,
117 0,
118 line_number,
119 1,
120 ))
121}
122
123pub fn parse_var(
125 line: &str,
126 mut parts: impl Iterator<Item = impl AsRef<str>>,
127 line_number: usize,
128) -> Result<Statement> {
129 let name = parts
130 .next()
131 .ok_or_else(|| anyhow!("var statement requires a name"))?
132 .as_ref()
133 .to_string();
134
135 let remainder = line
136 .splitn(2, '=')
137 .nth(1)
138 .map(|r| r.trim().to_string())
139 .unwrap_or_default();
140
141 let value = if remainder.is_empty() {
142 None
143 } else {
144 if let Ok(num) = remainder.parse::<f32>() {
146 Some(Value::Number(num))
147 } else {
148 Some(Value::Identifier(remainder))
150 }
151 };
152
153 Ok(Statement::new(
154 StatementKind::Var { name, value },
155 Value::Null,
156 0,
157 line_number,
158 1,
159 ))
160}
161
162pub fn parse_const(
164 line: &str,
165 mut parts: impl Iterator<Item = impl AsRef<str>>,
166 line_number: usize,
167) -> Result<Statement> {
168 let name = parts
169 .next()
170 .ok_or_else(|| anyhow!("const statement requires a name"))?
171 .as_ref()
172 .to_string();
173
174 let remainder = line
175 .splitn(2, '=')
176 .nth(1)
177 .map(|r| r.trim().to_string())
178 .unwrap_or_default();
179
180 if remainder.is_empty() {
181 return Err(anyhow!("const declaration requires initialization"));
182 }
183
184 let value = if let Ok(num) = remainder.parse::<f32>() {
186 Some(Value::Number(num))
187 } else {
188 Some(Value::Identifier(remainder))
190 };
191
192 Ok(Statement::new(
193 StatementKind::Const { name, value },
194 Value::Null,
195 0,
196 line_number,
197 1,
198 ))
199}