Author: julien_viet
Date: 2010-11-27 07:02:10 -0500 (Sat, 27 Nov 2010)
New Revision: 5305
Modified:
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/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/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
fix a bug in the character class parser
Modified:
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 2010-11-26
21:24:55 UTC (rev 5304)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27
12:02:10 UTC (rev 5305)
@@ -95,18 +95,31 @@
return -1;
}
- protected final int indexOfBlah(int from, int to, char start, char end)
+ /**
+ * Find the closing char.
+ *
+ * @param from the index to start from, the char at this index should be the opening
char
+ * @param to the max exclusive value this closing char can be
+ * @param openingChar the opening char
+ * @param closingChar the closing char
+ * @return the index of the closing char or -1
+ */
+ protected final int findClosing(int from, int to, char openingChar, char closingChar)
{
+ if (s.charAt(from) != openingChar)
+ {
+ throw new AssertionError();
+ }
int closing = -1;
int depth = 0;
for (int i = from + 1;i < to;i++)
{
char c = s.charAt(i);
- if (c == start)
+ if (c == openingChar)
{
depth++;
}
- else if (c == end)
+ else if (c == closingChar)
{
if (depth == 0)
{
Modified:
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 2010-11-26
21:24:55 UTC (rev 5304)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-27
12:02:10 UTC (rev 5305)
@@ -28,41 +28,15 @@
public abstract String toString();
- public abstract void accept(Visitor visitor);
-
- /**
- * A visitor.
- */
- public static abstract class Visitor
+ public static final class Disjunction extends RENode
{
- public void enter(Disjunction disjunction) {}
- public void leave(Disjunction disjunction) {}
- public void enter(Alternative alternative) {}
- public void leave(Alternative alternative) {}
- public void enter(Group group) {}
- public void leave(Group group) {}
- public void visit(Assertion assertion) {}
- public void visit(Dot dot) {}
- public void visit(Character character) {}
- public void enter(CharacterClass.Not not) {}
- public void leave(CharacterClass.Not not) {}
- public void enter(CharacterClass.Or or) {}
- public void leave(CharacterClass.Or or) {}
- public void enter(CharacterClass.And and) {}
- public void leave(CharacterClass.And and) {}
- public void visit(CharacterClass.Simple simple) {}
- public void visit(CharacterClass.Range range) {}
- }
- public static class Disjunction extends RENode
- {
+ /** . */
+ private final Alternative alternative;
/** . */
private final Disjunction next;
- /** . */
- private final Alternative alternative;
-
public Disjunction(Alternative alternative)
{
this(alternative, null);
@@ -80,6 +54,16 @@
this.next = next;
}
+ public Disjunction getNext()
+ {
+ return next;
+ }
+
+ public Alternative getAlternative()
+ {
+ return alternative;
+ }
+
@Override
public String toString()
{
@@ -92,21 +76,9 @@
return alternative.toString();
}
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.enter(this);
- alternative.accept(visitor);
- if (next != null)
- {
- next.accept(visitor);
- }
- visitor.leave(this);
- }
}
- public static class Alternative extends RENode
+ public static final class Alternative extends RENode
{
/** . */
@@ -130,6 +102,16 @@
this.next = next;
}
+ public Exp getExp()
+ {
+ return exp;
+ }
+
+ public Alternative getNext()
+ {
+ return next;
+ }
+
@Override
public String toString()
{
@@ -142,18 +124,6 @@
return exp.toString();
}
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.enter(this);
- exp.accept(visitor);
- if (next != null)
- {
- next.accept(visitor);
- }
- visitor.leave(this);
- }
}
public static abstract class Exp extends RENode
@@ -162,6 +132,15 @@
/** . */
Quantifier quantifier;
+ private Exp()
+ {
+ }
+
+ public Quantifier getQuantifier()
+ {
+ return quantifier;
+ }
+
@Override
public final String toString()
{
@@ -170,26 +149,27 @@
{
String q = quantifier.toString();
sb.append('<').append(q).append('>');
- toString(sb);
+ writeTo(sb);
sb.append("</").append(q).append('>');
}
else
{
- toString(sb);
+ writeTo(sb);
}
return sb.toString();
}
- protected abstract void toString(StringBuilder sb);
+ protected abstract void writeTo(StringBuilder sb);
}
public static abstract class Assertion extends Exp
{
+
/** . */
public static final Assertion BEGIN = new Assertion()
{
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<^/>");
}
@@ -199,7 +179,7 @@
public static final Assertion END = new Assertion()
{
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<$/>");
}
@@ -208,16 +188,13 @@
private Assertion()
{
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.visit(this);
- }
}
public static abstract class Atom extends Exp
{
+ private Atom()
+ {
+ }
}
public static final class Dot extends Atom
@@ -231,16 +208,10 @@
}
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<./>");
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.visit(this);
- }
}
public static final class Group extends Atom
@@ -258,18 +229,15 @@
this.disjunction = disjunction;
}
- @Override
- protected void toString(StringBuilder sb)
+ public Disjunction getDisjunction()
{
-
sb.append("<(>").append(disjunction).append("</)>");
+ return disjunction;
}
@Override
- public void accept(Visitor visitor)
+ protected void writeTo(StringBuilder sb)
{
- visitor.enter(this);
- disjunction.accept(visitor);
- visitor.leave(this);
+
sb.append("<(>").append(disjunction).append("</)>");
}
}
@@ -279,36 +247,64 @@
/** . */
private final char value;
+ public char getValue()
+ {
+ return value;
+ }
+
public Character(char value)
{
this.value = value;
}
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<c>").append(value).append("</c>");
}
+ }
+ public static class CharacterClass extends Atom
+ {
+
+ /** . */
+ private final CharacterClassExpr expr;
+
+ protected CharacterClass(CharacterClassExpr expr)
+ {
+ if (expr == null)
+ {
+ throw new NullPointerException();
+ }
+ this.expr = expr;
+ }
+
+ public CharacterClassExpr getExpr()
+ {
+ return expr;
+ }
+
@Override
- public void accept(Visitor visitor)
+ protected void writeTo(StringBuilder sb)
{
- visitor.visit(this);
+ sb.append(expr);
}
}
- public static abstract class CharacterClass extends Atom
+ public static abstract class CharacterClassExpr extends RENode
{
- protected abstract void toString(StringBuilder sb);
+ private CharacterClassExpr()
+ {
+ }
- public static class Not extends CharacterClass
+ public static class Not extends CharacterClassExpr
{
/** . */
- private final CharacterClass negated;
+ private final CharacterClassExpr negated;
- public Not(CharacterClass negated)
+ public Not(CharacterClassExpr negated)
{
if (negated == null)
{
@@ -317,33 +313,28 @@
this.negated = negated;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getNegated()
{
- sb.append("[^");
- negated.toString(sb);
- sb.append("]");
+ return negated;
}
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- negated.accept(visitor);
- visitor.leave(this);
+ return "[^" + negated + "]";
}
}
- public static class Or extends CharacterClass
+ public static class Or extends CharacterClassExpr
{
/** . */
- private final CharacterClass left;
+ private final CharacterClassExpr left;
/** . */
- private final CharacterClass right;
+ private final CharacterClassExpr right;
- public Or(CharacterClass left, CharacterClass right)
+ public Or(CharacterClassExpr left, CharacterClassExpr right)
{
if (left == null)
{
@@ -357,35 +348,33 @@
this.right = right;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getLeft()
{
- sb.append("[");
- left.toString(sb);
- right.toString(sb);
- sb.append("]");
+ return left;
}
+ public CharacterClassExpr getRight()
+ {
+ return right;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- left.accept(visitor);
- right.accept(visitor);
- visitor.leave(this);
+ return "[" + left + right + "]";
}
}
- public static class And extends CharacterClass
+ public static class And extends CharacterClassExpr
{
/** . */
- private final CharacterClass left;
+ private final CharacterClassExpr left;
/** . */
- private final CharacterClass right;
+ private final CharacterClassExpr right;
- public And(CharacterClass left, CharacterClass right)
+ public And(CharacterClassExpr left, CharacterClassExpr right)
{
if (left == null)
{
@@ -399,27 +388,24 @@
this.right = right;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getLeft()
{
- sb.append("[");
- left.toString(sb);
- sb.append("&&");
- right.toString(sb);
- sb.append("]");
+ return left;
}
+ public CharacterClassExpr getRight()
+ {
+ return right;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- left.accept(visitor);
- right.accept(visitor);
- visitor.leave(this);
+ return "[" + left + "&&" + right +
"]";
}
}
- public static class Simple extends CharacterClass
+ public static class Simple extends CharacterClassExpr
{
/** . */
@@ -430,22 +416,19 @@
this.value = value;
}
- @Override
- protected void toString(StringBuilder sb)
+ public char getValue()
{
- sb.append("[");
- sb.append(value);
- sb.append("]");
+ return value;
}
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.visit(this);
+ return "[" + value + "]";
}
}
- public static class Range extends CharacterClass
+ public static class Range extends CharacterClassExpr
{
/** From inclusive. */
@@ -460,20 +443,20 @@
this.to = to;
}
- @Override
- protected void toString(StringBuilder sb)
+ public char getFrom()
{
- sb.append("[");
- sb.append(from);
- sb.append('-');
- sb.append(to);
- sb.append("]");
+ return from;
}
+ public char getTo()
+ {
+ return to;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.visit(this);
+ return "[" + from + "-" + to + "]";
}
}
}
Modified:
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 2010-11-26
21:24:55 UTC (rev 5304)
+++
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27
12:02:10 UTC (rev 5305)
@@ -147,7 +147,7 @@
index++;
break;
case '(':
- int closingParenthesis = indexOfBlah(index + 1, to, '(',
')');
+ int closingParenthesis = findClosing(index, to, '(', ')');
if (closingParenthesis == -1)
{
throw new SyntaxException();
@@ -164,12 +164,12 @@
throw new SyntaxException();
case '[':
- int closingBracket = indexOfBlah(index + 1, to, '[', ']');
+ int closingBracket = findClosing(index, to, '[', ']');
if (closingBracket == -1)
{
throw new SyntaxException();
}
- exp = parseCharacterClass(index, closingBracket + 1);
+ exp = new RENode.CharacterClass(parseCharacterClass(index, closingBracket +
1));
index = closingBracket + 1;
break;
case '\\':
@@ -285,84 +285,84 @@
/**
* character_class -> '[' bracket_list ']' | '['
'^' bracket_list ']'
- * bracket_term -> bracket_term | bracket_term bracket_term | bracket_term
'&' '&' bracket_term
+ * bracket_list -> bracket_term | bracket_term bracket_list | bracket_term
'&' '&' bracket_list
* 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)
+ private RENode.CharacterClassExpr 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 (begin < end)
{
- if (end - begin < 3)
+ RENode.CharacterClassExpr next;
+ if (s.charAt(begin) == '[')
{
- throw new SyntaxException();
- }
- if (s.charAt(end - 1) != ']')
- {
- throw new SyntaxException();
- }
+ int closing = findClosing(begin, end, '[', ']');
+ if (closing == -1)
+ {
+ throw new SyntaxException("Was expecting a closing brack");
+ }
- //
- begin++;
- end--;
+ //
+ boolean matching = true;
+ int nestedStart = begin + 1;
+ int nestedEnd = closing;
+ if (s.charAt(nestedStart) == '^' && nestedStart + 1 <
nestedEnd)
+ {
+ nestedStart++;
+ matching = false;
+ }
- //
- if (s.charAt(begin) == '^' && begin + 1 < end)
+ //
+ RENode.CharacterClassExpr nested = parseCharacterClass(nestedStart,
nestedEnd);
+ next = matching ? nested : new RENode.CharacterClassExpr.Not(nested);
+ begin = closing + 1;
+ }
+ else
{
+ char c = s.charAt(begin);
begin++;
- matching = false;
+ if (begin + 1 < end && s.charAt(begin) == '-')
+ {
+ next = new RENode.CharacterClassExpr.Range(c, s.charAt(begin + 1));
+ begin += 2;
+ }
+ else
+ {
+ next = new RENode.CharacterClassExpr.Simple(c);
+ }
}
- }
- //
- //
- 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) == '&')
+ //
+ if (begin < end)
{
- RENode.CharacterClass next = parseCharacterClass(begin + 2, end);
- cc = new RENode.CharacterClass.And(cc, next);
+ char n = s.charAt(begin);
+ if (n == '&' && begin + 1 < end &&
s.charAt(begin + 1) == '&')
+ {
+ RENode.CharacterClassExpr next2 = parseCharacterClass(begin + 2, end);
+ next = new RENode.CharacterClassExpr.And(next, next2);
+ }
+ else
+ {
+ RENode.CharacterClassExpr next2 = parseCharacterClass(begin, end);
+ next = new RENode.CharacterClassExpr.Or(next, next2);
+ }
}
- else
- {
- RENode.CharacterClass next = parseCharacterClass(begin, end);
- cc = new RENode.CharacterClass.Or(cc, next);
- }
- }
- //
- if (matching)
- {
- return cc;
+ //
+ return next;
}
else
{
- return new RENode.CharacterClass.Not(cc);
+ throw new UnsupportedOperationException();
}
}
}
Modified:
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 2010-11-26
21:24:55 UTC (rev 5304)
+++
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27
12:02:10 UTC (rev 5305)
@@ -190,6 +190,8 @@
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]c]").assertParseBracketExpression("[[a][[b][c]]]");
+ new
ParserTester("[[a]bc]").assertParseBracketExpression("[[a][[b][c]]]");
new ParserTester("[-]").assertParseBracketExpression("[-]");
new
ParserTester("[a-]").assertParseBracketExpression("[[a][-]]");
new
ParserTester("[---]").assertParseBracketExpression("[---]");