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

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