1use simple_colors::blue;
2
3use crate::node::*;
4use crate::{Token, TokenType, uid};
5use crate::user_output::CompileError;
6
7pub struct Parser<'a> {
8 tokens: &'a mut Vec<Token>,
9 ids: Vec<(String, usize)>
11}
12
13impl<'a> Parser<'a> {
14 pub fn new(tokens: &'a mut Vec<Token>) -> Self {
15 Self { tokens, ids: Vec::new() }
16 }
17
18 pub fn parse(&mut self) -> Vec<Box<dyn Node + Send + Sync>> {
19 let mut nodes: Vec<Box<dyn Node + Send + Sync>> = Vec::new();
20 while !self.tokens.is_empty() {
21 nodes.push(self.parse_next_statement());
22 }
23 nodes
24 }
25
26 fn parse_next_statement(&mut self) -> Box<dyn Node + Send + Sync> {
27 match self.tokens[0].ttype {
29 TokenType::Char => Box::new(self.parse_char()),
30 TokenType::Zombie => Box::new(self.parse_zombie()),
31 TokenType::Merchant => Box::new(self.parse_merchant()),
32 TokenType::Potion => Box::new(self.parse_potion()),
33 TokenType::SpellBook => Box::new(self.parse_spellbook()),
34 TokenType::Identifier => self.parse_identifier(),
35 other => crate::compile_error!("Unexpected token type at beginning of statement: {}", other.to_string())
36 }
37 }
38
39 fn parse_char(&mut self) -> node::Char {
40 self.consume(TokenType::Char);
41 let name = self.consume(TokenType::Identifier).value;
42 self.consume(TokenType::Equals);
43 self.consume(TokenType::OParen);
44 let health = self.consume(TokenType::Integer).value
45 .parse::<u32>()
46 .expect_compile_error(&format!(
47 "Character {} has an invalid value for its health.\n{} Characters can only have \
48 non-negative health. Their health must be an unsigned 32-bit integer.",
49 name,
50 simple_colors::cyan!("HELP:"))
51 );
52 self.consume(TokenType::Comma);
53 let attack = self.consume(TokenType::Integer).value
54 .parse::<u32>()
55 .expect_compile_error(&format!(
56 "Character {} has an invalid value for its attack.\n{} Attack must be non-negative. \
57 Attack is an unsigned 32-bit integer.",
58 name,
59 simple_colors::cyan!("HELP:"))
60 );
61 self.consume(TokenType::CParen);
62
63 let id = uid::generate_uid();
64 self.ids.push((name.clone(), id));
65
66 node::Char {
67 id,
68 name,
69 health,
70 attack
71 }
72 }
73
74 fn parse_zombie(&mut self) -> node::Zombie {
75 self.consume(TokenType::Zombie);
76 let name = self.consume(TokenType::Identifier).value;
77 self.consume(TokenType::Equals);
78 self.consume(TokenType::OParen);
79 let health = self.consume(TokenType::Integer).value
80 .parse::<i32>()
81 .expect_compile_error(&format!(
82 "Zombie {} has an invalid value for its health.\n{} Make sure you have put in an \
83 integer. Zombie's health are signed 32-bit integers.",
84 name,
85 simple_colors::cyan!("HELP:"))
86 );
87 self.consume(TokenType::Comma);
88 let attack = self.consume(TokenType::Integer).value
89 .parse::<u32>()
90 .expect_compile_error(&format!(
91 "Zombie {} has an invalid value for its attack.\n{} Attack must be non-negative. \
92 Attack is an unsigned 32-bit integer.",
93 name,
94 simple_colors::cyan!("HELP:"))
95 );
96 self.consume(TokenType::CParen);
97
98 let id = uid::generate_uid();
99 self.ids.push((name.clone(), id));
100
101 node::Zombie {
102 id,
103 name,
104 health,
105 attack
106 }
107 }
108
109 fn parse_merchant(&mut self) -> node::Merchant {
111 self.consume(TokenType::Merchant);
112 let name = self.consume(TokenType::Identifier).value;
113 self.consume(TokenType::Equals);
114 self.consume(TokenType::OParen);
115 self.consume(TokenType::CParen);
116
117 let id = uid::generate_uid();
118 self.ids.push((name.clone(), id));
119
120 node::Merchant {
121 id,
122 name
123 }
124 }
125
126 fn parse_potion(&mut self) -> node::Potion {
128 self.consume(TokenType::Potion);
129 let name = self.consume(TokenType::Identifier).value;
130 self.consume(TokenType::Equals);
131 self.consume(TokenType::OParen);
132 let value = self.consume(TokenType::Integer).value
133 .parse::<u32>()
134 .expect_compile_error(&format!(
135 "Potion {} has an invalid value for its healing value.\n{} Potions can only have \
136 non-negative healing values. Their value must be an unsigned 32-bit integer.",
137 name,
138 simple_colors::cyan!("HELP:"))
139 );
140 self.consume(TokenType::CParen);
141
142 let id = uid::generate_uid();
143 self.ids.push((name.clone(), id));
144
145 node::Potion {
146 id,
147 name,
148 value
149 }
150 }
151
152 fn parse_spellbook(&mut self) -> node::SpellBook {
154 self.consume(TokenType::SpellBook);
155 let name = self.consume(TokenType::Identifier).value;
156 self.consume(TokenType::Equals);
157 self.consume(TokenType::OParen);
158 self.consume(TokenType::CParen);
159
160 let id = uid::generate_uid();
161 self.ids.push((name.clone(), id));
162
163 node::SpellBook {
164 id,
165 name
166 }
167 }
168
169 fn parse_identifier(&mut self) -> Box<dyn Node + Send + Sync> {
171 let ident = self.consume(TokenType::Identifier);
172 return match {
173 if let Some(t) = self.peek_type(0) { t }
174 else { crate::compile_error!("Expected an action after identifier {}, but got none.", ident.value) }
175 } {
176 TokenType::FnBuys => Box::new(self.parse_fn_buys(&ident)),
177 TokenType::FnAttacks => Box::new(self.parse_fn_attacks(&ident)),
178 TokenType::FnShouts => self.parse_fn_shouts(&ident),
179 TokenType::FnWhispers => self.parse_fn_whispers(&ident),
180 TokenType::FnUses => self.parse_fn_uses(&ident),
181 TokenType::FnCasting => crate::compile_error!("Casting can not be used on its own. It has to be used alongside a `uses` action."),
182 v => crate::compile_error!("Expected an action after identifier {}, but got {}", ident.value, v.to_string())
183 }
184 }
185
186 fn parse_fn_buys(&mut self, ident: &Token) -> node::FnBuys {
188 let user = &ident.value;
189 self.consume(TokenType::FnBuys);
190 let item = self.consume(TokenType::Identifier).value;
191 self.consume(TokenType::From);
192 let merchant = self.consume(TokenType::Identifier).value;
193 let user_id = &self.ids.iter().find_map(|obj| {
194 if &obj.0 == user {
195 Some(obj.1)
196 } else {
197 None
198 }
199 }).expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", user, blue!("HINT:")));
200 let item_id = &self.ids.iter().find_map(|obj| {
202 if &obj.0 == &item {
203 Some(obj.1)
204 } else {
205 None
206 }
207 }).expect_compile_error(&format!("No item {} exists.\n{} Define the item before you use it.", item, blue!("HINT:")));
208 let merchant_id = &self.ids.iter().find_map(|obj| {
210 if &obj.0 == &merchant {
211 Some(obj.1)
212 } else {
213 None
214 }
215 }).expect_compile_error(&format!("No merchant {} exists.\n{} Define the merchant before you use it.", merchant, blue!("HINT:")));
216
217 node::FnBuys {
218 id: uid::generate_uid(),
219 user: *user_id,
220 item: *item_id,
221 merchant: *merchant_id
222 }
223 }
224
225 fn parse_fn_attacks(&mut self, ident: &Token) -> node::FnAttacks {
227 let attacker = &ident.value;
228 self.consume(TokenType::FnAttacks);
229 let attacked = self.consume(TokenType::Identifier).value;
230 let attacker_id = self.ids.iter().find_map(|obj| {
231 if &obj.0 == attacker {
232 Some(obj.1)
233 } else {
234 None
235 }
236 }).expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", attacker, blue!("HINT:")));
237 let attacked_id = self.ids.iter().find_map(|obj| {
238 if &obj.0 == &attacked {
239 Some(obj.1)
240 } else {
241 None
242 }
243 }).expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", attacked, blue!("HINT:")));
244
245 node::FnAttacks {
246 id: uid::generate_uid(),
247 attacked: attacked_id,
248 attacker: attacker_id
249 }
250 }
251
252 fn parse_fn_uses(&mut self, ident: &Token) -> Box<dyn Node + Send + Sync> {
253 let user = &ident.value;
254 self.consume(TokenType::FnUses);
255 let user_id = self.ids.iter().find_map(|obj| {
256 if &obj.0 == user {
257 Some(obj.1)
258 } else {
259 None
260 }
261 })
262 .expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", user, blue!("HINT:")));
263 let item_or_sb = self.consume(TokenType::Identifier).value;
264 let item_or_sb_id = self.ids.iter().find_map(|obj| {
265 if &obj.0 == &item_or_sb {
266 Some(obj.1)
267 } else {
268 None
269 }
270 })
271 .expect_compile_error(&format!("No item or spellbook {} exists.\n{} Define the item or spellbook before you use it.", item_or_sb, blue!("HINT:")));
272 if let Ok(is_casting) = self.peek(TokenType::FnCasting, 0) {
273 if is_casting {
274 self.consume(TokenType::FnCasting);
276 if let Some(spell) = self.peek_type(0) {
277 return match spell {
278 TokenType::SbFnUnZombify => Box::new(self.parse_spell_un_zombify(user_id, item_or_sb_id)),
279 TokenType::SbFnConfuse => Box::new(self.parse_spell_confuse(user_id, item_or_sb_id)),
280 TokenType::SbFnGodSpeech => Box::new(self.parse_spell_god_speech(user_id, item_or_sb_id)),
281 TokenType::SbFnTimeWarp => Box::new(self.parse_spell_time_warp(user_id, item_or_sb_id)),
282 TokenType::SbFnShift => Box::new(self.parse_spell_shift(user_id, item_or_sb_id)),
283 TokenType::SbFnCreatePotion => Box::new(self.parse_spell_pot(user_id, item_or_sb_id)),
284 val => crate::compile_error!("{}", &format!("Invalid spellbook spell: {}", val.to_string()))
285 }
286 }
287 }
288 }
289 Box::new(
291 FnUses {
292 id: uid::generate_uid(),
293 user: user_id,
294 item: item_or_sb_id
295 }
296 )
297 }
298
299 fn parse_spell_pot(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
300 self.consume(TokenType::SbFnCreatePotion);
301 self.consume(TokenType::OParen);
302 let potion = self.consume(TokenType::Identifier).value;
303 let potion_id = self.ids.iter().find_map(|obj| {
304 if &obj.0 == &potion {
305 Some(obj.1)
306 } else {
307 None
308 }
309 }).expect_compile_error(&format!("No potion {} exists.\n{} Define the potion before you use it.", potion, blue!("HINT:")));
310 self.consume(TokenType::CParen);
311
312 node::FnUsesCasting {
313 id: uid::generate_uid(),
314 user,
315 spell_book: sb,
316 function: SBFunction::CreatePot,
317 parameter: Some(potion_id),
318 body: None
319 }
320 }
321
322 fn parse_spell_shift(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
323 self.consume(TokenType::SbFnShift);
324 self.consume(TokenType::OParen);
325 self.consume(TokenType::CParen);
326
327 node::FnUsesCasting {
328 id: uid::generate_uid(),
329 user,
330 spell_book: sb,
331 function: SBFunction::Shift,
332 parameter: None,
333 body: None
334 }
335 }
336
337 fn parse_spell_un_zombify(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
338 self.consume(TokenType::SbFnUnZombify);
339 self.consume(TokenType::OParen);
340 let zombie = self.consume(TokenType::Identifier).value;
341 let zombie_id = self.ids.iter().find_map(|obj| {
342 if &obj.0 == &zombie {
343 Some(obj.1)
344 } else {
345 None
346 }
347 }).expect_compile_error(&format!("No zombie {} exists.\n{} Define the zombie before you use it.", zombie, blue!("HINT:")));
348 self.consume(TokenType::CParen);
349
350 node::FnUsesCasting {
351 id: uid::generate_uid(),
352 user,
353 spell_book: sb,
354 function: SBFunction::UnZombify,
355 parameter: Some(zombie_id),
356 body: None
357 }
358 }
359
360 fn parse_spell_confuse(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
361 self.consume(TokenType::SbFnConfuse);
362 self.consume(TokenType::OParen);
363 let confused_char = self.consume(TokenType::Identifier).value;
364 self.consume(TokenType::CParen);
365 let confused_char_id = self.ids.iter().find_map(|obj| {
366 if &obj.0 == &confused_char {
367 Some(obj.1)
368 } else {
369 None
370 }
371 }).expect_compile_error(&format!("No character or zombie {} exists.\n{} Define the character or zombie before you use it.", confused_char, blue!("HINT:")));
372
373 node::FnUsesCasting {
374 id: uid::generate_uid(),
375 user,
376 spell_book: sb,
377 function: SBFunction::Confuse,
378 parameter: Some(confused_char_id),
379 body: None
380 }
381 }
382
383 fn parse_spell_god_speech(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
384 self.consume(TokenType::SbFnGodSpeech);
385 self.consume(TokenType::OParen);
386 self.consume(TokenType::CParen);
387 node::FnUsesCasting {
388 id: uid::generate_uid(),
389 user,
390 spell_book: sb,
391 function: SBFunction::GodSpeech,
392 parameter: None,
393 body: None
394 }
395 }
396
397 fn parse_spell_time_warp(&mut self, user: usize, sb: usize) -> node::FnUsesCasting {
398 self.consume(TokenType::SbFnTimeWarp);
399 self.consume(TokenType::OParen);
400 let consumed = self.consume(TokenType::Identifier).value;
401 self.consume(TokenType::CParen);
402 let consumed_id = self.ids.iter().find_map(|obj| {
403 if &obj.0 == &consumed {
404 Some(obj.1)
405 } else {
406 None
407 }
408 }).expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", consumed, blue!("HINT:")));
409 let mut body: Vec<Box<dyn Node + Send + Sync>> = Vec::new();
410 while !self.peek(TokenType::End, 0).expect_compile_error("Expected time warp loop to end with `end`, but got none.") {
411 body.push(self.parse_next_statement());
412 }
413 self.consume(TokenType::End);
414 node::FnUsesCasting {
415 id: uid::generate_uid(),
416 user,
417 spell_book: sb,
418 function: SBFunction::TimeWarp,
419 parameter: Some(consumed_id),
420 body: Some(node::FnBody {
421 id: uid::generate_uid(),
422 body
423 })
424 }
425 }
426
427 fn parse_fn_shouts(&mut self, ident: &Token) -> Box<dyn Node + Send + Sync> {
429 self.consume(TokenType::FnShouts);
430 let user = &ident.value;
431 let user_id = self.ids.iter().find_map(|obj| if &obj.0 == user { Some(obj.1) } else { None })
432 .expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", user, blue!("HINT:")));
433 if let Ok(is_casting) = self.peek(TokenType::FnCasting, 1) {
434 if let Ok(is_speak) = self.peek(TokenType::SbFnSpeak, 2) {
435 if is_casting && is_speak {
436 let spellbook = self.consume(TokenType::Identifier).value;
437 let sb_id = self.ids.iter().find_map(|obj| if &obj.0 == &spellbook { Some(obj.1) } else { None })
438 .expect_compile_error(&format!("No spellbook {} exists.\n{} Define the spellbook before you use it.", spellbook, blue!("HINT:")));
439 self.consume(TokenType::FnCasting);
440 self.consume(TokenType::SbFnSpeak);
441 self.consume(TokenType::OParen);
442 self.consume(TokenType::CParen);
443 return Box::new(node::FnShoutsSpeak {
444 id: uid::generate_uid(),
445 user: user_id,
446 spell_book: sb_id
447 });
448 }
449 }
450 }
451 Box::new(
452 node::FnShouts {
453 id: uid::generate_uid(),
454 user: user_id
455 }
456 )
457 }
458
459 fn parse_fn_whispers(&mut self, ident: &Token) -> Box<dyn Node + Send + Sync> {
460 self.consume(TokenType::FnWhispers);
461 let user = &ident.value;
462 let user_id = self.ids.iter().find_map(|obj| if &obj.0 == user { Some(obj.1) } else { None })
463 .expect_compile_error(&format!("No character {} exists.\n{} Define the character before you use it.", user, blue!("HINT:")));
464 if let Ok(is_casting) = self.peek(TokenType::FnCasting, 1) {
465 if let Ok(is_speak) = self.peek(TokenType::SbFnSpeak, 2) {
466 if is_casting && is_speak {
467 let spellbook = self.consume(TokenType::Identifier).value;
468 let sb_id = self.ids.iter().find_map(|obj| if &obj.0 == &spellbook { Some(obj.1) } else { None })
469 .expect_compile_error(&format!("No spellbook {} exists.\n{} Define the spellbook before you use it.", spellbook, blue!("HINT:")));
470 self.consume(TokenType::FnCasting);
471 self.consume(TokenType::SbFnSpeak);
472 self.consume(TokenType::OParen);
473 self.consume(TokenType::CParen);
474 return Box::new(node::FnWhispersSpeak {
475 id: uid::generate_uid(),
476 user: user_id,
477 spell_book: sb_id
478 });
479 }
480 }
481 }
482 Box::new(
483 node::FnWhispers {
484 id: uid::generate_uid(),
485 user: user_id
486 }
487 )
488 }
489
490 fn consume(&mut self, expected_type: TokenType) -> Token {
494 let token = self.tokens.remove(0);
495 if token.ttype == expected_type {
496 token
497 } else {
498 crate::compile_error!("Expected token type {} but got {}", expected_type.to_string(), token.ttype.to_string())
499 }
500 }
501
502 fn peek_type(&self, offset: usize) -> Option<TokenType> {
505 if let Some(token) = self.tokens.get(offset) {
506 return Some(token.ttype);
507 } else {
508 None
509 }
510 }
511
512 fn peek(&self, expected_type: TokenType, offset: usize) -> Result<bool, String> {
517 if let Some(token) = self.tokens.get(offset) {
518 Ok(token.ttype == expected_type)
519 } else {
520 Err("Incomplete syntax".to_string())
521 }
522 }
523}
524
525pub mod node {
526 use std::any::Any;
527 use std::fmt;
528 use crate::{impl_node, new_node};
529
530 new_node!(Char, name: String, health: u32, attack: u32);
531
532 new_node!(Zombie, name: String, health: i32, attack: u32);
533
534 new_node!(Merchant, name: String);
535
536 new_node!(Potion, name: String, value: u32);
537 impl Item for Potion {}
538
539 new_node!(SpellBook, name: String);
540 impl Item for SpellBook {}
541
542 new_node!(FnBuys, user: usize, item: usize, merchant: usize);
545
546 new_node!(FnUses, user: usize, item: usize);
548
549 new_node!(FnUsesCasting, user: usize, spell_book: usize, function: SBFunction, parameter: Option<usize>, body: Option<FnBody>);
550
551 new_node!(FnBody, body: Vec<Box<dyn Node + Send + Sync>>);
552
553 new_node!(FnAttacks, attacked: usize, attacker: usize);
554
555 new_node!(FnShouts, user: usize);
556 new_node!(FnShoutsSpeak, user: usize, spell_book: usize);
557
558 new_node!(FnWhispers, user: usize);
559 new_node!(FnWhispersSpeak, user: usize, spell_book: usize);
560
561 #[derive(Debug, PartialEq)]
562 pub enum NodeType {
563 Char,
564 Zombie,
565 Merchant,
566 Potion,
567 SpellBook,
568 FnBuys,
569 FnAttacks,
570 FnUses,
571 FnShouts,
572 FnShoutsSpeak,
574 FnWhispers,
575 FnWhispersSpeak,
577 FnUsesCasting,
579 FnBody
582 }
583
584 #[derive(Clone, Copy, Debug)]
585 pub enum SBFunction {
587 UnZombify,
588 Confuse,
589 GodSpeech,
590 TimeWarp,
591 Shift,
592 CreatePot
593 }
595
596 #[macro_export]
597 macro_rules! new_node {
598 ( $name: ident, $($field: ident: $type: ty),* ) => (
599 #[derive(Debug, Clone)]
600 pub struct $name {
601 pub id: usize,
602 $(pub $field: $type),*
603 }
604
605 unsafe impl Send for $name {}
606 unsafe impl Sync for $name {}
607
608 impl Node for $name {
609 impl_node!{NodeType::$name}
610 }
611 )
612 }
613
614 #[macro_export]
615 macro_rules! impl_node {
617 ( $type: expr ) => (
618 fn get_type(&self) -> NodeType {
619 $type
620 }
621
622 fn as_any(&self) -> &dyn Any {
623 self
624 }
625
626 fn get_id(&self) -> usize {
627 self.id
628 }
629 )
630 }
631
632 pub trait Node: fmt::Debug + NodeClone + Send + Sync {
633 fn get_type(&self) -> NodeType;
634 fn as_any(&self) -> &dyn Any;
635 fn get_id(&self) -> usize;
636 }
637
638 pub trait Item: fmt::Debug + ItemClone {}
639
640 pub trait NodeClone {
642 fn clone_box(&self) -> Box<dyn Node + Send + Sync>;
643 }
644
645 impl<T> NodeClone for T
646 where T: 'static + Node + Clone
647 {
648 fn clone_box(&self) -> Box<dyn Node + Send + Sync> {
649 Box::new(self.clone())
650 }
651 }
652
653 impl Clone for Box<dyn Node + Send + Sync> {
654 fn clone(&self) -> Box<dyn Node + Send + Sync> {
655 self.clone_box()
656 }
657 }
658
659 pub trait ItemClone {
660 fn clone_box(&self) -> Box<dyn Item>;
661 }
662
663 impl<T> ItemClone for T
664 where T: 'static + Item + Clone
665 {
666 fn clone_box(&self) -> Box<dyn Item> {
667 Box::new(self.clone())
668 }
669 }
670
671 impl Clone for Box<dyn Item> {
672 fn clone(&self) -> Box<dyn Item> {
673 self.clone_box()
674 }
675 }
676
677 pub fn parse_dyn_node<NodeType: 'static>(n: &dyn Node) -> &NodeType {
678 let parse_node: &NodeType = match n.as_any().downcast_ref::<NodeType>() {
679 Some(n) => n,
680 None => crate::compile_error!("Expected wrong type")
681 };
682 parse_node
683 }
684}