1use crate::{
2 ast::{
3 BooleanMethod, BooleanMethodKind, Command, Condition, Conditional, ConditionalKind, Flow,
4 FlowKind, IntegerMethod, IntegerMethodKind, Start, Value,
5 },
6 parser::Parser,
7};
8use std::collections::VecDeque;
9use topcodes::TopCode;
10
11pub fn parse(topcodes: &Vec<TopCode>) -> Option<Start> {
12 Parser::new(topcodes).parse()
13}
14
15pub fn start() -> TangiblStartBuilder {
16 TangiblStartBuilder::default()
17}
18
19pub fn flow() -> TangiblFlowBuilder {
20 TangiblFlowBuilder::default()
21}
22
23#[derive(Default, Debug)]
24pub struct TangiblStartBuilder {
25 flow_builder: TangiblFlowBuilder,
27}
28
29impl TangiblStartBuilder {
30 pub fn with_command(&mut self, command: Command) -> &mut Self {
31 self.flow_builder.with_command(command);
32 self
33 }
34
35 pub fn with_conditional(
36 &mut self,
37 conditional_kind: ConditionalKind,
38 alternate: Option<Flow>,
39 ) -> &mut Self {
40 self.flow_builder.with_conditional(Conditional {
41 kind: conditional_kind,
42 alternate: alternate.map(Box::new),
43 });
44 self
45 }
46
47 pub fn with_boolean_method(
48 &mut self,
49 boolean_method_kind: BooleanMethodKind,
50 condition: Option<Condition>,
51 body: Option<Flow>,
52 ) -> &mut Self {
53 self.flow_builder
54 .with_boolean_method(boolean_method_kind, condition, body);
55 self
56 }
57
58 pub fn with_integer_method(
59 &mut self,
60 integer_method_kind: IntegerMethodKind,
61 value: Option<Value>,
62 body: Option<Flow>,
63 ) -> &mut Self {
64 self.flow_builder
65 .with_integer_method(integer_method_kind, value, body);
66 self
67 }
68
69 pub fn build(&mut self) -> Start {
70 Start {
71 next: self.flow_builder.build(),
72 }
73 }
74}
75
76#[derive(Default, Debug)]
77pub struct TangiblFlowBuilder {
78 nodes: VecDeque<Flow>,
79}
80
81impl TangiblFlowBuilder {
82 pub fn with_command(&mut self, command: Command) -> &mut Self {
83 self.with_flow(Flow::new(FlowKind::Command(command)));
84 self
85 }
86
87 pub fn with_conditional(&mut self, conditional: Conditional) -> &mut Self {
88 self.with_flow(Flow::new(FlowKind::Conditional(conditional)));
89 self
90 }
91
92 pub fn with_boolean_method(
93 &mut self,
94 boolean_method_kind: BooleanMethodKind,
95 condition: Option<Condition>,
96 body: Option<Flow>,
97 ) -> &mut Self {
98 self.with_flow(Flow::new(FlowKind::BooleanMethod(BooleanMethod {
99 kind: boolean_method_kind,
100 condition,
101 body: body.map(Box::new),
102 })));
103 self
104 }
105
106 pub fn with_integer_method(
107 &mut self,
108 integer_method_kind: IntegerMethodKind,
109 value: Option<Value>,
110 body: Option<Flow>,
111 ) -> &mut Self {
112 self.with_flow(Flow::new(FlowKind::IntegerMethod(IntegerMethod {
113 kind: integer_method_kind,
114 value,
115 body: body.map(Box::new),
116 })));
117 self
118 }
119
120 pub fn build(&mut self) -> Option<Flow> {
121 let mut current = None;
122 while let Some(mut node) = self.nodes.pop_back() {
123 match current {
124 None => current = Some(node),
125 Some(_) => {
126 node.next = current.map(Box::new);
127 current = Some(node);
128 }
129 }
130 }
131 current
132 }
133
134 fn with_flow(&mut self, flow: Flow) -> &mut Self {
135 self.nodes.push_back(flow);
136 self
137 }
138}