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@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@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@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@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@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@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("[#--]");
+ }
+
+}