source: default/trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/EbnfFormatterVisitor.java @ 22

Last change on this file since 22 was 22, checked in by zeiss, 14 years ago
  • Property svn:mime-type set to text/plain
File size: 12.0 KB
Line 
1package de.ugoe.cs.swe.bnftools.ui.formatter;
2
3import java.util.ArrayList;
4
5import org.eclipse.emf.common.util.EList;
6import org.eclipse.emf.ecore.EObject;
7import org.eclipse.xtext.parsetree.AbstractNode;
8import org.eclipse.xtext.parsetree.CompositeNode;
9import org.eclipse.xtext.parsetree.LeafNode;
10import org.eclipse.xtext.parsetree.NodeAdapter;
11import org.eclipse.xtext.parsetree.NodeUtil;
12
13import de.ugoe.cs.swe.bnftools.ebnf.Atom;
14import de.ugoe.cs.swe.bnftools.ebnf.BnfEntry;
15import de.ugoe.cs.swe.bnftools.ebnf.DefinitionList;
16import de.ugoe.cs.swe.bnftools.ebnf.DeltaEntry;
17import de.ugoe.cs.swe.bnftools.ebnf.EtsiBnf;
18import de.ugoe.cs.swe.bnftools.ebnf.ExtRule;
19import de.ugoe.cs.swe.bnftools.ebnf.GlobalCombinator;
20import de.ugoe.cs.swe.bnftools.ebnf.GroupedSequence;
21import de.ugoe.cs.swe.bnftools.ebnf.HookCombinator;
22import de.ugoe.cs.swe.bnftools.ebnf.Import;
23import de.ugoe.cs.swe.bnftools.ebnf.ImportSection;
24import de.ugoe.cs.swe.bnftools.ebnf.MergeEntry;
25import de.ugoe.cs.swe.bnftools.ebnf.MergeRule;
26import de.ugoe.cs.swe.bnftools.ebnf.OptionalSequence;
27import de.ugoe.cs.swe.bnftools.ebnf.RepeatedSequence;
28import de.ugoe.cs.swe.bnftools.ebnf.Rule;
29import de.ugoe.cs.swe.bnftools.ebnf.RuleCombinator;
30import de.ugoe.cs.swe.bnftools.ebnf.RuleReference;
31import de.ugoe.cs.swe.bnftools.ebnf.SectionHeading;
32import de.ugoe.cs.swe.bnftools.ebnf.SingleDefinition;
33import de.ugoe.cs.swe.bnftools.ebnf.StringRule;
34import de.ugoe.cs.swe.bnftools.ebnf.Term;
35import de.ugoe.cs.swe.bnftools.visitor.EbnfVisitor;
36
37public class EbnfFormatterVisitor extends EbnfVisitor {
38        private StringBuffer buf;
39        private FormatterConfig config;
40        private int bufferPosition = 0;
41        private int bufferPositionOriginalText = 0;
42        private int commentPosition = 0;
43        private int allCommentsPosition = 0;
44        private ArrayList<LeafNode> allComments = new ArrayList<LeafNode>();
45        private ArrayList<String> collectedComments = new ArrayList<String>();
46       
47        private boolean lastWasSectionHeading=false;
48        private CompositeNode parserEtsiBnfNode;
49        private String originalText;
50        private String originalTextNoWhitespaces;
51        private int bufferPositionFormattedText;
52        private String formattedText;
53        private String bufNoWhitespaces;
54       
55        public EbnfFormatterVisitor(EObject rootNode, FormatterConfig config) {
56                super(rootNode);
57                this.config = config;
58                buf = new StringBuffer();
59        }
60
61        public EbnfFormatterVisitor(FormatterConfig config) {
62                this.config = config;
63                buf = new StringBuffer();
64        }
65
66        public StringBuffer getBuf() {
67                return buf;
68        }
69
70        private boolean isCommentNode(LeafNode node) {
71                if ((node.getText().trim().startsWith("//") || node.getText().trim().startsWith("/*")) && (node.isHidden()))
72                        return true;
73                return false;
74        }
75       
76        private void collectAllComments(CompositeNode node) {
77                for (int i=0; i < node.getChildren().size(); i++) {
78                        AbstractNode currentNode = node.getChildren().get(i);
79                        if (currentNode instanceof LeafNode) {
80                                LeafNode leafNode = (LeafNode) currentNode;
81                                if (isCommentNode(leafNode)) {
82                                        allComments.add(leafNode);
83                                }
84                        }
85                       
86                        if (currentNode instanceof CompositeNode) {
87                                collectAllComments((CompositeNode) currentNode);
88                        }
89                }
90        }
91
92//      private ArrayList<String> collectComments(CompositeNode node) {
93//              collectedComments.clear();
94////            System.out.println(node);
95////            System.out.println(node.serialize());
96////            searchSubTree(node);
97//              return collectedComments;
98//      }
99       
100        private boolean isSingleLineComment(String str) {
101                if (str.startsWith("//"))
102                        return true;
103                return false;
104        }
105       
106        private boolean isMultiLineComment(String str) {
107                if (str.startsWith("/*"))
108                        return true;
109                return false;
110        }
111
112        private boolean isWhitespace(char ch) {
113                if ((ch==' ') || (ch == '\t') || (ch == '\n') || (ch == '\r'))
114                        return true;
115                return false;
116        }
117       
118        private void skipWhitespacesOriginalText() {
119                while (isWhitespace(originalText.charAt(bufferPositionOriginalText))) {
120                        bufferPositionOriginalText++;
121                }
122        }
123
124        private void skipWhitespacesFormattedText(StringBuffer result) {
125                while (isWhitespace(formattedText.charAt(bufferPositionFormattedText))) {
126                        result.append(formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1));
127                        bufferPositionFormattedText++;
128                }
129        }
130
131        private boolean isSingleLineCommentNext(String str, int position) {
132                if ((str.charAt(position) == '/') && (str.charAt(position) == '/'))
133                        return true;
134                return false;
135        }
136       
137        private boolean isMultiLineCommentNext(String str, int position) {
138                if ((str.charAt(position) == '/') && (str.charAt(position) == '*'))
139                        return true;
140                return false;
141        }
142               
143        private boolean isCommentNext(String str, int position) {
144                if (isSingleLineCommentNext(str, position) || isMultiLineCommentNext(str, position))
145                        return true;
146                else
147                        return false;
148        }
149       
150        private String scanBackWhitespaces(String str, int position) {
151                StringBuffer whiteSpaces = new StringBuffer();
152                int currentPosition = position;
153                while (isWhitespace(str.charAt(currentPosition))) {
154                        whiteSpaces.append(str.charAt(currentPosition));
155                        currentPosition--;
156                }
157                return whiteSpaces.toString();
158        }
159       
160        private String stripEndingNewline(String str) {
161                int position = str.length() - 1;
162                while ((str.charAt(position) == '\n') || (str.charAt(position) == '\r')) {
163                        position--;
164                }
165                return str.substring(0, position + 1);
166        }
167       
168        private void weaveComments() {
169                bufferPosition = 0;
170                bufferPositionOriginalText = 0;
171                bufferPositionFormattedText = 0;
172               
173                StringBuffer result = new StringBuffer();
174                bufNoWhitespaces = buf.toString().replaceAll("[ \t\n\r]", "");
175                formattedText = buf.toString();
176               
177                while (bufferPosition < bufNoWhitespaces.length()) {
178                        skipWhitespacesOriginalText();
179                        skipWhitespacesFormattedText(result);
180
181                        if (bufNoWhitespaces.charAt(bufferPosition) != originalText.charAt(bufferPositionOriginalText)) {
182                                if (isCommentNext(originalText, bufferPositionOriginalText)) {
183                                        LeafNode currentComment = allComments.get(allCommentsPosition);
184                                        if (currentComment.getTotalOffset() == bufferPositionOriginalText) {
185                                               
186                                               
187                                                if (isMultiLineComment(currentComment.getText())) {
188                                                        result.append(currentComment.getText());
189                                                        result.append("\n");
190                                                } else {
191                                                        String lastWhiteSpaces = scanBackWhitespaces(result.toString(), result.toString().length()-1);
192                                                        result.delete(result.toString().length() - lastWhiteSpaces.length(), result.toString().length());
193                                                        result.append(" " + stripEndingNewline(currentComment.getText()));
194                                                        result.append(lastWhiteSpaces);
195                                                }
196                                                bufferPositionOriginalText+=currentComment.getLength();
197                                                allCommentsPosition++;
198                                        }
199                                }
200                        } else {
201                                result.append(formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1));
202
203                                bufferPositionOriginalText++;
204                                bufferPositionFormattedText++;
205                                bufferPosition++;
206                        }
207                }
208                buf = result;
209               
210        }
211       
212        private void appendComments(EObject node) {
213//              String currentBuf = buf.toString().replaceAll("[ \t\n\r]", "");
214//              while (bufferPosition < currentBuf.length()) {
215//                      skipWhitespacesOriginalText();
216//                      System.out.print(currentBuf.charAt(bufferPosition));
217//                      System.out.print(originalText.charAt(bufferPositionOriginalText));
218//                      bufferPositionOriginalText++;
219//                      bufferPosition++;
220//              }
221               
222//
223//              ArrayList<String> comments = collectComments(parseTreeNode);
224//              for (int i=0; i < comments.size(); i++) {
225//                      if (isSingleLineComment(comments.get(i))) {
226//                              buf.append(" ");
227//                              buf.append(comments.get(i).trim());
228//                              if (i+1 < comments.size())
229//                                      buf.append("\n");
230//                      } else if (isMultiLineComment(comments.get(i))) {
231//                              buf.append("\n");
232//                              buf.append(comments.get(i));
233//                              if (i+1 < comments.size())
234//                                      buf.append("\n");
235//                      }
236//              }
237               
238        }
239       
240        // -----------------------------------------------------------------------------
241
242        protected void visitBefore(EtsiBnf node) {
243                parserEtsiBnfNode = NodeUtil.getNodeAdapter(node).getParserNode();
244                collectAllComments(parserEtsiBnfNode);
245                originalText = NodeUtil.getNodeAdapter(node).getParserNode().serialize();
246                originalTextNoWhitespaces = originalText.replaceAll("[ \t\n\r]", "");
247               
248                //System.out.println(allComments.toString());
249                buf.append("grammar " + node.getName());
250                if (node.getType() != null)
251                        buf.append(node.getType());
252                buf.append(";");
253
254                appendComments(node);
255               
256                buf.append("\n\n");
257        }
258
259        protected void visitAfter(EtsiBnf node) {
260                weaveComments();
261        }
262
263        protected void visitBefore(ImportSection node) {
264        }
265
266        protected void visitAfter(ImportSection node) {
267                buf.append("\n");
268        }
269
270        protected void visitBefore(BnfEntry node) {
271        }
272
273        protected void visitAfter(BnfEntry node) {
274        }
275       
276        protected void visitBefore(DeltaEntry node) {
277        }
278
279        protected void visitAfter(DeltaEntry node) {
280        }
281       
282        protected void visitBefore(MergeEntry node) {
283        }
284
285        protected void visitAfter(MergeEntry node) {
286        }
287       
288        protected void visitBefore(Atom node) {
289        }
290
291        protected void visitAfter(Atom node) {
292        }
293
294        protected void visitBefore(Term node) {
295        }
296
297        protected void visitAfter(Term node) {
298                if (!isLastElement())
299                        buf.append(" ");
300        }
301
302        protected void visitBefore(DefinitionList node) {
303        }
304
305        protected void visitAfter(DefinitionList node) {
306        }
307
308        protected void visitBefore(ExtRule node) {
309        }
310
311        protected void visitAfter(ExtRule node) {
312        }
313
314        protected void visitBefore(GlobalCombinator node) {
315        }
316
317        protected void visitAfter(GlobalCombinator node) {
318        }
319
320        protected void visitBefore(GroupedSequence node) {
321                buf.append("(");
322        }
323
324        protected void visitAfter(GroupedSequence node) {
325                buf.append(")");
326        }
327
328        protected void visitBefore(HookCombinator node) {
329        }
330
331        protected void visitAfter(HookCombinator node) {
332        }
333
334        protected void visitBefore(Import node) {
335                buf.append("import \"" + node.getImportURI() + "\";");
336                appendComments(node);
337                buf.append("\n");
338               
339        }
340
341        protected void visitAfter(Import node) {
342        }
343
344        protected void visitBefore(MergeRule node) {
345        }
346
347        protected void visitAfter(MergeRule node) {
348        }
349
350        protected void visitBefore(OptionalSequence node) {
351                buf.append("[");
352        }
353
354        protected void visitAfter(OptionalSequence node) {
355                buf.append("]");
356        }
357
358        protected void visitBefore(RepeatedSequence node) {
359                buf.append("{");
360        }
361
362        protected void visitAfter(RepeatedSequence node) {
363                buf.append("}");
364                if (node.isMorethanonce())
365                        buf.append("+");
366        }
367
368        protected void visitBefore(Rule node) {
369                if (lastWasSectionHeading)
370                        buf.append("\n");
371               
372                lastWasSectionHeading=false;
373
374                if (node.getRulenumber() > 0)
375                        buf.append(node.getRulenumber() + ". ");
376               
377                buf.append(node.getName() + " ::= ");
378        }
379
380        protected void visitAfter(Rule node) {
381                buf.append(";");
382//              appendComments(node);
383                buf.append("\n");
384        }
385
386        protected void visitBefore(RuleCombinator node) {
387        }
388
389        protected void visitAfter(RuleCombinator node) {
390        }
391
392        protected void visitBefore(RuleReference node) {
393                buf.append(node.getRuleref().getName());
394        }
395
396        protected void visitAfter(RuleReference node) {
397        }
398
399        protected void visitBefore(SectionHeading node) {
400                if (!lastWasSectionHeading && !buf.substring(buf.length()-2).equals("\n\n"))
401                        buf.append("\n");
402               
403                lastWasSectionHeading=true;
404//              if (!lastWasSectionHeading || !buf.substring(buf.length()-2).equals("\n\n"))
405//              if (!buf.substring(buf.length()-2).equals("\n\n"))
406//                      buf.append("\n");
407               
408                buf.append(node.getSectionHeader());
409               
410                appendComments(node);
411        }
412
413        protected void visitAfter(SectionHeading node) {
414//              buf.append("\n");
415        }
416
417        protected void visitBefore(SingleDefinition node) {
418        }
419
420        protected void visitAfter(SingleDefinition node) {
421                if (!isLastElement())
422                        buf.append(" | ");
423               
424        }
425
426        protected void visitBefore(StringRule node) {
427                if (node.getLiteral() != null)
428                        buf.append("\"" + node.getLiteral() + "\"");
429                else if (node.getColon() != null)
430                        buf.append("\"\"\"");
431        }
432
433        protected void visitAfter(StringRule node) {
434        }
435
436       
437       
438}
Note: See TracBrowser for help on using the repository browser.