Index: /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java
===================================================================
--- /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java	(revision 50)
+++ /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java	(revision 50)
@@ -0,0 +1,36 @@
+package de.ugoe.cs.swe.bnftools.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.swe.bnftools.ebnf.Rule;
+
+public class DuplicateEntry {
+	String snippet;
+	List<Rule> rules = new ArrayList<Rule>();
+
+	public String getSnippet() {
+		return snippet;
+	}
+
+	public void setSnippet(String snippet) {
+		this.snippet = snippet;
+	}
+
+	public List<Rule> getRules() {
+		return rules;
+	}
+
+	public void setRules(List<Rule> rule) {
+		this.rules = rule;
+	}
+
+	public void addRule(Rule r) {
+		rules.add(r);
+	}
+	
+	public int getMatchCount() {
+		return rules.size();
+	}
+	
+}
Index: /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java
===================================================================
--- /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java	(revision 49)
+++ /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java	(revision 50)
@@ -2,5 +2,9 @@
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Stack;
 
@@ -341,5 +345,9 @@
 		if (!checkSubruleDuplicates)
 			return;
-
+		
+		HashMap<String, DuplicateEntry> dupesMap = new HashMap<String, DuplicateEntry>();
+		Set<String> taggedEntries = new HashSet<String>();
+		
+		// build dupes map
 		for (int i=0; i < bnf.getBnfEntry().size(); i++) {
 			BnfEntry currentBnfEntry = bnf.getBnfEntry().get(i);
@@ -348,38 +356,8 @@
 				CompositeNode ruleParserNode = NodeUtil.getNodeAdapter(currentBnfEntry.getRule().getDefinitionList()).getParserNode();
 				String ruleText = ruleParserNode.serialize().trim();
-				ruleText = ruleText + " ";
-				String processedRuleText = ruleText.replaceAll("([^\"])\\(([^\"])", "$1 ( $2"); // ( case 1
-				processedRuleText = processedRuleText.replaceAll("\\(([^\"])", " ( $1"); // ( case 2
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\(\"", "$1 ( \""); // ( case 3
-
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\)([^\"])", "$1 ) $2"); // ) case 1
-				processedRuleText = processedRuleText.replaceAll("\\)([^\"])", " ) $1"); // ) case 2
-				processedRuleText = processedRuleText.replaceAll("\"\\)([^\"])", "\" ) $1"); // ) case 3
-				
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\{([^\"])", "$1 { $2"); // { case 1
-				processedRuleText = processedRuleText.replaceAll("\\{([^\"])", " { $1"); // { case 2
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\{\"", "$1 { \""); // { case 3
-				
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\}([^\\+\"])", "$1 } $2"); // } case 1
-				processedRuleText = processedRuleText.replaceAll("\\}([^\\+\"])", " } $1"); // } case 2
-				processedRuleText = processedRuleText.replaceAll("\"\\}([^\\+\"])", "\" } $1"); // } case 3
-				
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\}\\+([^\"])", "$1 }\\+ $2"); // }+ case 1
-				processedRuleText = processedRuleText.replaceAll("\\}\\+([^\"])", " }\\+ $1 "); // }+ case 2
-				processedRuleText = processedRuleText.replaceAll("\"\\}\\+([^\"])", "\" }\\+ $1 "); // }+ case 3
-				
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\[([^\"])", "$1 [ $2"); // [ case 1
-				processedRuleText = processedRuleText.replaceAll("\\[([^\"])", " [ $1"); // [ case 2
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\[\"", "$1 [ \""); // [ case 3
-
-				processedRuleText = processedRuleText.replaceAll("([^\"])\\]([^\"])", "$1 ] $2"); // ] case 1
-				processedRuleText = processedRuleText.replaceAll("\\]([^\"])", " ] $1"); // ] case 2
-				processedRuleText = processedRuleText.replaceAll("\"\\]([^\"])", "\" ] $1"); // ] case 3
-
+				String processedRuleText = textSpacer(ruleText);
 				
 				String trimmedRuleText = processedRuleText.replaceAll("[\t\n\r]", " ").replaceAll("[ ]+", " ");
-				System.out.println("rule: " + trimmedRuleText);
 				
-//				System.out.println(trimmedRuleText);
 				String[] parts = trimmedRuleText.split(" ");
 				
@@ -388,36 +366,89 @@
 						if (isBalancedPairs(parts, j, k) && (k-j > 1)) {
 							String balancedSubString = createString(parts, j, k);
-							System.out.println(balancedSubString);
+							DuplicateEntry mapEntry = dupesMap.get(balancedSubString);
+							if (mapEntry == null) {
+								mapEntry = new DuplicateEntry();
+								mapEntry.setSnippet(balancedSubString);
+								mapEntry.addRule(currentBnfEntry.getRule());
+								dupesMap.put(balancedSubString, mapEntry);
+							} else {
+								mapEntry.addRule(currentBnfEntry.getRule());
+								dupesMap.put(balancedSubString, mapEntry);
+								taggedEntries.add(balancedSubString);
+							}
 						}
-
-//						combined.append(parts[k]);
-//						combined.append(" ");
 					}
 				}
+			}
+		}
+		
+		// create warnings
+		
+		Iterator<String> it = taggedEntries.iterator();
+		
+		while (it.hasNext()) {
+			String entry = it.next();
+			DuplicateEntry dupeEntry = dupesMap.get(entry);
+			if (dupeEntry.getRules().size() < 2)
+				continue;
+			
+			String warningText = "";
+			warningText += entry + " is duplicated in the following rules: ";
+			for (int i=0; i < dupeEntry.getRules().size(); i++) {
+				Rule rule = dupeEntry.getRules().get(i);
+				CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
+
+				if (rule.getRulenumber() > 0) {
+					String ruleNumber = Integer.toString(rule.getRulenumber()).replaceAll("[ \t\n\r]", ""); 
+					warningText += ruleNumber;
+				}
+				warningText += " (Line ";
+				warningText += parserNode.getLine();
+				warningText += ")";
 				
-				System.out.println("---------------------------------------------");
-
-				
-				
-				
-			}
-		}
-		
-		
-		
-		
-//		System.out.println("rule name: " + rule.getName());
-//		for (int i=0; i < definitionLists.size(); i++) {
-//			DefinitionList currentDefList = definitionLists.get(i);
-//			
-//			CompositeNode currentRuleDefinitionList = NodeUtil.getNodeAdapter(currentDefList).getParserNode();
-//			String currentRuleDefinitionListText = currentRuleDefinitionList.serialize().trim();
-//			String trimmedCurrentRuleDefinitionListText = currentRuleDefinitionListText.replaceAll("[ \t\n\r]", "");
-//			System.out.println(trimmedCurrentRuleDefinitionListText);
-////			System.out.println("  -> " + currentRuleDefinitionListText);
-//
-//			
-//		}
-		
+				if (i+1 < dupeEntry.getRules().size())
+					warningText += ", ";
+
+			}
+
+			for (int i=0; i < dupeEntry.getRules().size(); i++) {
+				Rule rule = dupeEntry.getRules().get(i);
+				CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
+				warning(warningText, parserNode.getElement(), 1);
+			}
+		}
+		
+	}
+
+	private String textSpacer(String ruleText) {
+		ruleText = ruleText + " ";
+		String processedRuleText = ruleText.replaceAll("([^\"])\\(([^\"])", "$1 ( $2"); // ( case 1
+		processedRuleText = processedRuleText.replaceAll("\\(([^\"])", " ( $1"); // ( case 2
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\(\"", "$1 ( \""); // ( case 3
+
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\)([^\"])", "$1 ) $2"); // ) case 1
+		processedRuleText = processedRuleText.replaceAll("\\)([^\"])", " ) $1"); // ) case 2
+		processedRuleText = processedRuleText.replaceAll("\"\\)([^\"])", "\" ) $1"); // ) case 3
+		
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\{([^\"])", "$1 { $2"); // { case 1
+		processedRuleText = processedRuleText.replaceAll("\\{([^\"])", " { $1"); // { case 2
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\{\"", "$1 { \""); // { case 3
+		
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\}([^\\+\"])", "$1 } $2"); // } case 1
+		processedRuleText = processedRuleText.replaceAll("\\}([^\\+\"])", " } $1"); // } case 2
+		processedRuleText = processedRuleText.replaceAll("\"\\}([^\\+\"])", "\" } $1"); // } case 3
+		
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\}\\+([^\"])", "$1 }\\+ $2"); // }+ case 1
+		processedRuleText = processedRuleText.replaceAll("\\}\\+([^\"])", " }\\+ $1 "); // }+ case 2
+		processedRuleText = processedRuleText.replaceAll("\"\\}\\+([^\"])", "\" }\\+ $1 "); // }+ case 3
+		
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\[([^\"])", "$1 [ $2"); // [ case 1
+		processedRuleText = processedRuleText.replaceAll("\\[([^\"])", " [ $1"); // [ case 2
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\[\"", "$1 [ \""); // [ case 3
+
+		processedRuleText = processedRuleText.replaceAll("([^\"])\\]([^\"])", "$1 ] $2"); // ] case 1
+		processedRuleText = processedRuleText.replaceAll("\\]([^\"])", " ] $1"); // ] case 2
+		processedRuleText = processedRuleText.replaceAll("\"\\]([^\"])", "\" ] $1"); // ] case 3
+		return processedRuleText;
 	}
 	
