most parsing done
[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 = malloc(sizeof(State));
94     state->cur_todolist = NULL;
95     state->cur_todoitem = NULL;
96
97     new_board = malloc(sizeof(Board));
98     new_board->todolist_list = malloc(0);
99     new_board->todolist_count = 0;
100     state->board = new_board;
101
102     md_parse(input_buffer, input_size, &parser, state);
103
104     /* finish calls */
105     exit_todolist(state);
106
107     free((char*)input_buffer);
108
109     return state->board;
110 }
111
112 void
113 enter_todolist(State* state, char* list_name)
114 {
115     TodoList* new_todolist;
116     
117     new_todolist = malloc(sizeof(TodoList));
118     new_todolist->list_name = list_name;
119     new_todolist->item_list = malloc(0);
120     new_todolist->item_count = 0;
121
122     state->cur_todolist = new_todolist;
123 }
124
125 void
126 exit_todolist(State* state)
127 {
128     Board* board;
129     TodoList** todolist_list;
130
131     if (state->cur_todolist == NULL) { 
132         return;
133     }
134
135     exit_todoitem(state);
136
137     /* append new todolist to board */
138     board = state->board;
139     todolist_list = board->todolist_list;
140
141     board->todolist_count += 1;
142     todolist_list = realloc(todolist_list, board->todolist_count*sizeof(TodoList*));
143     todolist_list[board->todolist_count-1] = state->cur_todolist;
144     state->cur_todolist = NULL;
145
146     /* save */
147     board->todolist_list = todolist_list;
148
149 }
150
151 void
152 enter_todoitem(State* state, char* item_name)
153 {
154     TodoItem* new_todoitem;
155
156     new_todoitem = malloc(sizeof(TodoItem));
157     new_todoitem->item_name = item_name;
158     new_todoitem->description = NULL;
159     new_todoitem->due = NULL;
160     new_todoitem->subtask_list = malloc(0);
161     new_todoitem->subtask_count = 0;
162
163     state->cur_todoitem = new_todoitem;
164     
165 }
166
167 void
168 exit_todoitem(State* state)
169 {
170     TodoList* todolist;
171     TodoItem** item_list;
172
173     if (state->cur_todoitem == NULL) {
174         return;
175     }
176     
177     /* append current item to todo list */
178     todolist = state->cur_todolist;
179     item_list = todolist->item_list;
180
181     todolist->item_count += 1;
182     item_list = realloc(item_list, todolist->item_count*sizeof(TodoItem*));
183     item_list[todolist->item_count-1] = state->cur_todoitem;
184     state->cur_todoitem = NULL;
185
186     /* save */
187     todolist->item_list = item_list;
188
189 }
190
191 void
192 set_description(State* state, char* description)
193 {
194     state->cur_todoitem->description = description;
195 }
196
197 void
198 set_due(State* state, char* due)
199 {
200
201 }
202
203 void
204 add_subtask(State* state, char* subtask_name, SubTaskState subtask_state)
205 {
206     SubTask* new_subtask;
207     SubTask** subtask_list;
208     
209     /* create new subtask */
210     new_subtask = malloc(sizeof(SubTask));
211     new_subtask->subtask_name = subtask_name;
212     new_subtask->done = subtask_state;
213
214     /* add it */
215     subtask_list = state->cur_todoitem->subtask_list;
216
217     state->cur_todoitem->subtask_count += 1;
218     subtask_list = realloc(subtask_list, state->cur_todoitem->subtask_count*sizeof(SubTask*));
219     subtask_list[state->cur_todoitem->subtask_count-1] = new_subtask;
220
221     state->cur_todoitem->subtask_list = subtask_list;
222
223 }
224
225 int
226 enter_block(MD_BLOCKTYPE type, void* detail, void* userdata)
227 {
228     return 0;
229 }
230
231 int
232 leave_block(MD_BLOCKTYPE type, void* detail, void* userdata)
233 {
234     State* state;
235     state = (State*)userdata;
236
237     switch (type) {
238
239         case MD_BLOCK_H:;
240
241             MD_BLOCK_H_DETAIL* h_detail;
242             h_detail = ((MD_BLOCK_H_DETAIL*)detail);
243
244             switch(h_detail->level) {
245
246                 case 1:
247                     break;
248
249                 case 2:
250                     exit_todolist(state);
251                     enter_todolist(state, state->last_block_text);
252                     break;
253
254                 case 3:
255                     exit_todoitem(state);
256                     enter_todoitem(state, state->last_block_text);
257                     break;
258             }
259
260             break;
261
262         case MD_BLOCK_QUOTE:
263             set_description(state, state->last_block_text);
264             break;
265
266         case MD_BLOCK_LI:;
267             MD_BLOCK_LI_DETAIL* li_detail;
268             SubTaskState done;
269
270             li_detail = ((MD_BLOCK_LI_DETAIL*)detail);
271
272             assert(li_detail->is_task != 0); // all lists should be task lists
273
274             done = li_detail->task_mark == ' ' ? SubTaskState_todo : SubTaskState_done;
275
276             add_subtask(state, state->last_block_text, done);
277             break;
278
279         // no need for default case for now :>
280     }
281     return 0;
282 }
283
284 int
285 enter_span(MD_SPANTYPE type, void* detail, void* userdata)
286 {
287
288
289     return 0;
290 }
291
292 int
293 leave_span(MD_SPANTYPE type, void* detail, void* userdata)
294 {
295     State* state;
296     state = (State*)userdata;
297     
298     switch (type) {
299         case MD_SPAN_STRONG:
300             printf("date, %s\n", state->last_block_text);
301             break;
302     }
303     return 0;
304 }
305
306 int
307 text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata){
308
309     State* state;
310     char* content;
311
312     state = (State*)userdata;
313
314     content = malloc(size*sizeof(char)+1);
315     memcpy(content, text, size);
316     content[size] = 0;
317
318     /* printf("%s\n", content); */
319     state->last_block_text = content;
320     
321     return 0;
322 }
323
324 void
325 debug_log(const char* msg, void* userdata)
326 {
327     printf(msg);
328     return;
329 }
330
331 void 
332 syntax(void)
333 {
334     return;
335 }