moving items between lists
[taskasaur.git] / parser.c
1
2 #include "headers/parser.h"
3
4 typedef struct State {
5     Board* board;
6     TodoList* cur_todolist;
7     TodoItem* cur_todoitem;
8     /* for use during processing */
9     char* last_block_text;
10 } State;
11
12 char* read_file(char* file_name, long* size);
13
14 /* processing */
15 void enter_todolist(State* state, char* list_name);
16 void exit_todolist(State* state);
17
18 void enter_todoitem(State* state, char* item_name);
19 void exit_todoitem(State* state);
20
21 void set_description(State* state, char* description);
22 void set_due(State* state, char* due); // make an acc date struct later
23 void add_subtask(State* state, char* subtask_name, SubTaskState subtask_state);
24
25 /* callbacks to parser */
26 int enter_block(MD_BLOCKTYPE type, void* detail, void* userdata);
27 int leave_block(MD_BLOCKTYPE type, void* detail, void* userdata);
28 int enter_span(MD_SPANTYPE type, void* detail, void* userdata);
29 int leave_span(MD_SPANTYPE type, void* detail, void* userdata);
30 int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata);
31 void debug_log(const char* msg, void* userdata);
32 void syntax(void);
33
34 const MD_PARSER parser = {
35     0,
36     MD_FLAG_TASKLISTS,
37     &enter_block,
38     &leave_block,
39     &enter_span,
40     &leave_span,
41     &text,
42     &debug_log,
43     &syntax
44 };
45
46
47 void
48 log_todo(Board* board)
49 {
50     for (int i = 0; i < board->todolist_count; i++) {
51         TodoList* todolist;
52         printf("List =-=-=-=-=-==-=-=-=-=-=-\n");
53         todolist = board->todolist_list[i];
54         printf("List name: %s\n", todolist->list_name);
55         printf("Num of items: %d\n", todolist->item_count);
56
57         for (int j = 0; j < todolist->item_count; j++) {
58             TodoItem* todoitem;
59             printf("Item =-=-=-=-=-\n");
60             todoitem = todolist->item_list[j];
61             printf("Item name: %s\n", todoitem->item_name);
62             printf("Description: %s\n", todoitem->description);
63             printf("Num of subtasks: %d\n", todoitem->subtask_count);
64
65             for (int k = 0; k < todoitem->subtask_count; k++) {
66                 SubTask* subtask;
67                 int done;
68
69                 subtask = todoitem->subtask_list[k];
70                 printf("Subtask: %s, %d\n", subtask->subtask_name, subtask->done);
71             }
72         }
73     }
74 }
75
76 Board*
77 begin_parse(char* board_path)
78 {
79     const char* input_buffer;
80     long input_size;
81     State state;
82     Board* new_board;
83
84     /* read entire file */
85     input_buffer = read_file(board_path, &input_size);
86
87     /* setup state */
88     state.cur_todolist = NULL;
89     state.cur_todoitem = NULL;
90
91     new_board = malloc(sizeof(Board));
92     new_board->todolist_list = malloc(0);
93     new_board->todolist_count = 0;
94     state.board = new_board;
95
96     md_parse(input_buffer, input_size, &parser, &state);
97
98     /* finish calls */
99     exit_todolist(&state);
100
101     free((char*)input_buffer);
102
103     return state.board;
104 }
105
106 char*
107 read_file(char* file_name, long* size) 
108 { // apparently using seek isnt the greatest, may change to chunk reading later
109     FILE* file;
110     char* output;
111     long fsize;
112
113     file = fopen(file_name, "r");
114     if (file == NULL) {
115         printf("Something went wrong opening file\n");
116         return NULL;
117     }
118
119     fseek(file, 0, SEEK_END);
120     fsize = ftell(file);
121     fseek(file, 0, SEEK_SET);
122
123     output = malloc(fsize+1); // maybe error check malloc
124     fread(output, 1, fsize, file);
125     if (ferror(file)) {
126         printf("Something went wrong reading file\n");
127         fclose(file);
128         free(output);
129         return NULL;
130     }
131     output[fsize] = 0; // add null terminator
132     
133     /* clean up */
134     fclose(file);
135
136     /* return */
137     *size = fsize;
138     return output;
139 }
140
141 void
142 enter_todolist(State* state, char* list_name)
143 {
144     TodoList* new_todolist;
145     
146     new_todolist = malloc(sizeof(TodoList));
147     new_todolist->list_name = list_name;
148     new_todolist->item_list = malloc(0);
149     new_todolist->item_count = 0;
150
151     state->cur_todolist = new_todolist;
152 }
153
154 void
155 exit_todolist(State* state)
156 {
157     #define sb state->board
158
159     if (state->cur_todolist == NULL) return; 
160
161     exit_todoitem(state);
162
163     sb->todolist_count += 1;
164     sb->todolist_list = realloc(sb->todolist_list, sb->todolist_count*sizeof(TodoList*));
165     sb->todolist_list[sb->todolist_count-1] = state->cur_todolist;
166     state->cur_todolist = NULL;
167
168     #undef sb
169 }
170
171 void
172 enter_todoitem(State* state, char* item_name)
173 {
174     TodoItem* new_todoitem;
175
176     new_todoitem = malloc(sizeof(TodoItem));
177     new_todoitem->item_name = item_name;
178     new_todoitem->description = NULL;
179     new_todoitem->due = NULL;
180     new_todoitem->subtask_list = malloc(0);
181     new_todoitem->subtask_count = 0;
182
183     state->cur_todoitem = new_todoitem;
184     
185 }
186
187 void
188 exit_todoitem(State* state)
189 {
190     #define st state->cur_todolist
191
192     TodoList* todolist;
193     TodoItem** item_list;
194
195     if (state->cur_todoitem == NULL) return; 
196     
197     /* append current item to todo list */
198     todolist = state->cur_todolist;
199     item_list = todolist->item_list;
200
201     st->item_count += 1;
202     st->item_list = realloc(st->item_list, st->item_count*sizeof(TodoItem*));
203     st->item_list[st->item_count-1] = state->cur_todoitem;
204     state->cur_todoitem = NULL;
205
206 }
207
208 void
209 set_description(State* state, char* description)
210 {
211     state->cur_todoitem->description = description;
212 }
213
214 void
215 set_due(State* state, char* due)
216 {
217
218 }
219
220 void
221 add_subtask(State* state, char* subtask_name, SubTaskState subtask_state)
222 {
223     SubTask* new_subtask;
224     SubTask** subtask_list;
225     
226     /* create new subtask */
227     new_subtask = malloc(sizeof(SubTask));
228     new_subtask->subtask_name = subtask_name;
229     new_subtask->done = subtask_state;
230
231     /* add it */
232     subtask_list = state->cur_todoitem->subtask_list;
233
234     state->cur_todoitem->subtask_count += 1;
235     subtask_list = realloc(subtask_list, state->cur_todoitem->subtask_count*sizeof(SubTask*));
236     subtask_list[state->cur_todoitem->subtask_count-1] = new_subtask;
237
238     state->cur_todoitem->subtask_list = subtask_list;
239
240 }
241
242 int
243 enter_block(MD_BLOCKTYPE type, void* detail, void* userdata)
244 {
245     return 0;
246 }
247
248 int
249 leave_block(MD_BLOCKTYPE type, void* detail, void* userdata)
250 {
251     State* state;
252     state = (State*)userdata;
253
254     switch (type) {
255
256         case MD_BLOCK_H:;
257
258             MD_BLOCK_H_DETAIL* h_detail;
259             h_detail = ((MD_BLOCK_H_DETAIL*)detail);
260
261             switch(h_detail->level) {
262
263                 case 1:
264                     break;
265
266                 case 2:
267                     exit_todolist(state);
268                     enter_todolist(state, state->last_block_text);
269                     break;
270
271                 case 3:
272                     exit_todoitem(state);
273                     enter_todoitem(state, state->last_block_text);
274                     break;
275             }
276
277             break;
278
279         case MD_BLOCK_QUOTE:
280             set_description(state, state->last_block_text);
281             break;
282
283         case MD_BLOCK_LI:;
284             MD_BLOCK_LI_DETAIL* li_detail;
285             SubTaskState done;
286
287             li_detail = ((MD_BLOCK_LI_DETAIL*)detail);
288
289             assert(li_detail->is_task != 0); // all lists should be task lists
290
291             done = li_detail->task_mark == ' ' ? SubTaskState_todo : SubTaskState_done;
292
293             add_subtask(state, state->last_block_text, done);
294             break;
295
296         // no need for default case for now :>
297     }
298     return 0;
299 }
300
301 int
302 enter_span(MD_SPANTYPE type, void* detail, void* userdata)
303 {
304
305
306     return 0;
307 }
308
309 int
310 leave_span(MD_SPANTYPE type, void* detail, void* userdata)
311 {
312     State* state;
313     state = (State*)userdata;
314     
315     switch (type) {
316         case MD_SPAN_STRONG:
317             printf("date, %s\n", state->last_block_text);
318             break;
319     }
320     return 0;
321 }
322
323 int
324 text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata){
325
326     State* state;
327     char* content;
328
329     state = (State*)userdata;
330
331     content = malloc(size*sizeof(char)+1);
332     memcpy(content, text, size);
333     content[size] = 0;
334
335     /* printf("%s\n", content); */
336     state->last_block_text = content;
337     
338     return 0;
339 }
340
341 void
342 debug_log(const char* msg, void* userdata)
343 {
344     printf(msg);
345     return;
346 }
347
348 void 
349 syntax(void)
350 {
351     return;
352 }