1use crate::ast::*;
4use crate::lexer::{Lexer, Token, TokenType};
5
6pub struct Parser {
8 lexer: Lexer,
9 cur: Token,
10 peek: Token,
11}
12
13impl Parser {
14 pub fn new(input: &str) -> Self {
15 let mut lexer = Lexer::new(input);
16 let cur = lexer.next_token();
17 let peek = lexer.next_token();
18 Self { lexer, cur, peek }
19 }
20
21 fn next_token(&mut self) {
22 self.cur = self.peek.clone();
23 self.peek = self.lexer.next_token();
24 }
25
26 fn expect(&self, t: TokenType) -> Result<(), String> {
27 if self.cur.typ != t {
28 Err(format!(
29 "expected {}, got {} at position {}",
30 t, self.cur.typ, self.cur.pos
31 ))
32 } else {
33 Ok(())
34 }
35 }
36
37 fn expect_symbol(&self, s: &str) -> Result<(), String> {
38 if self.cur.typ != TokenType::Symbol || self.cur.literal != s {
39 Err(format!(
40 "expected symbol {:?}, got {} {:?} at position {}",
41 s, self.cur.typ, self.cur.literal, self.cur.pos
42 ))
43 } else {
44 Ok(())
45 }
46 }
47
48 fn expect_identifier(&mut self) -> Result<String, String> {
49 if self.cur.typ == TokenType::Symbol {
50 let lit = self.cur.literal.clone();
51 self.next_token();
52 Ok(lit)
53 } else {
54 Err(format!(
55 "expected identifier, got {} at position {}",
56 self.cur.typ, self.cur.pos
57 ))
58 }
59 }
60
61 fn expect_guard_expr(&mut self) -> Result<String, String> {
62 if self.cur.typ == TokenType::Guard {
63 let lit = self.cur.literal.clone();
64 self.next_token();
65 Ok(lit)
66 } else {
67 Err(format!(
68 "expected guard expression, got {} at position {}",
69 self.cur.typ, self.cur.pos
70 ))
71 }
72 }
73
74 fn parse_schema(&mut self) -> Result<SchemaNode, String> {
75 self.expect(TokenType::LParen)?;
76 self.next_token();
77
78 self.expect_symbol("schema")?;
79 self.next_token();
80
81 let name = self.expect_identifier()?;
82 let mut node = SchemaNode {
83 name,
84 version: String::new(),
85 states: Vec::new(),
86 actions: Vec::new(),
87 arcs: Vec::new(),
88 constraints: Vec::new(),
89 };
90
91 while self.cur.typ != TokenType::RParen && self.cur.typ != TokenType::Eof {
92 if self.cur.typ != TokenType::LParen {
93 return Err(format!(
94 "expected '(' for clause, got {} at position {}",
95 self.cur.typ, self.cur.pos
96 ));
97 }
98 self.next_token();
99
100 if self.cur.typ != TokenType::Symbol {
101 return Err(format!(
102 "expected clause type, got {} at position {}",
103 self.cur.typ, self.cur.pos
104 ));
105 }
106
107 match self.cur.literal.as_str() {
108 "version" => {
109 self.next_token();
110 node.version = self.expect_identifier()?;
111 self.expect(TokenType::RParen)?;
112 self.next_token();
113 }
114 "states" => {
115 self.next_token();
116 node.states = self.parse_states()?;
117 self.expect(TokenType::RParen)?;
118 self.next_token();
119 }
120 "actions" => {
121 self.next_token();
122 node.actions = self.parse_actions()?;
123 self.expect(TokenType::RParen)?;
124 self.next_token();
125 }
126 "arcs" => {
127 self.next_token();
128 node.arcs = self.parse_arcs()?;
129 self.expect(TokenType::RParen)?;
130 self.next_token();
131 }
132 "constraints" => {
133 self.next_token();
134 node.constraints = self.parse_constraints()?;
135 self.expect(TokenType::RParen)?;
136 self.next_token();
137 }
138 other => {
139 return Err(format!(
140 "unknown clause type {:?} at position {}",
141 other, self.cur.pos
142 ));
143 }
144 }
145 }
146
147 Ok(node)
148 }
149
150 fn parse_states(&mut self) -> Result<Vec<StateNode>, String> {
151 let mut states = Vec::new();
152
153 while self.cur.typ == TokenType::LParen {
154 self.next_token();
155 self.expect_symbol("state")?;
156 self.next_token();
157
158 let id = self.expect_identifier()?;
159 let mut state = StateNode {
160 id,
161 typ: String::new(),
162 kind: "data".into(),
163 initial: None,
164 exported: false,
165 };
166
167 while self.cur.typ == TokenType::Keyword {
168 let keyword = self.cur.literal.clone();
169 self.next_token();
170
171 match keyword.as_str() {
172 ":type" => {
173 state.typ = self.expect_identifier()?;
174 }
175 ":kind" => {
176 self.expect(TokenType::Symbol)?;
177 state.kind = self.cur.literal.clone();
178 self.next_token();
179 }
180 ":initial" => {
181 state.initial = Some(self.parse_value()?);
182 }
183 ":exported" => {
184 state.exported = true;
185 }
186 other => {
187 return Err(format!(
188 "unknown state keyword {:?} at position {}",
189 other, self.cur.pos
190 ));
191 }
192 }
193 }
194
195 self.expect(TokenType::RParen)?;
196 self.next_token();
197 states.push(state);
198 }
199
200 Ok(states)
201 }
202
203 fn parse_actions(&mut self) -> Result<Vec<ActionNode>, String> {
204 let mut actions = Vec::new();
205
206 while self.cur.typ == TokenType::LParen {
207 self.next_token();
208 self.expect_symbol("action")?;
209 self.next_token();
210
211 let id = self.expect_identifier()?;
212 let mut action = ActionNode {
213 id,
214 guard: String::new(),
215 };
216
217 while self.cur.typ == TokenType::Keyword {
218 let keyword = self.cur.literal.clone();
219 self.next_token();
220
221 match keyword.as_str() {
222 ":guard" => {
223 action.guard = self.expect_guard_expr()?;
224 }
225 other => {
226 return Err(format!(
227 "unknown action keyword {:?} at position {}",
228 other, self.cur.pos
229 ));
230 }
231 }
232 }
233
234 self.expect(TokenType::RParen)?;
235 self.next_token();
236 actions.push(action);
237 }
238
239 Ok(actions)
240 }
241
242 fn parse_arcs(&mut self) -> Result<Vec<ArcNode>, String> {
243 let mut arcs = Vec::new();
244
245 while self.cur.typ == TokenType::LParen {
246 self.next_token();
247 self.expect_symbol("arc")?;
248 self.next_token();
249
250 let source = self.expect_identifier()?;
251
252 self.expect(TokenType::Arrow)?;
253 self.next_token();
254
255 let target = self.expect_identifier()?;
256
257 let mut arc = ArcNode {
258 source,
259 target,
260 keys: Vec::new(),
261 value: String::new(),
262 };
263
264 while self.cur.typ == TokenType::Keyword {
265 let keyword = self.cur.literal.clone();
266 self.next_token();
267
268 match keyword.as_str() {
269 ":keys" => {
270 arc.keys = self.parse_identifier_list()?;
271 }
272 ":value" => {
273 arc.value = self.expect_identifier()?;
274 }
275 other => {
276 return Err(format!(
277 "unknown arc keyword {:?} at position {}",
278 other, self.cur.pos
279 ));
280 }
281 }
282 }
283
284 self.expect(TokenType::RParen)?;
285 self.next_token();
286 arcs.push(arc);
287 }
288
289 Ok(arcs)
290 }
291
292 fn parse_constraints(&mut self) -> Result<Vec<ConstraintNode>, String> {
293 let mut constraints = Vec::new();
294
295 while self.cur.typ == TokenType::LParen {
296 self.next_token();
297 self.expect_symbol("constraint")?;
298 self.next_token();
299
300 let id = self.expect_identifier()?;
301 let expr = self.expect_guard_expr()?;
302
303 self.expect(TokenType::RParen)?;
304 self.next_token();
305 constraints.push(ConstraintNode { id, expr });
306 }
307
308 Ok(constraints)
309 }
310
311 fn parse_identifier_list(&mut self) -> Result<Vec<String>, String> {
312 self.expect(TokenType::LParen)?;
313 self.next_token();
314
315 let mut ids = Vec::new();
316 while self.cur.typ == TokenType::Symbol {
317 ids.push(self.cur.literal.clone());
318 self.next_token();
319 }
320
321 self.expect(TokenType::RParen)?;
322 self.next_token();
323
324 Ok(ids)
325 }
326
327 fn parse_value(&mut self) -> Result<InitialValue, String> {
328 match self.cur.typ {
329 TokenType::Number => {
330 let n: i64 = self
331 .cur
332 .literal
333 .parse()
334 .map_err(|e| format!("invalid number: {}", e))?;
335 self.next_token();
336 Ok(InitialValue::Int(n))
337 }
338 TokenType::Str => {
339 let s = self.cur.literal.clone();
340 self.next_token();
341 Ok(InitialValue::Str(s))
342 }
343 TokenType::Symbol if self.cur.literal == "nil" => {
344 self.next_token();
345 Ok(InitialValue::Nil)
346 }
347 _ => Err(format!(
348 "unexpected token {} in value position at {}",
349 self.cur.typ, self.cur.pos
350 )),
351 }
352 }
353}
354
355pub fn parse(input: &str) -> Result<SchemaNode, String> {
357 let mut p = Parser::new(input);
358 p.parse_schema()
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364
365 #[test]
366 fn test_parse_simple_schema() {
367 let input = r#"(schema ERC-020
368 (version v1.0.0)
369
370 (states
371 (state totalSupply :type uint256)
372 (state balances :type map[address]uint256 :exported)
373 )
374
375 (actions
376 (action transfer :guard {balances[from] >= amount})
377 )
378
379 (arcs
380 (arc balances -> transfer :keys (from))
381 (arc transfer -> balances :keys (to))
382 )
383
384 (constraints
385 (constraint conservation {sum(balances) == totalSupply})
386 )
387)"#;
388
389 let node = parse(input).unwrap();
390 assert_eq!(node.name, "ERC-020");
391 assert_eq!(node.version, "v1.0.0");
392 assert_eq!(node.states.len(), 2);
393 assert_eq!(node.actions.len(), 1);
394 assert_eq!(node.arcs.len(), 2);
395 assert_eq!(node.constraints.len(), 1);
396
397 assert_eq!(node.states[0].id, "totalSupply");
398 assert_eq!(node.states[1].id, "balances");
399 assert!(node.states[1].exported);
400
401 assert_eq!(node.actions[0].id, "transfer");
402 assert_eq!(node.actions[0].guard, "balances[from] >= amount");
403
404 assert_eq!(node.arcs[0].source, "balances");
405 assert_eq!(node.arcs[0].target, "transfer");
406 assert_eq!(node.arcs[0].keys, vec!["from"]);
407
408 assert_eq!(node.constraints[0].id, "conservation");
409 assert_eq!(node.constraints[0].expr, "sum(balances) == totalSupply");
410 }
411
412 #[test]
413 fn test_parse_token_state() {
414 let input = r#"(schema counter
415 (states
416 (state count :kind token :initial 5)
417 )
418 (actions
419 (action inc)
420 )
421 (arcs
422 (arc inc -> count)
423 )
424)"#;
425
426 let node = parse(input).unwrap();
427 assert_eq!(node.states[0].kind, "token");
428 match &node.states[0].initial {
429 Some(InitialValue::Int(5)) => {}
430 other => panic!("expected Int(5), got {:?}", other),
431 }
432 }
433}