[gatein-commits] gatein SVN: r5301 - in portal/branches/navcontroller/component/web/controller/src: main/java/org/exoplatform/web/controller/regexp and 2 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Nov 26 14:21:58 EST 2010


Author: julien_viet
Date: 2010-11-26 14:21:57 -0500 (Fri, 26 Nov 2010)
New Revision: 5301

Added:
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
   portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java
   portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/
   portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
start to implement regexp analyser


Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class Parser
+{
+
+   /** . */
+   protected final CharSequence s;
+
+   /** . */
+   protected final int from;
+
+   /** . */
+   protected final int to;
+
+   public Parser(CharSequence s)
+   {
+      if (s == null)
+      {
+         throw new NullPointerException();
+      }
+
+      //
+      this.s = s;
+      this.from = 0;
+      this.to = s.length();
+   }
+
+   public Parser(CharSequence s, int from, int to)
+   {
+      if (s == null)
+      {
+         throw new NullPointerException();
+      }
+      if (to > s.length())
+      {
+         throw new IllegalArgumentException();
+      }
+      if (from < 0)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (from > to)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      //
+      this.s = s;
+      this.from = from;
+      this.to = to;
+   }
+
+   public final int getFrom()
+   {
+      return from;
+   }
+
+   public final int getTo()
+   {
+      return to;
+   }
+
+   protected final int lastIndexOf(char c)
+   {
+      for (int i = to - 1;i >= from;i--)
+      {
+         if (s.charAt(i) == c)
+         {
+            return i;
+         }
+      }
+      return -1;
+   }
+
+   protected final int indexOfBlah(int from, int to, char start, char end)
+   {
+      int closing = -1;
+      int depth = 0;
+      for (int i = from + 1;i < to;i++)
+      {
+         char c = s.charAt(i);
+         if (c == start)
+         {
+            depth++;
+         }
+         else if (c == end)
+         {
+            if (depth == 0)
+            {
+               closing = i;
+               break;
+            }
+            else
+            {
+               depth--;
+            }
+         }
+      }
+      return closing;
+   }
+
+   protected final int indexOf(int from, char c, int to)
+   {
+      for (int i = from;i < to;i++)
+      {
+         if (s.charAt(i) == c)
+         {
+            return i;
+         }
+      }
+      return -1;
+   }
+}

Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class Quantifier
+{
+
+   private Quantifier()
+   {
+   }
+
+   /** . */
+   public static final Quantifier STAR = new Quantifier()
+   {
+      @Override
+      public String toString()
+      {
+         return "*";
+      }
+   };
+
+   /** . */
+   public static final Quantifier PLUS = new Quantifier()
+   {
+      @Override
+      public String toString()
+      {
+         return "+";
+      }
+   };
+
+   /** . */
+   public static final Quantifier QUESTION_MARK = new Quantifier()
+   {
+      @Override
+      public String toString()
+      {
+         return "?";
+      }
+   };
+
+}

Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import org.hibernate.criterion.Disjunction;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class RENode
+{
+
+   public static class Disjunction extends RENode
+   {
+
+      /** . */
+      private final Disjunction next;
+
+      /** . */
+      private final Alternative alternative;
+
+      public Disjunction(Alternative alternative)
+      {
+         this.alternative = alternative;
+         this.next = null;
+      }
+
+      public Disjunction(Alternative alternative, Disjunction next)
+      {
+         this.alternative = alternative;
+         this.next = next;
+      }
+
+      @Override
+      public String toString()
+      {
+         if (next != null)
+         {
+            return alternative + "|" + next;
+         }
+         else
+         {
+            return alternative.toString();
+         }
+      }
+   }
+
+   public static class Alternative extends RENode
+   {
+
+      /** . */
+      private final Exp exp;
+
+      /** . */
+      private final Alternative next;
+
+      public Alternative(Exp exp)
+      {
+         this.exp = exp;
+         this.next = null;
+      }
+
+      public Alternative(Exp exp, Alternative next)
+      {
+         this.exp = exp;
+         this.next = next;
+      }
+
+      @Override
+      public String toString()
+      {
+         if (next != null)
+         {
+            return exp.toString() + next;
+         }
+         else
+         {
+            return exp.toString();
+         }
+      }
+   }
+
+   public String toString()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public static abstract class Exp extends RENode
+   {
+   }
+
+   public static class Assertion extends Exp
+   {
+      /** . */
+      public static final Assertion BEGIN = new Assertion()
+      {
+         @Override
+         public String toString()
+         {
+            return "<^/>";
+         }
+      };
+
+      /** . */
+      public static final Assertion END = new Assertion()
+      {
+         @Override
+         public String toString()
+         {
+            return "<$/>";
+         }
+      };
+
+      private Assertion()
+      {
+      }
+   }
+
+   public static final class QuantifiedExp extends Exp
+   {
+      /** . */
+      private final Exp exp;
+
+      /** . */
+      private final Quantifier quantifier;
+
+      public QuantifiedExp(Exp exp, Quantifier quantifier)
+      {
+         this.exp = exp;
+         this.quantifier = quantifier;
+      }
+
+      @Override
+      public String toString()
+      {
+         return "<" + quantifier + ">" + exp + "</" + quantifier + ">";
+      }
+   }
+
+   public static abstract class Atom extends Exp
+   {
+   }
+
+   public static final class Dot extends Atom
+   {
+
+      /** . */
+      public static Dot INSTANCE = new Dot();
+
+      private Dot()
+      {
+      }
+
+      public String toString()
+      {
+         return "<./>";
+      }
+   }
+
+   public static final class Group extends Atom
+   {
+
+      /** . */
+      private final Disjunction disjunction;
+
+      public Group(Disjunction disjunction)
+      {
+         this.disjunction = disjunction;
+      }
+
+      @Override
+      public String toString()
+      {
+         return "<(>" + disjunction + "</)>";
+      }
+   }
+
+   public static final class Character extends Atom
+   {
+
+      /** . */
+      private final char value;
+
+      public Character(char value)
+      {
+         this.value = value;
+      }
+
+      @Override
+      public String toString()
+      {
+         return "<c>" + value + "</c>";
+      }
+   }
+
+   public static abstract class CharacterClass extends Atom
+   {
+
+      protected abstract void toString(StringBuilder sb);
+
+      public static class Not extends CharacterClass
+      {
+
+         /** . */
+         private final CharacterClass negated;
+
+         public Not(CharacterClass negated)
+         {
+            this.negated = negated;
+         }
+
+         @Override
+         public String toString()
+         {
+            StringBuilder sb = new StringBuilder();
+            toString(sb);
+            return sb.toString();
+         }
+
+         @Override
+         protected void toString(StringBuilder sb)
+         {
+            sb.append("[^");
+            negated.toString(sb);
+            sb.append("]");
+         }
+      }
+
+      public static class Or extends CharacterClass
+      {
+
+         /** . */
+         private final CharacterClass left;
+
+         /** . */
+         private final CharacterClass right;
+
+         public Or(CharacterClass left, CharacterClass right)
+         {
+            this.left = left;
+            this.right = right;
+         }
+
+         @Override
+         public String toString()
+         {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            toString(sb);
+            sb.append("]");
+            return sb.toString();
+         }
+
+         @Override
+         protected void toString(StringBuilder sb)
+         {
+            left.toString(sb);
+            right.toString(sb);
+         }
+      }
+
+      public static class And extends CharacterClass
+      {
+
+         /** . */
+         private final CharacterClass left;
+
+         /** . */
+         private final CharacterClass right;
+
+         public And(CharacterClass left, CharacterClass right)
+         {
+            this.left = left;
+            this.right = right;
+         }
+
+         @Override
+         public String toString()
+         {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            toString(sb);
+            sb.append("]");
+            return sb.toString();
+         }
+
+         @Override
+         protected void toString(StringBuilder sb)
+         {
+            left.toString(sb);
+            sb.append("&&");
+            right.toString(sb);
+         }
+      }
+
+      public static class Simple extends CharacterClass
+      {
+
+         /** . */
+         private final char value;
+
+         public Simple(char value)
+         {
+            this.value = value;
+         }
+
+         @Override
+         public String toString()
+         {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            toString(sb);
+            sb.append("]");
+            return sb.toString();
+         }
+
+         @Override
+         protected void toString(StringBuilder sb)
+         {
+            sb.append(value);
+         }
+      }
+
+      public static class Range extends CharacterClass
+      {
+
+         /** From inclusive. */
+         private final char from;
+
+         /** To inclusive. */
+         private final char to;
+
+         public Range(char from, char to)
+         {
+            this.from = from;
+            this.to = to;
+         }
+
+         @Override
+         public String toString()
+         {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            toString(sb);
+            sb.append("]");
+            return sb.toString();
+         }
+
+         @Override
+         protected void toString(StringBuilder sb)
+         {
+            sb.append(from);
+            sb.append('-');
+            sb.append(to);
+         }
+      }
+   }
+}

Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class RegExpParser extends Parser
+{
+
+   /** . */
+   private static final Set<Character> ESCAPABLE = new HashSet<Character>();
+
+   static
+   {
+      for (char c : "^.[$()|*+?{\\".toCharArray())
+      {
+         ESCAPABLE.add(c);
+      }
+   }
+
+   /** . */
+   private int index;
+
+   public RegExpParser(CharSequence s)
+   {
+      super(s);
+
+      //
+      this.index = 0;
+   }
+
+   public RegExpParser(CharSequence s, int from, int to)
+   {
+      super(s, from, to);
+
+      //
+      this.index = from;
+   }
+
+   public int getIndex()
+   {
+      return index;
+   }
+
+   /**
+    * disjunction -> alternative | alternative '|' disjunction
+    *
+    * @return the disjunction
+    */
+   public RENode.Disjunction parseDisjunction()
+   {
+      int pipe = lastIndexOf('|');
+      if (pipe == -1)
+      {
+         return new RENode.Disjunction(parseAlternative());
+      }
+      else
+      {
+         RegExpParser left = new RegExpParser(s, from, pipe);
+         RENode.Alternative alternative = left.parseAlternative();
+         RegExpParser right = new RegExpParser(s, pipe + 1, to);
+         RENode.Disjunction next = right.parseDisjunction();
+         index = to;
+         return new RENode.Disjunction(alternative, next);
+      }
+   }
+
+   /**
+    * alternative -> expression | expression '|' alternative
+    *
+    * @return the alternative
+    */
+   public RENode.Alternative parseAlternative()
+   {
+      if (index < to)
+      {
+         RENode.Exp exp = parseExpression();
+         if (index < to)
+         {
+            RENode.Alternative next = parseAlternative();
+            return new RENode.Alternative(exp, next);
+         }
+         else
+         {
+            return new RENode.Alternative(exp);
+         }
+      }
+      else
+      {
+         throw new SyntaxException();
+      }
+   }
+
+   /**
+    * expression      -> assertion | '(' disjunction ')' | '(' '?' disjunction ')' | character | expression quantifier
+    * assertion       -> '^' | '$'
+    * character       -> '.' | escaped | character_class | literal
+    * escaped         -> '\' any char
+    * quantifier      -> '*' | '+' | '?' | '{' count '}' | '{' count ',' '}' | '{' count ',' count '}'
+    * literal         -> todo
+    *
+    * @return the expression
+    */
+   public RENode.Exp parseExpression()
+   {
+      if (index == to)
+      {
+         throw new SyntaxException();
+      }
+      RENode.Exp exp;
+      char c = s.charAt(index);
+      switch (c)
+      {
+         case '^':
+            exp = RENode.Exp.Assertion.BEGIN;
+            index++;
+            break;
+         case '$':
+            exp = RENode.Exp.Assertion.END;
+            index++;
+            break;
+         case '(':
+            int closingParenthesis = indexOfBlah(index + 1, to, '(', ')');
+            if (closingParenthesis == -1)
+            {
+               throw new SyntaxException();
+            }
+            RENode.Disjunction grouped = new RegExpParser(s, index + 1, closingParenthesis).parseDisjunction();
+            exp = new RENode.Group(grouped);
+            index = closingParenthesis + 1;
+            break;
+         case '*':
+         case '+':
+         case '?':
+         case '{':
+         case '|':
+            throw new SyntaxException();
+
+         case '[':
+            int closingBracket = indexOfBlah(index + 1, to, '[', ']');
+            if (closingBracket == -1)
+            {
+               throw new SyntaxException();
+            }
+            exp = parseCharacterClass(index, closingBracket + 1);
+            index = closingBracket + 1;
+            break;
+         case '\\':
+            if (index +1 < to)
+            {
+               index++;
+               char escaped = s.charAt(index);
+               if (!ESCAPABLE.contains(escaped))
+               {
+                  throw new SyntaxException();
+               }
+               exp = new RENode.Character(escaped);
+               index++;
+               break;
+            }
+            else
+            {
+               throw new SyntaxException();
+            }
+         case '.':
+            exp = RENode.Dot.INSTANCE;
+            index++;
+            break;
+         default:
+            exp = new RENode.Character(c);
+            index++;
+            break;
+            //
+      }
+
+      //
+      Quantifier quantifier = parseQuantifierSymbol();
+      if (quantifier != null)
+      {
+         exp = new RENode.QuantifiedExp(exp, quantifier);
+      }
+
+      //
+      return exp;
+   }
+
+   Quantifier parseQuantifierSymbol()
+   {
+      if (index < to)
+      {
+         char c = s.charAt(index);
+         switch (c)
+         {
+            case '*':
+               index++;
+               return Quantifier.STAR;
+            case '+':
+               index++;
+               return Quantifier.PLUS;
+            case '?':
+               index++;
+               return Quantifier.QUESTION_MARK;
+            case '{':
+               index++;
+               throw new UnsupportedOperationException();
+            default:
+               return null;
+         }
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    * character_class -> '[' bracket_list ']' | '[' '^' bracket_list ']'
+    * bracket_term    -> bracket_term | bracket_term bracket_term | bracket_term '&' '&' bracket_term
+    * bracket_term    -> character_class | single_term | range_term
+    *
+    * @param begin the begin
+    * @param end the end
+    * @return a character class expression
+    */
+   private RENode.CharacterClass parseCharacterClass(int begin, int end)
+   {
+      if (begin == end)
+      {
+         throw new SyntaxException();
+      }
+
+      // Check if we do have bracket around or not
+      boolean matching = true;
+      if (s.charAt(begin) == '[')
+      {
+         if (end - begin < 3)
+         {
+            throw new SyntaxException();
+         }
+         if (s.charAt(end - 1) != ']')
+         {
+            throw new SyntaxException();
+         }
+
+         //
+         begin++;
+         end--;
+
+         //
+         if (s.charAt(begin) == '^' && begin + 1 < end)
+         {
+            begin++;
+            matching = false;
+         }
+      }
+
+      //
+      //
+      RENode.CharacterClass cc;
+      char c = s.charAt(begin);
+      begin++;
+      if (begin + 1 < end && s.charAt(begin) == '-')
+      {
+         cc = new RENode.CharacterClass.Range(c, s.charAt(begin + 1));
+         begin += 2;
+      }
+      else
+      {
+         cc = new RENode.CharacterClass.Simple(c);
+      }
+
+      //
+      if (begin < end)
+      {
+         char n = s.charAt(begin);
+         if (n == '&' && begin + 1 < end && s.charAt(begin + 1) == '&')
+         {
+            RENode.CharacterClass next = parseCharacterClass(begin + 2, end);
+            cc = new RENode.CharacterClass.And(cc, next);
+         }
+         else
+         {
+            RENode.CharacterClass next = parseCharacterClass(begin, end);
+            cc = new RENode.CharacterClass.Or(cc, next);
+         }
+      }
+
+      //
+      if (matching)
+      {
+         return cc;
+      }
+      else
+      {
+         return new RENode.CharacterClass.Not(cc);
+      }
+   }
+}

Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class SyntaxException extends RuntimeException
+{
+   public SyntaxException()
+   {
+   }
+
+   public SyntaxException(String s)
+   {
+      super(s);
+   }
+
+   public SyntaxException(String s, Throwable throwable)
+   {
+      super(s, throwable);
+   }
+
+   public SyntaxException(Throwable throwable)
+   {
+      super(throwable);
+   }
+}

Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,42 @@
+/**
+ * Grammar:
+ * extended_reg_exp   -> ERE_branch | extended_reg_exp '|' ERE_branch
+ * ERE_branch         -> ERE_expression | ERE_branch ERE_expression
+ * ERE_expression     -> one_character_ERE | '^' | '$' | '(' extended_reg_exp ')' | ERE_expression ERE_dupl_symbol
+ * one_character_ERE  -> ORD_CHAR | QUOTED_CHAR | '.' | bracket_expression
+ * ERE_dupl_symbol    -> '*' | '+' | '?' | '{' DUP_COUNT '}' | '{' DUP_COUNT ',' '}' | '{' DUP_COUNT ',' DUP_COUNT '}'
+ *
+ * bracket_expression -> '[' matching_list ']' | '[' nonmatching_list ']'
+ * matching_list      -> bracket_list
+ * nonmatching_list   -> '^' bracket_list
+ * bracket_list       -> follow_list | follow_list '-'
+ * follow_list        -> expression_term | follow_list expression_term
+ * expression_term    -> single_expression | range_expression
+ * single_expression  -> end_range | character_class | equivalence_class
+ * range_expression   -> start_range end_range | start_range '-'
+ * start_range        -> end_range '-'
+ * end_range          -> COLL_ELEM | collating_symbol
+ * collating_symbol   -> Open_dot COLL_ELEM Dot_close Open_dot META_CHAR Dot_close
+ * equivalence_class  -> Open_equal COLL_ELEM Equal_close
+ * character_class    -> Open_colon class_name Colon_close
+ *
+ * ORD_CHAR : A character, other than one of the special characters in SPEC_CHAR
+ * SPEC_CHAR : '^' '.' '[' '$' '(' ')' '|' '*' '+'  '?' '{' '\'
+ * QUOTED_CHAR : '\^' '\.' '\[' '\$' '\(' '\)' '\|' '\*' '\+' '\?' '\{' '\\'
+ * DUP_COUNT : Represents a numeric constant. This token will only be recognised when the context of the grammar
+ * requires it. At all other times, digits not preceded by '\' will be treated as ORD_CHAR
+ * COLL_ELEM : Any single-character collating element, unless it is a META_CHAR
+ * META_CHAR :
+ *  '^' when found first in a bracket expression
+ *  '-' when found anywhere but first (after an initial '^', if any) or last in a bracket expression, or as the ending
+ *      range point in a range expression
+ *  ']' when found anywhere but first (after an initial '^' if any) in a bracket expression
+ *
+ * Open_dot : '[.'
+ * Dot_close : '.]'
+ * Open_equal : '[='
+ * Equal_close : '=]'
+ * Open_colon : '[:'
+ * Colon_close : ':]'
+ */
+package org.exoplatform.web.controller.regexp;
\ No newline at end of file

Added: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java	                        (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java	2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import junit.framework.TestCase;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class TestParser extends TestCase
+{
+
+
+   public void testSomeStuff()
+   {
+      Pattern pattern = Pattern.compile("^[\\^a\b]$");
+      assertTrue(pattern.matcher("^").matches());
+      assertTrue(pattern.matcher("a").matches());
+
+   }
+
+   private static class ParserTester
+   {
+      private final RegExpParser parser;
+      private ParserTester(CharSequence s)
+      {
+         this.parser = new RegExpParser(s);
+      }
+      private ParserTester(CharSequence s, int from, int to)
+      {
+         this.parser = new RegExpParser(s, from, to);
+      }
+      ParserTester assertParseBracketExpression(String expectedValue)
+      {
+         RENode node = parser.parseExpression();
+         assertTrue(node instanceof RENode.CharacterClass);
+         assertEquals(expectedValue, node.toString());
+         return this;
+      }
+      ParserTester assertParseExtendedRegExp(String expectedValue)
+      {
+         int expectedIndex = parser.getTo();
+         RENode.Disjunction disjunction = parser.parseDisjunction();
+         assertEquals(expectedValue, disjunction.toString());
+         assertEquals(expectedIndex, parser.getIndex());
+         return this;
+      }
+      ParserTester assertNotParseExtendedRegExp()
+      {
+         int expectedIndex = parser.getIndex();
+         try
+         {
+            parser.parseDisjunction();
+            fail();
+         }
+         catch (SyntaxException e)
+         {
+            assertEquals(expectedIndex, parser.getIndex());
+         }
+         return this;
+      }
+      ParserTester assertParseExpression(String expectedValue, int expectedIndex)
+      {
+         RENode.Exp exp = parser.parseExpression();
+         assertEquals(expectedValue, exp.toString());
+         assertEquals(expectedIndex, parser.getIndex());
+         return this;
+      }
+      ParserTester assertNotParseEREExpression()
+      {
+         int index = parser.getIndex();
+         try
+         {
+            parser.parseExpression();
+            fail();
+         }
+         catch (SyntaxException e)
+         {
+            assertEquals(index, parser.getIndex());
+         }
+         return this;
+      }
+      ParserTester assertParseEREDuplSymbol(Quantifier expectedQuantifier)
+      {
+         int index = parser.getIndex();
+         if (expectedQuantifier != null)
+         {
+            assertEquals(expectedQuantifier, parser.parseQuantifierSymbol());
+            assertEquals(index + 1, parser.getIndex());
+         }
+         else
+         {
+            assertNull(parser.parseQuantifierSymbol());
+            assertEquals(index, parser.getIndex());
+         }
+         return this;
+      }
+      ParserTester assertIndex(int expectedIndex)
+      {
+         assertEquals(expectedIndex, parser.getIndex());
+         return this;
+      }
+   }
+
+   public void testExtendedRegexp()
+   {
+      new ParserTester("^").assertParseExtendedRegExp("<^/>");
+      new ParserTester("^$").assertParseExtendedRegExp("<^/><$/>");
+      new ParserTester("a").assertParseExtendedRegExp("<c>a</c>");
+      new ParserTester("a|b").assertParseExtendedRegExp("<c>a</c>|<c>b</c>");
+      new ParserTester("a+|b*").assertParseExtendedRegExp("<+><c>a</c></+>|<*><c>b</c></*>");
+   }
+   
+   public void testExpression()
+   {
+      new ParserTester("").assertNotParseEREExpression();
+      new ParserTester("^").assertParseExpression("<^/>", 1);
+      new ParserTester("^+").assertParseExpression("<+><^/></+>", 2);
+      new ParserTester("$").assertParseExpression("<$/>", 1);
+      new ParserTester("$+").assertParseExpression("<+><$/></+>", 2);
+      new ParserTester("a").assertParseExpression("<c>a</c>", 1);
+      new ParserTester("a+").assertParseExpression("<+><c>a</c></+>", 2);
+      new ParserTester(".").assertParseExpression("<./>", 1);
+      new ParserTester(".+").assertParseExpression("<+><./></+>", 2);
+      new ParserTester("\\+").assertParseExpression("<c>+</c>", 2);
+      new ParserTester("\\++").assertParseExpression("<+><c>+</c></+>", 3);
+      new ParserTester("*").assertNotParseEREExpression();
+      new ParserTester("+").assertNotParseEREExpression();
+      new ParserTester("?").assertNotParseEREExpression();
+      new ParserTester("{").assertNotParseEREExpression();
+      new ParserTester("|").assertNotParseEREExpression();
+      new ParserTester("(a)").assertParseExpression("<(><c>a</c></)>", 3);
+      new ParserTester("(a(b)c)").assertParseExpression("<(><c>a</c><(><c>b</c></)><c>c</c></)>", 7);
+   }
+
+   // missing stuff:
+   // ()
+   // +?
+   // {0,2}
+   // escape in bracket
+
+
+   public void testEREDuplSymbol()
+   {
+      new ParserTester("*").assertParseEREDuplSymbol(Quantifier.STAR);
+      new ParserTester("+").assertParseEREDuplSymbol(Quantifier.PLUS);
+      new ParserTester("?").assertParseEREDuplSymbol(Quantifier.QUESTION_MARK);
+      new ParserTester("a").assertParseEREDuplSymbol(null);
+      new ParserTester("").assertParseEREDuplSymbol(null);
+   }
+
+   public void testParseBracketExpression()
+   {
+      new ParserTester("[a]").assertParseBracketExpression("[a]");
+      new ParserTester("[^a]").assertParseBracketExpression("[^a]");
+      new ParserTester("[^a-b]").assertParseBracketExpression("[^a-b]");
+      new ParserTester("[a-b]").assertParseBracketExpression("[a-b]");
+      new ParserTester("[ab]").assertParseBracketExpression("[ab]");
+      new ParserTester("[a&]").assertParseBracketExpression("[a&]");
+      new ParserTester("[a&&b]").assertParseBracketExpression("[a&&b]");
+      new ParserTester("[a&&[^b]]").assertParseBracketExpression("[a&&[^b]]");
+      new ParserTester("[a[^b]]").assertParseBracketExpression("[a[^b]]");
+      new ParserTester("[a[b]]").assertParseBracketExpression("[ab]");
+      new ParserTester("[-]").assertParseBracketExpression("[-]");
+      new ParserTester("[a-]").assertParseBracketExpression("[a-]");
+      new ParserTester("[---]").assertParseBracketExpression("[---]");
+      new ParserTester("[#--]").assertParseBracketExpression("[#--]");
+   }
+
+}



More information about the gatein-commits mailing list