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