Index: trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/EbnfFormatterVisitor.java
===================================================================
--- trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/EbnfFormatterVisitor.java	(revision 20)
+++ trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/EbnfFormatterVisitor.java	(revision 21)
@@ -1,6 +1,13 @@
 package de.ugoe.cs.swe.bnftools.ui.formatter;
+
+import java.util.ArrayList;
 
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.parsetree.AbstractNode;
+import org.eclipse.xtext.parsetree.CompositeNode;
+import org.eclipse.xtext.parsetree.LeafNode;
+import org.eclipse.xtext.parsetree.NodeAdapter;
+import org.eclipse.xtext.parsetree.NodeUtil;
 
 import de.ugoe.cs.swe.bnftools.ebnf.Atom;
@@ -31,6 +38,18 @@
 	private StringBuffer buf;
 	private FormatterConfig config;
-
+	private int bufferPosition = 0;
+	private int bufferPositionOriginalText = 0;
+	private int commentPosition = 0;
+	private int allCommentsPosition = 0;
+	private ArrayList<LeafNode> allComments = new ArrayList<LeafNode>();
+	private ArrayList<String> collectedComments = new ArrayList<String>();
+	
 	private boolean lastWasSectionHeading=false;
+	private CompositeNode parserEtsiBnfNode;
+	private String originalText;
+	private String originalTextNoWhitespaces;
+	private int bufferPositionFormattedText;
+	private String formattedText;
+	private String bufNoWhitespaces;
 	
 	public EbnfFormatterVisitor(EObject rootNode, FormatterConfig config) {
@@ -49,19 +68,175 @@
 	}
 
+	private boolean isCommentNode(LeafNode node) {
+		if ((node.getText().trim().startsWith("//") || node.getText().trim().startsWith("/*")) && (node.isHidden()))
+			return true;
+		return false;
+	}
+	
+	private void collectAllComments(CompositeNode node) {
+		for (int i=0; i < node.getChildren().size(); i++) {
+			AbstractNode currentNode = node.getChildren().get(i);
+			if (currentNode instanceof LeafNode) {
+				LeafNode leafNode = (LeafNode) currentNode;
+				if (isCommentNode(leafNode)) {
+					allComments.add(leafNode);
+				} 
+			}
+			
+			if (currentNode instanceof CompositeNode) {
+				collectAllComments((CompositeNode) currentNode);
+			}
+		}
+	}
+
+//	private ArrayList<String> collectComments(CompositeNode node) {
+//		collectedComments.clear();
+////		System.out.println(node);
+////		System.out.println(node.serialize());
+////		searchSubTree(node);
+//		return collectedComments;
+//	}
+	
+	private boolean isSingleLineComment(String str) {
+		if (str.startsWith("//"))
+			return true;
+		return false;
+	}
+	
+	private boolean isMultiLineComment(String str) {
+		if (str.startsWith("/*"))
+			return true;
+		return false;
+	}
+
+	private boolean isWhitespace(char ch) {
+		if ((ch==' ') || (ch == '\t') || (ch == '\n') || (ch == '\r'))
+			return true;
+		return false;
+	}
+	
+	private void skipWhitespacesOriginalText() {
+		while (isWhitespace(originalText.charAt(bufferPositionOriginalText))) {
+			bufferPositionOriginalText++;
+		}
+	}
+
+	private void skipWhitespacesFormattedText(StringBuffer result) {
+		while (isWhitespace(formattedText.charAt(bufferPositionFormattedText))) {
+			result.append(formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1));
+			bufferPositionFormattedText++;
+		}
+	}
+
+	private boolean isSingleLineCommentNext(String str, int position) {
+		if ((str.charAt(position) == '/') && (str.charAt(position) == '/'))
+			return true;
+		return false;
+	}
+	
+	private boolean isMultiLineCommentNext(String str, int position) {
+		if ((str.charAt(position) == '/') && (str.charAt(position) == '*'))
+			return true;
+		return false;
+	}
+		
+	private boolean isCommentNext(String str, int position) {
+		if (isSingleLineCommentNext(str, position) || isMultiLineCommentNext(str, position))
+			return true;
+		else
+			return false;
+	}
+	
+	private void weaveComments() {
+		bufferPosition = 0;
+		bufferPositionOriginalText = 0;
+		bufferPositionFormattedText = 0;
+		
+		StringBuffer result = new StringBuffer();
+		bufNoWhitespaces = buf.toString().replaceAll("[ \t\n\r]", "");
+		formattedText = buf.toString();
+		
+		while (bufferPosition < bufNoWhitespaces.length()) {
+			skipWhitespacesOriginalText();
+			skipWhitespacesFormattedText(result);
+
+			if (bufNoWhitespaces.charAt(bufferPosition) != originalText.charAt(bufferPositionOriginalText)) {
+				if (isCommentNext(originalText, bufferPositionOriginalText)) {
+					LeafNode currentComment = allComments.get(allCommentsPosition); 
+					if (currentComment.getTotalOffset() == bufferPositionOriginalText) {
+						result.append(currentComment.getText());
+						
+						if (isMultiLineComment(currentComment.getText())) {
+							result.append("\n");
+						} 
+						bufferPositionOriginalText+=currentComment.getLength();
+						allCommentsPosition++;
+					}
+				}
+				
+			} else {
+				result.append(formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1));
+
+				bufferPositionOriginalText++;
+				bufferPositionFormattedText++;
+				bufferPosition++;
+			}
+		}
+		buf = result;
+		
+	}
+	
+	private void appendComments(EObject node) {
+//		String currentBuf = buf.toString().replaceAll("[ \t\n\r]", "");
+//		while (bufferPosition < currentBuf.length()) {
+//			skipWhitespacesOriginalText();
+//			System.out.print(currentBuf.charAt(bufferPosition));
+//			System.out.print(originalText.charAt(bufferPositionOriginalText));
+//			bufferPositionOriginalText++;
+//			bufferPosition++;
+//		}
+		
+//
+//		ArrayList<String> comments = collectComments(parseTreeNode);
+//		for (int i=0; i < comments.size(); i++) {
+//			if (isSingleLineComment(comments.get(i))) {
+//				buf.append(" ");
+//				buf.append(comments.get(i).trim());
+//				if (i+1 < comments.size())
+//					buf.append("\n");
+//			} else if (isMultiLineComment(comments.get(i))) {
+//				buf.append("\n");
+//				buf.append(comments.get(i));
+//				if (i+1 < comments.size())
+//					buf.append("\n");
+//			}
+//		}
+		
+	}
+	
 	// -----------------------------------------------------------------------------
 
 	protected void visitBefore(EtsiBnf node) {
+		parserEtsiBnfNode = NodeUtil.getNodeAdapter(node).getParserNode();
+		collectAllComments(parserEtsiBnfNode);
+		originalText = NodeUtil.getNodeAdapter(node).getParserNode().serialize();
+		originalTextNoWhitespaces = originalText.replaceAll("[ \t\n\r]", "");
+		
+		//System.out.println(allComments.toString());
 		buf.append("grammar " + node.getName());
 		if (node.getType() != null)
 			buf.append(node.getType());
 		buf.append(";");
-		buf.append("\n");
+
+		appendComments(node);
+		
+		buf.append("\n\n");
 	}
 
 	protected void visitAfter(EtsiBnf node) {
+		weaveComments();
 	}
 
 	protected void visitBefore(ImportSection node) {
-		buf.append("\n");
 	}
 
@@ -135,5 +310,8 @@
 
 	protected void visitBefore(Import node) {
-		buf.append("import \"" + node.getImportURI() + "\";\n");
+		buf.append("import \"" + node.getImportURI() + "\";");
+		appendComments(node);
+		buf.append("\n");
+		
 	}
 
@@ -178,5 +356,7 @@
 
 	protected void visitAfter(Rule node) {
-		buf.append(";\n");
+		buf.append(";");
+//		appendComments(node);
+		buf.append("\n");
 	}
 
@@ -204,4 +384,6 @@
 		
 		buf.append(node.getSectionHeader());
+		
+		appendComments(node);
 	}
 
