[svn-inject] Installing original source of jabref
[debian/jabref.git] / src / java / net / sf / jabref / search / TreeParser.g
1 header {
2 package net.sf.jabref.search;
3 import java.util.*;
4 import java.util.regex.*;
5 import net.sf.jabref.*;
6 }
7
8 class SearchExpressionTreeParser extends TreeParser;
9
10 options {
11         importVocab = SearchExpressionParser;
12         exportVocab = SearchExpressionTreeParser;
13 }
14
15 {
16         private static final int MATCH_EXACT = 0;
17         private static final int MATCH_CONTAINS = 1;
18         private static final int MATCH_DOES_NOT_CONTAIN = 2;
19
20         private BibtexEntry bibtexEntry;
21         private Object[] searchKeys;
22
23     private static final int PSEUDOFIELD_TYPE = 1;
24
25     public int apply(AST ast, BibtexEntry bibtexEntry) throws antlr.RecognitionException {
26                 this.bibtexEntry = bibtexEntry;
27                 // specification of fields to search is done in the search expression itself
28                 this.searchKeys = bibtexEntry.getAllFields();
29                 return tSearchExpression(ast) ? 1 : 0;
30         }
31 }
32
33
34
35 // ---------- Condition and Expressions ----------
36
37 tSearchExpression returns [boolean ret = false;] throws PatternSyntaxException
38 {
39         boolean a = false, b = false;
40 }
41         : // predicates for and/or used to evaluate 2nd expression only if necessary
42         #( And a=tSearchExpression ( {a}? b=tSearchExpression | . ) ) { ret = a && b; }
43         |
44         #( Or a=tSearchExpression ( {!a}? b=tSearchExpression | . ) ) { ret = a || b; }
45         |
46         #( Not a=tSearchExpression ) { ret = !a; }
47         |
48         ret=tExpressionSearch
49         ;
50
51 tSearchType returns [ int matchType = 0; ]
52         :
53         LITERAL_contains { matchType = MATCH_CONTAINS; }
54         |
55         LITERAL_matches { matchType = MATCH_EXACT; }
56         |
57         EQUAL { matchType = MATCH_CONTAINS; }
58         |
59         EEQUAL { matchType = MATCH_EXACT; }
60         |
61         NEQUAL { matchType = MATCH_DOES_NOT_CONTAIN; }
62         ;
63
64 tExpressionSearch returns [ boolean ret = false; ] throws PatternSyntaxException
65 {
66         int matchType = 0;
67 }
68         :
69         #( ExpressionSearch var_f:RegularExpression matchType=tSearchType var_v:RegularExpression
70                 {
71                         Pattern fieldSpec = ((RegExNode)var_f).getPattern();
72                         Pattern valueSpec = ((RegExNode)var_v).getPattern();
73                         int pseudoField = 0;
74             boolean noSuchField = true;
75                         // this loop iterates over all regular keys, then over pseudo keys like "type"
76                         for (int i = 0; i < searchKeys.length + PSEUDOFIELD_TYPE && !ret; ++i) {
77                                 String content;
78                                 switch (i - searchKeys.length + 1) {
79                                         case PSEUDOFIELD_TYPE:
80                                                 if (!fieldSpec.matcher("entrytype").matches())
81                                                         continue;
82                                                 content = bibtexEntry.getType().getName();
83                                                 break;
84                                         default: // regular field
85                                                 if (!fieldSpec.matcher(searchKeys[i].toString()).matches())
86                                                         continue;
87                                                 content = (String)bibtexEntry.getField(searchKeys[i].toString());
88                                 }
89                 noSuchField = false;
90                                 if (content == null)
91                                         continue; // paranoia
92                                 Matcher matcher = valueSpec.matcher(content);
93                                 switch (matchType) {
94                                 case MATCH_CONTAINS:
95                                         ret = matcher.find();
96                                         break;
97                                 case MATCH_EXACT:
98                                         ret = matcher.matches();
99                                         break;
100                                 case MATCH_DOES_NOT_CONTAIN:
101                                         ret = !matcher.find();
102                                         break;
103                                 }
104                         }
105             if (noSuchField && matchType == MATCH_DOES_NOT_CONTAIN)
106                 ret = true; // special case
107                 }
108         )
109         ;
110