hook up read from file
[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 }
169
170 void
171 enter_todoitem(State* state, char* item_name)
172 {
173     TodoItem* new_todoitem;
174
175     new_todoitem = malloc(sizeof(TodoItem));
176     new_todoitem->item_name = item_name;
177     new_todoitem->description = NULL;
178     new_todoitem->due = NULL;
179     new_todoitem->subtask_list = malloc(0);
180     new_todoitem->subtask_count = 0;
181
182     state->cur_todoitem = new_todoitem;
183     
184 }
185
186 void
187 exit_todoitem(State* state)
188 {
189     #define st state->cur_todolist
190
191     TodoList* todolist;
192     TodoItem** item_list;
193
194     if (state->cur_todoitem == NULL) return; 
195     
196     /* append current item to todo list */
197     todolist = state->cur_todolist;
198     item_list = todolist->item_list;
199
200     st->item_count += 1;
201     st->item_list = realloc(st->item_list, st->item_count*sizeof(TodoItem*));
202     st->item_list[st->item_count-1] = state->cur_todoitem;
203     state->cur_todoitem = NULL;
204
205 }
206
207 void
208 set_description(State* state, char* description)
209 {
210     state->cur_todoitem->description = description;
211 }
212
213 void
214 set_due(State* state, char* due)
215 {
216
217 }
218
219 void
220 add_subtask(State* state, char* subtask_name, SubTaskState subtask_state)
221 {
222     SubTask* new_subtask;
223     SubTask** subtask_list;
224     
225     /* create new subtask */
226     new_subtask = malloc(sizeof(SubTask));
227     new_subtask->subtask_name = subtask_name;
228     new_subtask->done = subtask_state;
229
230     /* add it */
231     subtask_list = state->cur_todoitem->subtask_list;
232
233     state->cur_todoitem->subtask_count += 1;
234     subtask_list = realloc(subtask_list, state->cur_todoitem->subtask_count*sizeof(SubTask*));
235     subtask_list[state->cur_todoitem->subtask_count-1] = new_subtask;
236
237     state->cur_todoitem->subtask_list = subtask_list;
238
239 }
240
241 int
242 enter_block(MD_BLOCKTYPE type, void* detail, void* userdata)
243 {
244     return 0;
245 }
246
247 int
248 leave_block(MD_BLOCKTYPE type, void* detail, void* userdata)
249 {
250     State* state;
251     state = (State*)userdata;
252
253     switch (type) {
254
255         case MD_BLOCK_H:;
256
257             MD_BLOCK_H_DETAIL* h_detail;
258             h_detail = ((MD_BLOCK_H_DETAIL*)detail);
259
260             switch(h_detail->level) {
261
262                 case 1:
263                     break;
264
265                 case 2:
266                     exit_todolist(state);
267                     enter_todolist(state, state->last_block_text);
268                     break;
269
270                 case 3:
271                     exit_todoitem(state);
272                     enter_todoitem(state, state->last_block_text);
273                     break;
274             }
275
276             break;
277
278         case MD_BLOCK_QUOTE:
279             set_description(state, state->last_block_text);
280             break;
281
282         case MD_BLOCK_LI:;
283             MD_BLOCK_LI_DETAIL* li_detail;
284             SubTaskState done;
285
286             li_detail = ((MD_BLOCK_LI_DETAIL*)detail);
287
288             assert(li_detail->is_task != 0); // all lists should be task lists
289
290             done = li_detail->task_mark == ' ' ? SubTaskState_todo : SubTaskState_done;
291
292             add_subtask(state, state->last_block_text, done);
293             break;
294
295         // no need for default case for now :>
296     }
297     return 0;
298 }
299
300 int
301 enter_span(MD_SPANTYPE type, void* detail, void* userdata)
302 {
303
304
305     return 0;
306 }
307
308 int
309 leave_span(MD_SPANTYPE type, void* detail, void* userdata)
310 {
311     State* state;
312     state = (State*)userdata;
313     
314     switch (type) {
315         case MD_SPAN_STRONG:
316             printf("date, %s\n", state->last_block_text);
317             break;
318     }
319     return 0;
320 }
321
322 int
323 text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata){
324
325     State* state;
326     char* content;
327
328     state = (State*)userdata;
329
330     content = malloc(size*sizeof(char)+1);
331     memcpy(content, text, size);
332     content[size] = 0;
333
334     /* printf("%s\n", content); */
335     state->last_block_text = content;
336     
337     return 0;
338 }
339
340 void
341 debug_log(const char* msg, void* userdata)
342 {
343     printf(msg);
344     return;
345 }
346
347 void 
348 syntax(void)
349 {
350     return;
351 }