1use std::ffi::{CStr, CString};
4use std::os::raw::c_char;
5
6use crate::syntax::*;
7
8extern "C" {
9 fn initialize_haskell();
10 fn exit_haskell();
11 fn amethyst_parser(code: *const c_char) -> *mut i32;
12 fn free_result(result_ptr: *mut i32);
13 fn move_type(move_ptr: *mut i32) -> i32;
15 fn transition_read_symbol(transition_ptr: *mut i32) -> c_char;
17 fn transition_write_symbol(transition_ptr: *mut i32) -> c_char;
18 fn transition_move_symbol(transition_ptr: *mut i32) -> *mut i32;
19 fn transition_new_state(transition_ptr: *mut i32) -> *mut c_char;
20 fn state_type(state_ptr: *mut i32) -> i32;
22 fn state_name(state_ptr: *mut i32) -> *mut c_char;
23 fn state_is_initial(state_ptr: *mut i32) -> bool;
24 fn state_tr_len(state_ptr: *mut i32) -> i32;
25 fn state_transitions(state_ptr: *mut i32) -> *mut i32;
26 fn state_transition_i(transitions_ptr: *mut i32, i: i32) -> *mut i32;
27 fn macro_type(macro_ptr: *mut i32) -> i32;
29 fn macro_string(macro_ptr: *mut i32) -> *mut c_char;
30 fn macro_number(macro_ptr: *mut i32) -> i32;
31 fn macro_move(macro_ptr: *mut i32) -> *mut i32;
32 fn macro_symbol(macro_ptr: *mut i32) -> c_char;
33 fn macro_list_len(macro_ptr: *mut i32) -> i32;
34 fn macro_list(macro_ptr: *mut i32) -> *mut i32;
35 fn macro_list_i(macro_ptr: *mut i32, i: i32) -> *mut c_char;
36 fn machine_components_len(machine_ptr: *mut i32) -> i32;
38 fn machine_components(machine_ptr: *mut i32) -> *mut i32;
39 fn machine_components_i_first(components_ptr: *mut i32, i: i32) -> *mut c_char;
40 fn machine_components_i_second(components_ptr: *mut i32, i: i32) -> *mut c_char;
41 fn machine_states_len(machine_ptr: *mut i32) -> i32;
42 fn machine_states(machine_ptr: *mut i32) -> *mut i32;
43 fn machine_states_i(states: *mut i32, i: i32) -> *mut i32;
44 fn automaton_type(automaton_ptr: *mut i32) -> i32;
46 fn automaton_name(automaton_ptr: *mut i32) -> *mut c_char;
47 fn automaton_machine(automaton_ptr: *mut i32) -> *mut i32;
48 fn automaton_macro(automaton_ptr: *mut i32) -> *mut i32;
49 fn result_type(result_ptr: *mut i32) -> i32;
51 fn result_program_len(program_ptr: *mut i32) -> i32;
52 fn program_automata(program_ptr: *mut i32) -> *mut i32;
53 fn program_automata_i(automata_ptr: *mut i32, i: i32) -> *mut i32;
54 fn error_string(error_ptr: *mut i32) -> *mut c_char;
55 fn error_line(error_ptr: *mut i32) -> i32;
56 fn error_column(error_ptr: *mut i32) -> i32;
57}
58
59fn parse_move(move_ptr: *mut i32) -> Move {
60 unsafe {
61 match move_type(move_ptr) {
62 0 => Move::Left,
63 1 => Move::Right,
64 2 => Move::Neutral,
65 _ => panic!("Unexpected move type"),
66 }
67 }
68}
69
70pub fn parse_transition(transition_ptr: *mut i32) -> Transition {
71 unsafe {
72 let read_symbol = transition_read_symbol(transition_ptr) as u8 as char;
73 let write_symbol = transition_write_symbol(transition_ptr) as u8 as char;
74 let move_ptr = transition_move_symbol(transition_ptr);
76 let move_symbol = parse_move(move_ptr);
77 let new_state = CStr::from_ptr(transition_new_state(transition_ptr))
79 .to_str()
80 .expect("Error converting CString to String")
81 .to_owned();
82
83 Transition {
84 read_symbol,
85 write_symbol,
86 move_symbol,
87 new_state,
88 }
89 }
90}
91
92pub fn parse_state(state_ptr: *mut i32) -> StateType {
93 unsafe {
94 let state_name = CStr::from_ptr(state_name(state_ptr))
95 .to_str()
96 .expect("Error converting CString to String")
97 .to_owned();
98 match state_type(state_ptr) {
99 0 => StateType::Accept(state_name),
100 1 => StateType::Reject(state_name),
101 2 => {
102 let initial = state_is_initial(state_ptr);
103 let transitions_len = state_tr_len(state_ptr);
104 let transitions_ptr = state_transitions(state_ptr);
105 let transitions = Box::new(
107 (0..transitions_len)
108 .map(|i| state_transition_i(transitions_ptr, i))
109 .map(parse_transition)
110 .collect(),
111 );
112 StateType::State(
113 state_name,
114 State {
115 initial,
116 transitions,
117 },
118 )
119 }
120 _ => panic!("Unexpected state type"),
121 }
122 }
123}
124
125pub fn parse_macro(macro_ptr: *mut i32) -> MacroType {
126 unsafe {
127 match macro_type(macro_ptr) {
128 0 => {
129 let macro_automaton = CStr::from_ptr(macro_string(macro_ptr))
130 .to_str()
131 .expect("Error converting CString to String")
132 .to_owned();
133 MacroType::Complement(macro_automaton)
134 }
135 1 => {
136 let automaton_list_len = macro_list_len(macro_ptr);
137 let automaton_list_ptr = macro_list(macro_ptr);
138 let automaton_list = Box::new(
140 (0..automaton_list_len)
141 .map(|i| macro_list_i(automaton_list_ptr, i))
142 .map(|s| {
143 CStr::from_ptr(s)
144 .to_str()
145 .expect("Error converting CString to String")
146 .to_owned()
147 })
148 .collect(),
149 );
150 MacroType::Intersect(automaton_list)
151 }
152 2 => {
153 let automaton_list_len = macro_list_len(macro_ptr);
154 let automaton_list_ptr = macro_list(macro_ptr);
155 let automaton_list = Box::new(
157 (0..automaton_list_len)
158 .map(|i| macro_list_i(automaton_list_ptr, i))
159 .map(|s| {
160 CStr::from_ptr(s)
161 .to_str()
162 .expect("Error converting CString to String")
163 .to_owned()
164 })
165 .collect(),
166 );
167 MacroType::Reunion(automaton_list)
168 }
169 3 => {
170 let automaton_list_len = macro_list_len(macro_ptr);
171 let automaton_list_ptr = macro_list(macro_ptr);
172 let automaton_list = Box::new(
174 (0..automaton_list_len)
175 .map(|i| macro_list_i(automaton_list_ptr, i))
176 .map(|s| {
177 CStr::from_ptr(s)
178 .to_str()
179 .expect("Error converting CString to String")
180 .to_owned()
181 })
182 .collect(),
183 );
184 MacroType::Chain(automaton_list)
185 }
186 4 => {
187 let number = macro_number(macro_ptr);
188 let automaton = CStr::from_ptr(macro_string(macro_ptr))
189 .to_str()
190 .expect("Error converting CString to String")
191 .to_owned();
192 MacroType::Repeat(number as u32, automaton)
193 }
194 5 => {
195 let number = macro_number(macro_ptr);
196 let move_symbol = parse_move(macro_move(macro_ptr));
197 MacroType::Move(move_symbol, number as u32)
198 }
199 6 => {
200 let number = macro_number(macro_ptr);
201 let move_symbol = parse_move(macro_move(macro_ptr));
202 let override_symbol = macro_symbol(macro_ptr) as u8 as char;
203 MacroType::Override(move_symbol, number as u32, override_symbol)
204 }
205 7 => {
206 let macro_text = CStr::from_ptr(macro_string(macro_ptr))
207 .to_str()
208 .expect("Error converting CString to String")
209 .to_owned();
210 MacroType::Place(macro_text)
211 }
212 8 => {
213 let number = macro_number(macro_ptr);
214 let move_symbol = parse_move(macro_move(macro_ptr));
215 MacroType::Shift(move_symbol, number as u32)
216 }
217 _ => panic!("Unexpected macro keyword type!"),
218 }
219 }
220}
221
222pub fn parse_machine(machine_ptr: *mut i32) -> Machine {
223 unsafe {
224 let comp_len = machine_components_len(machine_ptr);
225 let comp_list = machine_components(machine_ptr);
226 let components = Box::new(
227 (0..comp_len)
228 .map(|i| {
229 (
230 machine_components_i_first(comp_list, i),
231 machine_components_i_second(comp_list, i),
232 )
233 })
234 .map(|(s1, s2)| {
235 (
236 CStr::from_ptr(s1)
237 .to_str()
238 .expect("Error converting CString to String")
239 .to_owned(),
240 CStr::from_ptr(s2)
241 .to_str()
242 .expect("Error converting CString to String")
243 .to_owned(),
244 )
245 })
246 .collect(),
247 );
248 let states_len = machine_states_len(machine_ptr);
249 let states_list = machine_states(machine_ptr);
250 let states = Box::new(
251 (0..states_len)
252 .map(|i| machine_states_i(states_list, i))
253 .map(parse_state)
254 .collect(),
255 );
256 Machine { components, states }
257 }
258}
259
260pub fn parse_automaton(automaton_ptr: *mut i32) -> AutomatonType {
261 unsafe {
262 let automaton_name = CStr::from_ptr(automaton_name(automaton_ptr))
263 .to_str()
264 .expect("Error converting CString to String")
265 .to_owned();
266 match automaton_type(automaton_ptr) {
267 0 => AutomatonType::Machine(
268 automaton_name,
269 parse_machine(automaton_machine(automaton_ptr)),
270 ),
271
272 1 => AutomatonType::Macro(automaton_name, parse_macro(automaton_macro(automaton_ptr))),
273 _ => panic!("Unexpected automaton type"),
274 }
275 }
276}
277
278fn parse_program(program_ptr: *mut i32) -> Program {
279 unsafe {
280 let automaton_len = result_program_len(program_ptr);
281 let automata_list = program_automata(program_ptr);
282 let automata = Box::new(
283 (0..automaton_len)
284 .map(|i| program_automata_i(automata_list, i))
285 .map(parse_automaton)
286 .collect::<Vec<AutomatonType>>(),
287 );
288 Program { automata }
289 }
290}
291
292fn parse_error(error_ptr: *mut i32) -> String {
293 unsafe {
294 let error_string = CStr::from_ptr(error_string(error_ptr))
295 .to_str()
296 .expect("Error converting CString to String")
297 .to_owned();
298 let line = error_line(error_ptr);
299 let column = error_column(error_ptr);
300 return format!("Error: {} at line {} column {}", error_string, line, column);
301 }
302}
303
304pub fn parse_result(result_ptr: *mut i32) -> Result<Program, String> {
305 unsafe {
306 match result_type(result_ptr) {
307 0 => Ok(parse_program(result_ptr)),
308 1 => Err(parse_error(result_ptr)),
309 _ => panic!("Unexpected result type"),
310 }
311 }
312}
313
314pub fn parse_code(code: String) -> Result<Program, String> {
315 let result;
316 unsafe {
317 initialize_haskell();
318
319 let code_c = CString::new(code).expect("CString::new failed");
320 let result_ptr = amethyst_parser(code_c.as_ptr());
321 result = parse_result(result_ptr);
322 free_result(result_ptr);
323
324 exit_haskell();
325 }
326 result
327}