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