c8c4db58586093843b294ceb24d9d90a9506347a
[claws.git] / src / matcher_parser_parse.y
1 %{
2 #include "filtering.h"
3 #include "scoring.h"
4 #include "matcher.h"
5 #include "matcher_parser.h"
6 #include "matcher_parser_lex.h"
7 #include "intl.h"
8 #include <glib.h>
9
10 static gint error = 0;
11 static gint bool_op = 0;
12 static gint match_type = 0;
13 static gchar * header = NULL;
14
15 static MatcherProp * prop;
16
17 static GSList * matchers_list = NULL;
18
19 static MatcherList * cond;
20 static gint score = 0;
21 static FilteringAction * action = NULL;
22
23 static FilteringProp *  filtering;
24 static ScoringProp * scoring = NULL;
25
26 static GSList ** prefs_scoring = NULL;
27 static GSList ** prefs_filtering = NULL;
28
29 static int matcher_parser_dialog = 0;
30
31 FilteringProp * matcher_parser_get_filtering(gchar * str)
32 {
33         void * bufstate;
34
35         matcher_parserlineno = 1;
36         matcher_parser_dialog = 1;
37         bufstate = matcher_parser_scan_string(str);
38         matcher_parserparse();
39         matcher_parser_dialog = 0;
40         matcher_parser_delete_buffer(bufstate);
41         return filtering;
42 }
43
44 ScoringProp * matcher_parser_get_scoring(gchar * str)
45 {
46         void * bufstate;
47
48         matcher_parserlineno = 1;
49         matcher_parser_dialog = 1;
50         bufstate = matcher_parser_scan_string(str);
51         matcher_parserparse();
52         matcher_parser_dialog = 0;
53         matcher_parser_delete_buffer(bufstate);
54         return scoring;
55 }
56
57 MatcherList * matcher_parser_get_cond(gchar * str)
58 {
59         void * bufstate;
60
61         matcher_parserlineno = 1;
62         matcher_parser_dialog = 1;
63         bufstate = matcher_parser_scan_string(str);
64         matcher_parserparse();
65         matcher_parser_dialog = 0;
66         matcher_parser_delete_buffer(bufstate);
67         return cond;
68 }
69
70 MatcherProp * matcher_parser_get_prop(gchar * str)
71 {
72         MatcherList * list;
73         MatcherProp * prop;
74
75         matcher_parserlineno = 1;
76         list = matcher_parser_get_cond(str);
77         if (list == NULL)
78                 return NULL;
79
80         if (list->matchers == NULL)
81                 return NULL;
82
83         if (list->matchers->next != NULL)
84                 return NULL;
85
86         prop = list->matchers->data;
87
88         g_slist_free(list->matchers);
89         g_free(list);
90 }
91
92 void matcher_parsererror(char * str)
93 {
94         GSList * l;
95
96         if (matchers_list) {
97                 for(l = matchers_list ; l != NULL ;
98                     l = g_slist_next(l))
99                         matcherprop_free((MatcherProp *)
100                                          l->data);
101                 g_slist_free(matchers_list);
102                 matchers_list = NULL;
103         }
104
105         g_warning(_("scoring / filtering parsing: %i: %s\n"),
106                   matcher_parserlineno, str);
107         error = 1;
108 }
109
110 int matcher_parserwrap(void)
111 {
112         return 1;
113 }
114 %}
115
116 %union {
117         char * str;
118         int value;
119 }
120
121 %token MATCHER_ALL MATCHER_UNREAD  MATCHER_NOT_UNREAD 
122 %token MATCHER_NEW  MATCHER_NOT_NEW  MATCHER_MARKED
123 %token MATCHER_NOT_MARKED  MATCHER_DELETED  MATCHER_NOT_DELETED
124 %token MATCHER_REPLIED  MATCHER_NOT_REPLIED  MATCHER_FORWARDED
125 %token MATCHER_NOT_FORWARDED  MATCHER_SUBJECT  MATCHER_NOT_SUBJECT
126 %token MATCHER_FROM  MATCHER_NOT_FROM  MATCHER_TO  MATCHER_NOT_TO
127 %token MATCHER_CC  MATCHER_NOT_CC  MATCHER_TO_OR_CC  MATCHER_NOT_TO_AND_NOT_CC
128 %token MATCHER_AGE_GREATER  MATCHER_AGE_LOWER  MATCHER_NEWSGROUPS
129 %token MATCHER_NOT_NEWSGROUPS  MATCHER_INREPLYTO  MATCHER_NOT_INREPLYTO
130 %token MATCHER_REFERENCES  MATCHER_NOT_REFERENCES  MATCHER_SCORE_GREATER
131 %token MATCHER_SCORE_LOWER  MATCHER_HEADER  MATCHER_NOT_HEADER
132 %token MATCHER_HEADERS_PART  MATCHER_NOT_HEADERS_PART  MATCHER_MESSAGE
133 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
134 %token MATCHER_EXECUTE  MATCHER_NOT_EXECUTE  MATCHER_MATCHCASE  MATCHER_MATCH
135 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
136 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
137 %token MATCHER_MARK_AS_READ  MATCHER_MARK_AS_UNREAD  MATCHER_FORWARD
138 %token MATCHER_FORWARD_AS_ATTACHMENT  MATCHER_EOL  MATCHER_STRING  
139 %token MATCHER_OR MATCHER_AND  
140
141 %start file
142
143 %token <str> MATCHER_STRING
144 %token <str> MATCHER_SECTION
145 %token <value> MATCHER_INTEGER
146
147 %%
148
149 file:
150 {
151         if (!matcher_parser_dialog) {
152                 prefs_scoring = &global_scoring;
153                 prefs_filtering = &global_filtering;
154         }
155 }
156 file_line_list;
157
158 file_line_list:
159 file_line
160 file_line_list
161 | file_line
162 ;
163
164 file_line:
165 section_notification
166 | instruction
167 ;
168
169 section_notification:
170 MATCHER_SECTION MATCHER_EOL
171 {
172         gchar * folder = $1;
173         FolderItem * item = NULL;
174
175         if (!matcher_parser_dialog) {
176                 item = folder_find_item_from_identifier(folder);
177                 if (item == NULL) {
178                         prefs_scoring = &global_scoring;
179                         prefs_filtering = &global_scoring;
180                 }
181                 else {
182                         prefs_scoring = &item->prefs->scoring;
183                         prefs_filtering = &item->prefs->processing;
184                 }
185         }
186 }
187 ;
188
189 instruction:
190 condition end_instr_opt
191 | MATCHER_EOL
192 ;
193
194 end_instr_opt:
195 filtering_or_scoring MATCHER_EOL
196 |
197 {
198         if (!matcher_parser_dialog) {
199                 yyerror("parse error");
200                 return 1;
201         }
202 }
203 ;
204
205 filtering_or_scoring:
206 filtering_action
207 {
208         filtering = filteringprop_new(cond, action);
209         cond = NULL;
210         action = NULL;
211         if (!matcher_parser_dialog) {
212                 * prefs_filtering = g_slist_append(* prefs_filtering,
213                                                    filtering);
214                 filtering = NULL;
215         }
216 }
217 | scoring_rule
218 {
219         scoring = scoringprop_new(cond, score);
220         cond = NULL;
221         score = 0;
222         if (!matcher_parser_dialog) {
223                 * prefs_scoring = g_slist_append(* prefs_scoring, scoring);
224                 scoring = NULL;
225         }
226 }
227 ;
228
229 match_type:
230 MATCHER_MATCHCASE
231 {
232         match_type = MATCHTYPE_MATCHCASE;
233 }
234 | MATCHER_MATCH
235 {
236         match_type = MATCHTYPE_MATCH;
237 }
238 | MATCHER_REGEXPCASE
239 {
240         match_type = MATCHTYPE_REGEXPCASE;
241 }
242 | MATCHER_REGEXP
243 {
244         match_type = MATCHTYPE_REGEXP;
245 }
246 ;
247
248 condition:
249 condition_list
250 {
251         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
252         matchers_list = NULL;
253 }
254 ;
255
256 condition_list:
257 condition_list bool_op one_condition
258 {
259         matchers_list = g_slist_append(matchers_list, prop);
260 }
261 | one_condition
262 {
263         matchers_list = NULL;
264         matchers_list = g_slist_append(matchers_list, prop);
265 }
266 ;
267
268 bool_op:
269 MATCHER_AND
270 {
271         bool_op = MATCHERBOOL_AND;
272 }
273 | MATCHER_OR
274 {
275         bool_op = MATCHERBOOL_OR;
276 }
277 ;
278
279 one_condition:
280 MATCHER_ALL
281 {
282         gint criteria = 0;
283
284         criteria = MATCHCRITERIA_ALL;
285         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
286 }
287 | MATCHER_UNREAD
288 {
289         gint criteria = 0;
290
291         criteria = MATCHCRITERIA_UNREAD;
292         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
293 }
294 | MATCHER_NOT_UNREAD 
295 {
296         gint criteria = 0;
297
298         criteria = MATCHCRITERIA_NOT_UNREAD;
299         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
300 }
301 | MATCHER_NEW
302 {
303         gint criteria = 0;
304
305         criteria = MATCHCRITERIA_NEW;
306         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
307 }
308 | MATCHER_NOT_NEW
309 {
310         gint criteria = 0;
311
312         criteria = MATCHCRITERIA_NOT_NEW;
313         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
314 }
315 | MATCHER_MARKED
316 {
317         gint criteria = 0;
318
319         criteria = MATCHCRITERIA_MARKED;
320         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
321 }
322 | MATCHER_NOT_MARKED
323 {
324         gint criteria = 0;
325
326         criteria = MATCHCRITERIA_NOT_MARKED;
327         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
328 }
329 | MATCHER_DELETED
330 {
331         gint criteria = 0;
332
333         criteria = MATCHCRITERIA_DELETED;
334         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
335 }
336 | MATCHER_NOT_DELETED
337 {
338         gint criteria = 0;
339
340         criteria = MATCHCRITERIA_NOT_DELETED;
341         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
342 }
343 | MATCHER_REPLIED
344 {
345         gint criteria = 0;
346
347         criteria = MATCHCRITERIA_REPLIED;
348         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
349 }
350 | MATCHER_NOT_REPLIED
351 {
352         gint criteria = 0;
353
354         criteria = MATCHCRITERIA_NOT_REPLIED;
355         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
356 }
357 | MATCHER_FORWARDED
358 {
359         gint criteria = 0;
360
361         criteria = MATCHCRITERIA_FORWARDED;
362         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
363 }
364 | MATCHER_NOT_FORWARDED
365 {
366         gint criteria = 0;
367
368         criteria = MATCHCRITERIA_NOT_FORWARDED;
369         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
370 }
371 | MATCHER_SUBJECT match_type MATCHER_STRING
372 {
373         gint criteria = 0;
374         gchar * expr = NULL;
375
376         criteria = MATCHCRITERIA_SUBJECT;
377         expr = $3;
378         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
379 }
380 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
381 {
382         gint criteria = 0;
383         gchar * expr = NULL;
384
385         criteria = MATCHCRITERIA_NOT_SUBJECT;
386         expr = $3;
387         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
388 }
389 | MATCHER_FROM match_type MATCHER_STRING
390 {
391         gint criteria = 0;
392         gchar * expr = NULL;
393
394         criteria = MATCHCRITERIA_FROM;
395         expr = $3;
396         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
397 }
398 | MATCHER_NOT_FROM match_type MATCHER_STRING
399 {
400         gint criteria = 0;
401         gchar * expr = NULL;
402
403         criteria = MATCHCRITERIA_NOT_FROM;
404         expr = $3;
405         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
406 }
407 | MATCHER_TO match_type MATCHER_STRING
408 {
409         gint criteria = 0;
410         gchar * expr = NULL;
411
412         criteria = MATCHCRITERIA_TO;
413         expr = $3;
414         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
415 }
416 | MATCHER_NOT_TO match_type MATCHER_STRING
417 {
418         gint criteria = 0;
419         gchar * expr = NULL;
420
421         criteria = MATCHCRITERIA_NOT_TO;
422         expr = $3;
423         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
424 }
425 | MATCHER_CC match_type MATCHER_STRING
426 {
427         gint criteria = 0;
428         gchar * expr = NULL;
429
430         criteria = MATCHCRITERIA_CC;
431         expr = $3;
432         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
433 }
434 | MATCHER_NOT_CC match_type MATCHER_STRING
435 {
436         gint criteria = 0;
437         gchar * expr = NULL;
438
439         criteria = MATCHCRITERIA_NOT_CC;
440         expr = $3;
441         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
442 }
443 | MATCHER_TO_OR_CC match_type MATCHER_STRING
444 {
445         gint criteria = 0;
446         gchar * expr = NULL;
447
448         criteria = MATCHCRITERIA_TO_OR_CC;
449         expr = $3;
450         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
451 }
452 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
453 {
454         gint criteria = 0;
455         gchar * expr = NULL;
456
457         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
458         expr = $3;
459         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
460 }
461 | MATCHER_AGE_GREATER MATCHER_INTEGER
462 {
463         gint criteria = 0;
464         gint value = 0;
465
466         criteria = MATCHCRITERIA_AGE_GREATER;
467         value = atoi($2);
468         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
469 }
470 | MATCHER_AGE_LOWER MATCHER_INTEGER
471 {
472         gint criteria = 0;
473         gint value = 0;
474
475         criteria = MATCHCRITERIA_AGE_LOWER;
476         value = atoi($2);
477         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
478 }
479 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
480 {
481         gint criteria = 0;
482         gchar * expr = NULL;
483
484         criteria = MATCHCRITERIA_NEWSGROUPS;
485         expr = $3;
486         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
487 }
488 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
489 {
490         gint criteria = 0;
491         gchar * expr = NULL;
492
493         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
494         expr = $3;
495         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
496 }
497 | MATCHER_INREPLYTO match_type MATCHER_STRING
498 {
499         gint criteria = 0;
500         gchar * expr = NULL;
501
502         criteria = MATCHCRITERIA_INREPLYTO;
503         expr = $3;
504         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
505 }
506 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
507 {
508         gint criteria = 0;
509         gchar * expr = NULL;
510
511         criteria = MATCHCRITERIA_NOT_INREPLYTO;
512         expr = $3;
513         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
514 }
515 | MATCHER_REFERENCES match_type MATCHER_STRING
516 {
517         gint criteria = 0;
518         gchar * expr = NULL;
519
520         criteria = MATCHCRITERIA_REFERENCES;
521         expr = $3;
522         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
523 }
524 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
525 {
526         gint criteria = 0;
527         gchar * expr = NULL;
528
529         criteria = MATCHCRITERIA_NOT_REFERENCES;
530         expr = $3;
531         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
532 }
533 | MATCHER_SCORE_GREATER MATCHER_INTEGER
534 {
535         gint criteria = 0;
536         gint value = 0;
537
538         criteria = MATCHCRITERIA_SCORE_GREATER;
539         value = atoi($2);
540         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
541 }
542 | MATCHER_SCORE_LOWER MATCHER_INTEGER
543 {
544         gint criteria = 0;
545         gint value = 0;
546
547         criteria = MATCHCRITERIA_SCORE_LOWER;
548         value = atoi($2);
549         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
550 }
551 | MATCHER_HEADER MATCHER_STRING
552 {
553         header = g_strdup($2);
554 } match_type MATCHER_STRING
555 {
556         gint criteria = 0;
557         gchar * expr = NULL;
558
559         criteria = MATCHCRITERIA_HEADER;
560         expr = $2;
561         prop = matcherprop_new(criteria, header, match_type, expr, 0);
562         g_free(header);
563 }
564 | MATCHER_NOT_HEADER MATCHER_STRING
565 {
566         header = g_strdup($2);
567 } match_type MATCHER_STRING
568 {
569         gint criteria = 0;
570         gchar * expr = NULL;
571
572         criteria = MATCHCRITERIA_NOT_HEADER;
573         expr = $2;
574         prop = matcherprop_new(criteria, header, match_type, expr, 0);
575         g_free(header);
576 }
577 | MATCHER_HEADERS_PART match_type MATCHER_STRING
578 {
579         gint criteria = 0;
580         gchar * expr = NULL;
581
582         criteria = MATCHCRITERIA_HEADERS_PART;
583         expr = $3;
584         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
585 }
586 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
587 {
588         gint criteria = 0;
589         gchar * expr = NULL;
590
591         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
592         expr = $3;
593         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
594 }
595 | MATCHER_MESSAGE match_type MATCHER_STRING
596 {
597         gint criteria = 0;
598         gchar * expr = NULL;
599
600         criteria = MATCHCRITERIA_MESSAGE;
601         expr = $3;
602         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
603 }
604 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
605 {
606         gint criteria = 0;
607         gchar * expr = NULL;
608
609         criteria = MATCHCRITERIA_NOT_MESSAGE;
610         expr = $3;
611         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
612 }
613 | MATCHER_BODY_PART match_type MATCHER_STRING
614 {
615         gint criteria = 0;
616         gchar * expr = NULL;
617
618         criteria = MATCHCRITERIA_BODY_PART;
619         expr = $3;
620         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
621 }
622 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
623 {
624         gint criteria = 0;
625         gchar * expr = NULL;
626
627         criteria = MATCHCRITERIA_NOT_BODY_PART;
628         expr = $3;
629         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
630 }
631 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
632 {
633         gint criteria = 0;
634         gchar * expr = NULL;
635
636         criteria = MATCHCRITERIA_NOT_MESSAGE;
637         expr = $3;
638         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
639 }
640 | MATCHER_EXECUTE MATCHER_STRING
641 {
642         gint criteria = 0;
643         gchar * expr = NULL;
644
645         criteria = MATCHCRITERIA_EXECUTE;
646         expr = $2;
647         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
648 }
649 | MATCHER_NOT_EXECUTE MATCHER_STRING
650 {
651         gint criteria = 0;
652         gchar * expr = NULL;
653
654         criteria = MATCHCRITERIA_NOT_EXECUTE;
655         expr = $2;
656         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
657 }
658 ;
659
660 filtering_action:
661 MATCHER_EXECUTE MATCHER_STRING
662 {
663         gchar * cmd = NULL;
664         gint action_type = 0;
665
666         action_type = MATCHACTION_EXECUTE;
667         cmd = $2;
668         action = filteringaction_new(action_type, 0, cmd);
669 }
670 | MATCHER_MOVE MATCHER_STRING
671 {
672         gchar * destination = NULL;
673         gint action_type = 0;
674
675         action_type = MATCHACTION_MOVE;
676         destination = $2;
677         action = filteringaction_new(action_type, 0, destination);
678 }
679 | MATCHER_COPY MATCHER_STRING
680 {
681         gchar * destination = NULL;
682         gint action_type = 0;
683
684         action_type = MATCHACTION_COPY;
685         destination = $2;
686         action = filteringaction_new(action_type, 0, destination);
687 }
688 | MATCHER_DELETE
689 {
690         gint action_type = 0;
691
692         action_type = MATCHACTION_DELETE;
693         action = filteringaction_new(action_type, 0, NULL);
694 }
695 | MATCHER_MARK
696 {
697         gint action_type = 0;
698
699         action_type = MATCHACTION_MARK;
700         action = filteringaction_new(action_type, 0, NULL);
701 }
702 | MATCHER_UNMARK
703 {
704         gint action_type = 0;
705
706         action_type = MATCHACTION_UNMARK;
707         action = filteringaction_new(action_type, 0, NULL);
708 }
709 | MATCHER_MARK_AS_READ
710 {
711         gint action_type = 0;
712
713         action_type = MATCHACTION_MARK_AS_READ;
714         action = filteringaction_new(action_type, 0, NULL);
715 }
716 | MATCHER_MARK_AS_UNREAD
717 {
718         gint action_type = 0;
719
720         action_type = MATCHACTION_MARK_AS_UNREAD;
721         action = filteringaction_new(action_type, 0, NULL);
722 }
723 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
724 {
725         gchar * destination = NULL;
726         gint action_type = 0;
727         gint account_id = 0;
728
729         action_type = MATCHACTION_FORWARD;
730         account_id = $2;
731         destination = $3;
732         action = filteringaction_new(action_type, account_id, destination);
733 }
734 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
735 {
736         gchar * destination = NULL;
737         gint action_type = 0;
738         gint account_id = 0;
739
740         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
741         account_id = $2;
742         destination = $3;
743         action = filteringaction_new(action_type, account_id, destination);
744 }
745 ;
746
747 scoring_rule:
748 MATCHER_SCORE MATCHER_INTEGER
749 {
750         score = atoi($2);
751 }
752 ;