PatternParser.java
001 package gate.creole.morph;
002 
003 import gate.creole.ResourceInstantiationException;
004 
005 import java.io.BufferedReader;
006 import java.io.InputStreamReader;
007 import java.util.ArrayList;
008 import java.util.List;
009 
010 public class PatternParser {
011 
012   public static void main(String[] args) {
013     try {
014 
015       BufferedReader in = new BufferedReader(new InputStreamReader(
016           System.in));
017       variableDeclarationCommand("A ==> [abcdefghijklmnopqrstuvwxyz0123456789-]");
018       variableDeclarationCommand("V ==> [aeiou]");
019       variableDeclarationCommand("VI ==> [aeiouy]");
020       variableDeclarationCommand("C ==> [bcdfghjklmnpqrstvwxyz]");
021       variableDeclarationCommand("CX ==> [bcdfghjklmnpqrstvwxz]");
022       variableDeclarationCommand("CX2 ==> \"bb\" OR \"cc\" OR \"dd\" OR \"ff\" OR \"gg\" OR \"hh\" OR \"jj\" OR \"kk\" OR \"ll\" OR \"mm\" OR \"nn\" OR \"pp\" OR \"qq\" OR \"rr\" OR \"ss\" OR \"tt\" OR \"vv\" OR \"ww\" OR \"xx\" OR \"zz\"");
023       variableDeclarationCommand("CX2S ==> \"ff\" OR \"ss\" OR \"zz\"");
024       variableDeclarationCommand("S ==> \"s\" OR \"x\" OR \"ch\" OR \"sh\"");
025       variableDeclarationCommand("PRE ==> \"be\" OR \"ex\" OR \"in\" OR \"mis\" OR \"pre\" OR \"pro\" OR \"re\"");
026       variableDeclarationCommand("EDING ==> \"ed\" OR \"ing\"");
027       variableDeclarationCommand("ESEDING ==> \"es\" OR \"ed\" OR \"ing\"");
028       
029       while (true) {
030         System.out.print("Query: ");
031         String line = in.readLine();
032         if (line == null || line.length() 1)
033           break;
034 
035         getPattern(line);
036 
037       }
038     catch (Exception e) {
039       e.printStackTrace();
040     }
041 
042   }
043 
044   public static void getPattern(String line) {
045     String[] ruleParts = line.split("==>");
046     // now check if the method which has been called in this rule actually
047     // available in the MorphFunction Class
048     //String methodCalled = ruleParts[1].trim();
049 
050     // so RHS part is Ok
051     // now we need to check if LHS is written properly
052     // and convert it to the pattern that is recognized by the java
053     String category = "";
054     // we need to find out the category
055     int i = 1;
056     for (; i < ruleParts[0].length(); i++) {
057       if (ruleParts[0].charAt(i== '>')
058         break;
059       category = category + ruleParts[0].charAt(i);
060     }
061 
062     ruleParts[0= ruleParts[0].substring(i + 1, ruleParts[0].length()).trim();
063     String regExp = ParsingFunctions.convertToRegExp(ruleParts[0], variables);
064     String[] rules = ParsingFunctions.normlizePattern(regExp);
065     for (int m = 0; m < rules.length; m++) {
066       PatternPart parts[] = ParsingFunctions.getPatternParts(rules[m].trim());
067       // each part has a type associated with it
068       for (int j = 0; j < parts.length; j++) {
069         System.out.println(parts[j].getPartString() "=>"
070             + parts[j].getType());
071       }
072     }
073   }
074 
075   public final static Storage variables = new Storage();
076   
077   private static void variableDeclarationCommand(String line)
078       throws ResourceInstantiationException {
079     // ok so first find the variable name and the value for it
080     String varName = (line.split("==>"))[0].trim();
081     String varValue = (line.split("==>"))[1].trim();
082 
083     // find the type of variable it is
084     int valueType = ParsingFunctions.findVariableType(varValue.trim());
085 
086     // based on the variable type create the instance
087     Variable varInst = null;
088     switch (valueType) {
089     case Codes.CHARACTER_RANGE_CODE:
090       varInst = new CharacterRange();
091       break;
092     case Codes.CHARACTER_SET_CODE:
093       varInst = new CharacterSet();
094       break;
095     case Codes.STRING_SET_CODE:
096       varInst = new StringSet();
097       break;
098     }
099 
100     // set the values in the variable
101     if (!varInst.set(varName, varValue)) {
102     }
103 
104     // and finally add the variable in
105     if (!variables.add(varName, varInst.getPattern())) {
106     }
107 
108     varInst.resetPointer();
109   }
110 
111   public static List<String> parsePattern(String q1) {
112 
113     // arraylist to return - will contain all the OR normalized queries
114     List<String> patterns = new ArrayList<String>();
115 
116     // remove all extra spaces from the query
117     q1 = q1.trim();
118 
119     // we add opening and closing brackets explicitly
120     q1 = "( " + q1 + " )";
121 
122     // add the main Query in the arraylist
123     patterns.add(q1);
124 
125     for (int index = 0; index < patterns.size(); index++) {
126       // get the query to be parsed
127       String query = patterns.get(index);
128 
129       // current character and the previous character
130       char ch = ' ', pre = ' ';
131 
132       // if query is ORed
133       // we need duplication
134       // for example: {A}((B)|(C))
135       // the normalized form will be
136       // (A)(B)
137       // (A)(C)
138       // here we need (A) to be duplicated two times
139       boolean duplicated = false;
140       int dupliSize = 0;
141       
142       String data = "";
143 
144       // we need to look into one query at a time and parse it
145       for (int i = 0; i < query.length(); i++) {
146         pre = ch;
147         ch = query.charAt(i);
148 
149         // check if it is an open bracket
150         // it is if it doesn't follow the '\' escape sequence
151         if (isOpenBracket(ch, pre)) {
152 
153           // so find out where it gets closed
154           int brClPos = findBracketClosingPosition(i + 1, query);
155 
156           // see if there are any OR operators in it
157           List<String> orTokens = findOrTokens(query.substring(i + 1,
158               brClPos));
159 
160           // orTokens will have
161           // for eg. {A} | ({B}{C})
162           // then {A}
163           // and ({B}{C})
164           // so basically findOrTokens find out all the tokens around
165           // | operator
166           if (orTokens.size() 1) {
167             String text = "";
168 
169             // data contains all the buffered character before the
170             // current positions
171             // for example "ABC" ({B} | {C})
172             // here "ABC" will be in data
173             // and {B} and {C} in orTokens
174             if (!duplicated && data.length() 0) {
175               text = data;
176               data = "";
177             else {
178               if (index == patterns.size() 1) {
179                 // this is the case where we would select the
180                 // text as ""
181                 text = "";
182               else {
183                 text = patterns
184                     .get(patterns.size() 1);
185               }
186             }
187 
188             // so we need to duplicate the text orTokens.size()
189             // times
190             // for example "ABC" ({B} | {C})
191             // text = "ABC"
192             // orTokens {B} {C}
193             // so two queries will be added
194             // 1. "ABC"
195             // 2. "ABC"
196 
197             patterns = duplicate(patterns, text, dupliSize,
198                 orTokens.size());
199             // and tokens will be added
200             // 1. "ABC" {B}
201             // 2. "ABC" {C}
202             patterns = writeTokens(orTokens, patterns, dupliSize);
203 
204             // text is duplicated so make it true
205             duplicated = true;
206 
207             // and how many times it was duplicated
208             if (dupliSize == 0)
209               dupliSize = 1;
210             dupliSize *= orTokens.size();
211           else {
212             // what if the there is only one element between ( and )
213             // it is not an 'OR' query
214 
215             // check how many times we have duplicated the text
216             if (dupliSize == 0) {
217               // if zero and the text buffered is ""
218               // we simply add "" as a separate Query
219               // otherwise add the buffered data as a separate
220               // Query
221               if (data.length() == 0)
222                 patterns.add("");
223               else
224                 patterns.add(data);
225 
226               // because we simply needs to add it only once
227               // but still we have copied it as a separate query
228               // so say duplicated = true
229               duplicated = true;
230               data = "";
231               // and ofcourse the size of the duplication will be
232               // only 1
233               dupliSize = 1;
234             }
235             // and we need to add all the contents between two
236             // brackets in the last duplicated
237             // queries
238             patterns = writeStringInAll("<"
239                 + query.substring(i + 1, brClPos">",
240                 dupliSize, patterns);
241           }
242           i = brClPos;
243         else {
244           if (duplicated) {
245             patterns = writeCharInAll(ch, dupliSize, patterns);
246           else {
247             data += "" + ch;
248           }
249         }
250       }
251 
252       boolean scan = scanQueryForOrOrBracket(query);
253       if (scan) {
254         patterns.remove(index);
255         index--;
256       }
257     }
258 
259     List<String> queriesToReturn = new ArrayList<String>();
260     for (int i = 0; i < patterns.size(); i++) {
261       String q = patterns.get(i);
262       if (q.trim().length() == 0) {
263         continue;
264       else if (queriesToReturn.contains(q.trim())) {
265         continue;
266       else {
267         queriesToReturn.add(q.trim());
268       }
269     }
270 
271     for (int i = 0; i < queriesToReturn.size(); i++) {
272       String s = queriesToReturn.get(i);
273       s = s.replaceAll("<""(");
274       s = s.replaceAll(">"")");
275       s = s.substring(1, s.length() 1);
276       queriesToReturn.set(i, s.trim());
277     }
278     return queriesToReturn;
279   }
280 
281   public static boolean scanQueryForOrOrBracket(String query) {
282     int index = 0;
283     int index1 = 0;
284     do {
285       index = query.indexOf('|', index);
286       if (index == 0) {
287         return true;
288       else if (index > 0) {
289         // we have found it but we need to check if it is an escape
290         // sequence
291         if (query.charAt(index - 1== '\\') {
292           // yes it is an escape sequence
293           // lets search for the next one
294         else {
295           return true;
296         }
297       }
298 
299       // if we are here that means it was not found
300       index1 = query.indexOf('(', index1);
301       if (index1 == 0) {
302         return true;
303       else if (index1 > 0) {
304         // we have found it
305         if (query.charAt(index1 - 1== '\\') {
306           // yes it is an escape sequence
307           continue;
308         else {
309           return true;
310         }
311       }
312 
313     while (index >= && index1 >= 0);
314 
315     return false;
316   }
317 
318   public static List<String> writeTokens(List<String> tokens, List<String> queries,
319       int dupliSize) {
320     if (dupliSize == 0)
321       dupliSize = 1;
322 
323     List<String> qToRemove = new ArrayList<String>();
324     for (int j = 0; j < dupliSize; j++) {
325       for (int i = 1; i <= tokens.size(); i++) {
326         String token = tokens.get(i - 1);
327         if (token.trim().equals("{__o__}")) {
328           token = " ";
329         }
330         String s = queries.get(queries.size()
331             (j * tokens.size() + i));
332         qToRemove.add(s);
333         s += token;
334         queries.set(queries.size() (j * tokens.size() + i), s);
335       }
336     }
337 
338     // and now remove
339     for (int i = 0; i < qToRemove.size(); i++) {
340       queries.remove(qToRemove.get(i));
341     }
342 
343     return queries;
344   }
345 
346   public static List<String> duplicate(List<String> queries, String s,
347       int dupliSize, int no) {
348     if (s == null)
349       s = "";
350 
351     List<String> strings = new ArrayList<String>();
352     if (dupliSize == 0) {
353       strings.add(s);
354     else {
355       for (int i = 0; i < dupliSize; i++) {
356         strings.add(queries.get(queries.size() (i + 1)));
357       }
358     }
359 
360     for (int i = 0; i < strings.size(); i++) {
361       for (int j = 0; j < no; j++) {
362         queries.add(strings.get(i));
363       }
364     }
365 
366     return queries;
367   }
368 
369   public static List<String> findOrTokens(String query) {
370     int balance = 0;
371     char pre = ' ';
372     char ch = ' ';
373     List<String> ors = new ArrayList<String>();
374 
375     String s = "";
376     for (int i = 0; i < query.length(); i++) {
377       pre = ch;
378       ch = query.charAt(i);
379       if (isOpenBracket(ch, pre)) {
380         balance++;
381         s += "" + ch;
382         continue;
383       }
384 
385       if (isClosingBracket(ch, pre&& balance > 0) {
386         balance--;
387         s += "" + ch;
388         continue;
389       }
390 
391       if (isOrSym(ch, pre)) {
392         if (balance > 0) {
393           s += "" + ch;
394           continue;
395         else {
396           ors.add(s);
397           s = "";
398           continue;
399         }
400       }
401 
402       s += "" + ch;
403     }
404 
405     if (s.length() 0)
406       ors.add(s);
407 
408     return ors;
409   }
410 
411   public static int findBracketClosingPosition(int startFrom, String query) {
412     int balance = 0;
413     char pre = ' ';
414     char ch = ' ';
415     for (int i = startFrom; i < query.length(); i++) {
416       pre = ch;
417       ch = query.charAt(i);
418       if (isOpenBracket(ch, pre)) {
419         balance++;
420         continue;
421       }
422 
423       if (isClosingBracket(ch, pre)) {
424         if (balance > 0) {
425           balance--;
426         else {
427           return i;
428         }
429       }
430     }
431     return -1;
432   }
433 
434   public static List<String> writeCharInAll(char c, int no, List<String> queries) {
435     for (int i = 0; i < no; i++) {
436       String s = queries.get(queries.size() (i + 1));
437       s += "" + c;
438       queries.set(queries.size() (i + 1), s);
439     }
440     return queries;
441   }
442 
443   public static List<String> writeStringInAll(String c, int no, List<String> queries) {
444     for (int i = 0; i < no; i++) {
445       String s = queries.get(queries.size() (i + 1));
446       s += "" + c;
447       queries.set(queries.size() (i + 1), s);
448     }
449     return queries;
450   }
451 
452   public static boolean isOpenBracket(char ch, char pre) {
453     if (ch == '(' && pre != '\\')
454       return true;
455     else
456       return false;
457   }
458 
459   public static boolean isClosingBracket(char ch, char pre) {
460     if (ch == ')' && pre != '\\')
461       return true;
462     else
463       return false;
464   }
465 
466   public static boolean isOrSym(char ch, char pre) {
467     if (ch == '|' && pre != '\\')
468       return true;
469     else
470       return false;
471   }
472 
473 }