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

Last change on this file since 43 was 43, checked in by zeiss, 13 years ago
  • Property svn:mime-type set to text/plain
File size: 12.9 KB
Line 
1package de.ugoe.cs.swe.bnftools.ui.formatter;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5
6import org.apache.commons.lang.StringEscapeUtils;
7import org.apache.commons.lang.StringUtils;
8import org.eclipse.emf.ecore.EObject;
9import org.eclipse.xtext.parsetree.LeafNode;
10import org.eclipse.xtext.parsetree.NodeUtil;
11
12import de.ugoe.cs.swe.bnftools.ebnf.DefinitionList;
13import de.ugoe.cs.swe.bnftools.ebnf.EtsiBnf;
14import de.ugoe.cs.swe.bnftools.ebnf.Import;
15import de.ugoe.cs.swe.bnftools.ebnf.Rule;
16import de.ugoe.cs.swe.bnftools.ebnf.RuleReference;
17import de.ugoe.cs.swe.bnftools.ebnf.SectionHeading;
18import de.ugoe.cs.swe.bnftools.ebnf.SingleDefinition;
19import de.ugoe.cs.swe.bnftools.ebnf.StringRule;
20
21public class EbnfHtmlFormatterVisitor extends EbnfFormatterVisitor {
22
23        private ArrayList<MetaTextEntry> metaTexts = new ArrayList<MetaTextEntry>();
24        private ArrayList<MetaTextEntry> transformedTexts = new ArrayList<MetaTextEntry>();
25        private int lastMetaTextBlock = 0;
26        private boolean isParagraphOpen = false;
27       
28        public EbnfHtmlFormatterVisitor(EObject rootNode, FormatterConfig config) {
29                super(rootNode, config);
30                this.config = config;
31                buf = new StringBuffer();
32        }
33
34        protected void weaveComments() {
35                bufferPositionOriginalText = 0;
36                bufferPositionFormattedTextNoWhitespaces = 0;
37                bufferPositionFormattedText = 0;
38               
39                StringBuffer result = new StringBuffer();
40                formattedTextNoWhitespaces = buf.toString().replaceAll("[ \t\n\r]", "");
41                formattedText = buf.toString();
42
43                MetaTextEntry currentMetaText = null;
44                if (metaTexts.iterator().hasNext())
45                        currentMetaText = metaTexts.iterator().next();
46
47                MetaTextEntry currentTransformedText = null;
48                if (transformedTexts.iterator().hasNext())
49                        currentTransformedText = transformedTexts.iterator().next();
50               
51                while (bufferPositionFormattedTextNoWhitespaces <= formattedTextNoWhitespaces.length()) {
52                        skipWhitespacesOriginalText();
53                        skipWhitespacesFormattedText(result);
54                       
55                        if (!(bufferPositionOriginalText < originalText.length()))
56                                break;
57                       
58                        char formattedPositionNoWhitespaces;
59                        if (bufferPositionFormattedTextNoWhitespaces == formattedTextNoWhitespaces.length()) {
60                                formattedPositionNoWhitespaces = ' ';
61                        } else {
62                                formattedPositionNoWhitespaces = formattedTextNoWhitespaces.charAt(bufferPositionFormattedTextNoWhitespaces);
63                        }
64                        char originalPosition = originalText.charAt(bufferPositionOriginalText);
65                       
66                        if (formattedPositionNoWhitespaces != originalPosition) {
67//                              if ((currentMetaText != null) && (bufferPositionFormattedTextNoWhitespaces == currentMetaText.getOffset())) {
68//                                      result.append(currentMetaText.getText());
69//                                      metaTexts.remove(currentMetaText);
70//                                      if (metaTexts.iterator().hasNext())
71//                                              currentMetaText = metaTexts.iterator().next();
72//                                      else
73//                                              currentMetaText = null;
74//                              }
75
76                                if (formattedPositionNoWhitespaces == ';') { // formatted text always outputs the optional semicolon, skip it if necessary
77                                        bufferPositionFormattedTextNoWhitespaces++;
78                                        bufferPositionFormattedText++;
79                                } else if (isCommentNext(originalText, bufferPositionOriginalText)) {
80                                        LeafNode currentComment = allComments.get(allCommentsPosition);
81                                        if (currentComment.getTotalOffset() == bufferPositionOriginalText) {
82                                                if (isMultiLineComment(currentComment.getText())) {
83                                                        int newLinesCount = scanBackNewlinesCount(originalText, bufferPositionOriginalText-1);
84                                                        if (newLinesCount > 0) {
85                                                                if (scanBackNewlinesCount(result.toString(), result.toString().length()-1) == 0) {
86                                                                        result.append("\n\n");
87                                                                }
88                                                               
89                                                                result.append(currentComment.getText());
90                                                                result.append("\n");
91                                                        } else {
92                                                                String lastWhiteSpaces = scanBackWhitespaces(result.toString(), result.toString().length()-1);
93                                                                result.delete(result.toString().length() - lastWhiteSpaces.length(), result.toString().length());
94                                                                result.append(" " + stripEndingNewline(currentComment.getText()));
95                                                                result.append(lastWhiteSpaces);
96                                                        }
97                                                } else if (isSingleLineComment(currentComment.getText())) {
98                                                        int newLinesCount = scanBackNewlinesCount(originalText, bufferPositionOriginalText-1);
99                                                        String lastWhiteSpaces = scanBackWhitespaces(result.toString(), result.toString().length()-1);
100                                                        result.delete(result.toString().length() - lastWhiteSpaces.length(), result.toString().length());
101                                                        if (newLinesCount > 0) {
102                                                                result.append("\n\n" + stripEndingNewline(currentComment.getText()));
103                                                        } else {
104                                                                result.append(" " + stripEndingNewline(currentComment.getText()));
105                                                        }
106                                                        result.append(lastWhiteSpaces);
107                                                }
108                                                bufferPositionOriginalText+=currentComment.getLength();
109                                                allCommentsPosition++;
110                                        }
111                                } else { // disaster handling: return original unformatted text!
112                                        System.err.println("Disaster Recovery: returning original text!!");
113                                        buf = new StringBuffer();
114                                        buf.append(originalText);
115                                        return;
116                                }
117                        } else {
118                                while (lastMetaTextBlock == 0 && (currentMetaText != null) && (bufferPositionFormattedTextNoWhitespaces >= currentMetaText.getOffset())) {
119                                        result.append(currentMetaText.getText());
120                                        metaTexts.remove(currentMetaText);
121                                        if (metaTexts.iterator().hasNext())
122                                                currentMetaText = metaTexts.iterator().next();
123                                        else
124                                                currentMetaText = null;
125                                       
126                                        if ((currentMetaText == null) && (bufferPositionFormattedTextNoWhitespaces != currentMetaText.getOffset()))
127                                                lastMetaTextBlock = 1;
128                                }
129
130                                if (currentTransformedText != null && currentTransformedText.getOffset() == bufferPositionFormattedTextNoWhitespaces) {
131                                        result.append(currentTransformedText.getTransformedText());
132                                        bufferPositionOriginalText += currentTransformedText.getText().length();
133                                        bufferPositionFormattedText += currentTransformedText.getText().length();
134                                        bufferPositionFormattedTextNoWhitespaces += currentTransformedText.getText().replaceAll("[ \t\r\n]", "").length();
135                                        transformedTexts.remove(currentTransformedText);
136                                        currentTransformedText = null;
137                                       
138                                        if (transformedTexts.iterator().hasNext())
139                                                currentTransformedText = transformedTexts.iterator().next();
140                                } else {
141                                        String text = formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1);
142                                        result.append(text);
143                                        bufferPositionOriginalText++;
144                                        bufferPositionFormattedText++;
145                                        bufferPositionFormattedTextNoWhitespaces++;
146                                }
147
148                                while ( lastMetaTextBlock == 1 && currentMetaText != null && bufferPositionFormattedTextNoWhitespaces >= currentMetaText.getOffset()) {
149                                        result.append(currentMetaText.getText());
150                                        metaTexts.remove(currentMetaText);
151                                        if (metaTexts.iterator().hasNext()) {
152                                                currentMetaText = metaTexts.iterator().next();
153                                        } else {
154                                                currentMetaText = null;
155                                        }
156                                       
157                                        if ((currentMetaText == null) || (bufferPositionFormattedTextNoWhitespaces != currentMetaText.getOffset()))
158                                                lastMetaTextBlock = 0;
159                                }
160                        }
161                }
162                while ( bufferPositionFormattedTextNoWhitespaces >= formattedTextNoWhitespaces.length()-1 && currentMetaText != null) {
163                        result.append(currentMetaText.getText());
164                        metaTexts.remove(currentMetaText);
165                        if (metaTexts.iterator().hasNext()) {
166                                currentMetaText = metaTexts.iterator().next();
167                        } else {
168                                currentMetaText = null;
169                        }
170                }
171
172               
173                buf = result;
174        }
175       
176        protected void metaText(String str) {
177                MetaTextEntry metaTextEntry = new MetaTextEntry(str, buf.toString().replaceAll("[ \t\n\r]", "").length());
178                metaTexts.add(metaTextEntry);
179        }
180
181        protected void textTransformed(String original, String transformed) {
182                MetaTextEntry metaText = new MetaTextEntry(original, transformed, buf.toString().replaceAll("[ \t\n\r]", "").length());
183                transformedTexts.add(metaText);
184                buf.append(original);
185                newLineOffsetCounter += original.length();
186        }
187       
188        protected void newLine() {
189                buf.append("\n");
190                if (!isParagraphOpen) {
191                        metaText("\n<p class=PL style='mso-pagination:widow-orphan lines-together;page-break-after: avoid'>\n");
192                        isParagraphOpen = true;
193                } else {
194                        metaText("\n</p>\n");
195                        isParagraphOpen = false;
196                }
197                openParagraph();
198
199                if ((ruleSpacingStack != null) && (!ruleSpacingStack.empty())) {
200                        newLineOffsetCounter = ruleSpacingStack.peek();
201                } else {
202                        newLineOffsetCounter = 0;
203                }
204        }
205       
206        protected void space() {
207                metaText("<span style='mso-spacerun:yes'>&nbsp;</span>");
208                buf.append(" ");
209                newLineOffsetCounter++;
210        }
211       
212        protected void spaces(int count) {
213                metaText("<span style='mso-spacerun:yes'>");
214                buf.append(" ");
215                for (int i=0; i < count; i++) {
216                        metaText("&nbsp;");
217                }
218                metaText("</span>");
219        }
220       
221        protected void wrap() {
222                if ((config.isWrapAfterThreshold()) && (newLineOffsetCounter > config.getWrapThreshold())) {
223                        char last = buf.toString().charAt(buf.toString().length()-1);
224                        if (!((last == '(' || last == '[' || last == '{' ))) {
225                                newLine();
226                                newLine();
227                                if (ruleSpacingStack.size() > 1)
228                                        spaces(ruleSpacingStack.peek() + 1);
229                                else
230                                        spaces(ruleSpacingStack.peek());
231                        }
232                }
233        }
234       
235        private void closeOpenParagraph() {
236                if (isParagraphOpen) {
237                        metaText("\n</p>\n");
238                        isParagraphOpen = false;
239                }
240        }
241
242        private void openParagraph() {
243                if (!isParagraphOpen) {
244                        metaText("\n<p class=PL style='mso-pagination:widow-orphan lines-together;page-break-after: avoid'>\n");
245                        isParagraphOpen = true;
246                }
247        }
248        // -----------------------------------------------------------------------------
249       
250        protected void visitBefore(EtsiBnf node) {
251                parserEtsiBnfNode = NodeUtil.getNodeAdapter(node).getParserNode();
252                collectAllComments(parserEtsiBnfNode);
253                originalText = NodeUtil.getNodeAdapter(node).getParserNode().serialize();
254                originalTextNoWhitespaces = originalText.replaceAll("[ \t\n\r]", "");
255               
256                textTransformed("grammar " + node.getName(), "");
257                if (node.getType() != null)
258                        textTransformed(node.getType(), "");
259                textTransformed(";", "");
260//              metaText("<body lang=EN-US link=blue vlink=purple style='tab-interval:14.15pt'>");
261//              metaText("<div class=WordSection1>");
262//              System.out.println("call!!!");
263               
264//              newLine();
265//              newLine();
266        }
267       
268        protected void visitAfter(EtsiBnf node) {
269                closeOpenParagraph();
270               
271                metaText("</div>\n");
272                metaText("</body>\n");
273                metaText("</html>\n");
274                weaveComments();
275        }
276
277        protected void visitBefore(Import node) {
278                textTransformed("import \"" + node.getImportURI() + "\"","");
279                if (node.getGrammarType() != null) {
280                        textTransformed("/" + node.getGrammarType(), "");
281                }
282                if (node.getLabel() != null) {
283                        space();
284                        textTransformed("label: " + node.getLabel(), "");
285                }
286                textTransformed(";", "");
287//              text("\n");
288        }
289       
290        protected void visitBefore(SectionHeading node) {
291                if (!lastWasSectionHeading && !buf.substring(buf.length()-2).equals("\n\n"))
292                        newLine();
293               
294                lastWasSectionHeading=true;
295               
296                metaText("<h3><span lang=EN-GB>\n");
297                String text = node.getSectionHeader().replaceAll("[\n\r]", "");
298                textTransformed(text, StringEscapeUtils.escapeHtml(text).replaceAll("[\n\r]", ""));
299//              textTransformed(text, text.replaceAll("[\t]", "\\<span style='mso-tab-count:1'\\>"));
300                metaText("\n</span></h3>\n");
301        }
302
303        protected void visitAfter(SectionHeading node) {
304//              newLine();
305                closeOpenParagraph();
306        }
307
308        protected void visitBefore(RuleReference node) {
309                wrap();
310               
311                metaText("<u><span style='color:blue'><a href=\"#T" + node.getRuleref().getName().replaceAll("[ \t\n\r]","") + "\">");
312                textTransformed(node.getRuleref().getName(), node.getRuleref().getName().replaceAll("[ \t\n\r]", "") + "</a></span></u>");
313        }
314
315        protected void visitAfter(RuleReference node) {
316        }
317
318        protected void visitBefore(Rule node) {
319//              if (lastWasSectionHeading)
320               
321                newLine();
322               
323                lastWasSectionHeading=false;
324
325                newLineOffsetCounter = 0;
326
327                if (node.getRulenumber() > 0)
328                        text(node.getRulenumber() + ". ");
329
330                metaText("<span lang=EN-GB style='mso-no-proof:no'>");
331                metaText("<a name=\"T" + node.getName() + "\">");
332                textTransformed(node.getName(), node.getName().replaceAll("[ \t\r\n]", ""));
333                metaText("</a>");
334                text(" ::= ");
335               
336                rightHandSideRuleOffset = newLineOffsetCounter;
337                ruleSpacingStack.push(newLineOffsetCounter);
338        }
339       
340        protected void visitAfter(Rule node) {
341                metaText("<o:p></o:p>\n</span>");
342                text(";");
343                newLine();
344                text("\n");
345                ruleSpacingStack.pop();
346        }
347       
348        protected void visitBefore(StringRule node) {
349                wrap();
350                if (node.getLiteral() != null) {
351//                      text("\"" + node.getLiteral() + "\"");
352                        textTransformed("\"" + node.getLiteral() + "\"", StringEscapeUtils.escapeHtml("\"" + node.getLiteral() + "\"").replaceAll("[ \t\n\r]", ""));
353//                      textTransformed("\"" + node.getLiteral() + "\"", "gnabar");
354                } else if (node.getColon() != null) {
355//                      text("\"\"\"");
356                        textTransformed("\"\"\"", StringEscapeUtils.escapeHtml("\"\"\"").replaceAll("[ \t\n\r]", ""));
357//                      textTransformed("\"\"\"", "gnabar");
358                }
359        }
360
361        protected void visitAfter(StringRule node) {
362        }
363}
Note: See TracBrowser for help on using the repository browser.