summaryrefslogtreecommitdiffstats
path: root/parser/html/java/htmlparser/translator-src/nu/validator
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-01-15 14:56:04 -0500
committerMatt A. Tobin <email@mattatobin.com>2020-01-15 14:56:04 -0500
commit6168dbe21f5f83b906e562ea0ab232d499b275a6 (patch)
tree658a4b27554c85ebcaad655fc83f2c2bb99e8e80 /parser/html/java/htmlparser/translator-src/nu/validator
parent09314667a692fedff8564fc347c8a3663474faa6 (diff)
downloadUXP-6168dbe21f5f83b906e562ea0ab232d499b275a6.tar
UXP-6168dbe21f5f83b906e562ea0ab232d499b275a6.tar.gz
UXP-6168dbe21f5f83b906e562ea0ab232d499b275a6.tar.lz
UXP-6168dbe21f5f83b906e562ea0ab232d499b275a6.tar.xz
UXP-6168dbe21f5f83b906e562ea0ab232d499b275a6.zip
Add java htmlparser sources that match the original 52-level state
https://hg.mozilla.org/projects/htmlparser/ Commit: abe62ab2a9b69ccb3b5d8a231ec1ae11154c571d
Diffstat (limited to 'parser/html/java/htmlparser/translator-src/nu/validator')
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java139
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppOnlyInputStream.java70
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java445
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java2421
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/GkAtomParser.java70
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/HVisitor.java306
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LabelVisitor.java84
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LicenseExtractor.java75
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LocalSymbolTable.java89
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Main.java148
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/NoCppInputStream.java86
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringLiteralParser.java70
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringPair.java73
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTable.java80
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTableVisitor.java71
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/TranslatorUtils.java81
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Type.java99
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/ApplyHotSpotWorkaround.java104
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharacters.java182
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharactersCpp.java580
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/DuplicatingFallThroughRemover.java79
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/JavaVisitor.java1349
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/LoopBreakAnalyzerVisitor.java183
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/Main.java144
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/ModeFallThroughRemover.java106
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/RustVisitor.java1586
-rw-r--r--parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/SwitchBreakAnalyzerVisitor.java191
27 files changed, 8911 insertions, 0 deletions
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java
new file mode 100644
index 000000000..337394a89
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java
@@ -0,0 +1,139 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.util.List;
+
+import japa.parser.ast.expr.AnnotationExpr;
+import japa.parser.ast.expr.MarkerAnnotationExpr;
+import japa.parser.ast.type.ReferenceType;
+import japa.parser.ast.visitor.VoidVisitorAdapter;
+
+public class AnnotationHelperVisitor<T> extends VoidVisitorAdapter<T> {
+
+ protected List<AnnotationExpr> currentAnnotations;
+
+ protected boolean nsUri() {
+ return hasAnnotation("NsUri");
+ }
+
+ protected boolean prefix() {
+ return hasAnnotation("Prefix");
+ }
+
+ protected boolean local() {
+ return hasAnnotation("Local");
+ }
+
+ protected boolean literal() {
+ return hasAnnotation("Literal");
+ }
+
+ protected boolean inline() {
+ return hasAnnotation("Inline");
+ }
+
+ protected boolean noLength() {
+ return hasAnnotation("NoLength");
+ }
+
+ protected boolean auto() {
+ return hasAnnotation("Auto");
+ }
+
+ protected boolean virtual() {
+ return hasAnnotation("Virtual");
+ }
+
+ protected boolean isConst() {
+ return hasAnnotation("Const");
+ }
+
+ protected boolean characterName() {
+ return hasAnnotation("CharacterName");
+ }
+
+ private boolean hasAnnotation(String anno) {
+ if (currentAnnotations == null) {
+ return false;
+ }
+ for (AnnotationExpr ann : currentAnnotations) {
+ if (ann instanceof MarkerAnnotationExpr) {
+ MarkerAnnotationExpr marker = (MarkerAnnotationExpr) ann;
+ if (marker.getName().getName().equals(anno)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected Type convertType(japa.parser.ast.type.Type type, int modifiers) {
+ if (type instanceof ReferenceType) {
+ ReferenceType referenceType = (ReferenceType) type;
+ return new Type(convertTypeName(referenceType.getType().toString()), referenceType.getArrayCount(), noLength(), modifiers);
+ } else {
+ return new Type(convertTypeName(type.toString()), 0, false, modifiers);
+ }
+ }
+
+ private String convertTypeName(String name) {
+ if ("String".equals(name)) {
+ if (local()) {
+ return "@Local";
+ }
+ if (nsUri()) {
+ return "@NsUri";
+ }
+ if (prefix()) {
+ return "@Prefix";
+ }
+ if (literal()) {
+ return "@Literal";
+ }
+ if (auto()) {
+ return "@Auto";
+ }
+ if (characterName()) {
+ return "@CharacterName";
+ }
+ }
+ return name;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppOnlyInputStream.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppOnlyInputStream.java
new file mode 100644
index 000000000..587b81604
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppOnlyInputStream.java
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class CppOnlyInputStream extends InputStream {
+
+ private static final String DROP = "// CPPONLY:";
+
+ private final InputStream delegate;
+
+ public CppOnlyInputStream(InputStream delegate) {
+ this.delegate = new BufferedInputStream(delegate);
+ }
+
+ @Override public int read() throws IOException {
+ int c = delegate.read();
+ if (c == DROP.charAt(0)) {
+ delegate.mark(DROP.length());
+ for (int i = 1; i < DROP.length(); ++i) {
+ int d = delegate.read();
+ if (d != DROP.charAt(i)) {
+ delegate.reset();
+ return c;
+ }
+ }
+ return delegate.read();
+ }
+ return c;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java
new file mode 100644
index 000000000..35c3f6685
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java
@@ -0,0 +1,445 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008-2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class CppTypes {
+
+ /**
+ * The license for the atom list written by this program.
+ */
+ private static final String ATOM_LICENSE = "/*\n"
+ + " * Copyright (c) 2008-2010 Mozilla Foundation\n"
+ + " *\n"
+ + " * Permission is hereby granted, free of charge, to any person obtaining a \n"
+ + " * copy of this software and associated documentation files (the \"Software\"), \n"
+ + " * to deal in the Software without restriction, including without limitation \n"
+ + " * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n"
+ + " * and/or sell copies of the Software, and to permit persons to whom the \n"
+ + " * Software is furnished to do so, subject to the following conditions:\n"
+ + " *\n"
+ + " * The above copyright notice and this permission notice shall be included in \n"
+ + " * all copies or substantial portions of the Software.\n"
+ + " *\n"
+ + " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \n"
+ + " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n"
+ + " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \n"
+ + " * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n"
+ + " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n"
+ + " * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n"
+ + " * DEALINGS IN THE SOFTWARE.\n" + " */\n\n";
+
+ private static Set<String> reservedWords = new HashSet<String>();
+
+ static {
+ reservedWords.add("small");
+ reservedWords.add("for");
+ reservedWords.add("false");
+ reservedWords.add("true");
+ reservedWords.add("default");
+ reservedWords.add("class");
+ reservedWords.add("switch");
+ reservedWords.add("union");
+ reservedWords.add("template");
+ reservedWords.add("int");
+ reservedWords.add("char");
+ reservedWords.add("operator");
+ reservedWords.add("or");
+ reservedWords.add("and");
+ reservedWords.add("not");
+ reservedWords.add("xor");
+ reservedWords.add("unicode");
+ }
+
+ private static final String[] TREE_BUILDER_INCLUDES = { "nsContentUtils",
+ "nsIAtom", "nsHtml5AtomTable", "nsITimer", "nsString",
+ "nsNameSpaceManager", "nsIContent", "nsTraceRefcnt", "jArray",
+ "nsHtml5DocumentMode", "nsHtml5ArrayCopy", "nsHtml5Parser",
+ "nsHtml5Atoms", "nsHtml5TreeOperation", "nsHtml5StateSnapshot",
+ "nsHtml5StackNode", "nsHtml5TreeOpExecutor", "nsHtml5StreamParser",
+ "nsAHtml5TreeBuilderState", "nsHtml5Highlighter",
+ "nsHtml5PlainTextUtils", "nsHtml5ViewSourceUtils",
+ "mozilla/Likely", "nsIContentHandle", "nsHtml5OplessBuilder" };
+
+ private static final String[] TOKENIZER_INCLUDES = { "nsIAtom",
+ "nsHtml5AtomTable", "nsString", "nsIContent", "nsTraceRefcnt",
+ "jArray", "nsHtml5DocumentMode", "nsHtml5ArrayCopy",
+ "nsHtml5NamedCharacters", "nsHtml5NamedCharactersAccel",
+ "nsHtml5Atoms", "nsAHtml5TreeBuilderState", "nsHtml5Macros",
+ "nsHtml5Highlighter", "nsHtml5TokenizerLoopPolicies" };
+
+ private static final String[] INCLUDES = { "nsIAtom", "nsHtml5AtomTable",
+ "nsString", "nsNameSpaceManager", "nsIContent", "nsTraceRefcnt",
+ "jArray", "nsHtml5ArrayCopy", "nsAHtml5TreeBuilderState",
+ "nsHtml5Atoms", "nsHtml5ByteReadable", "nsIUnicodeDecoder",
+ "nsHtml5Macros", "nsIContentHandle" };
+
+ private static final String[] OTHER_DECLATIONS = {};
+
+ private static final String[] TREE_BUILDER_OTHER_DECLATIONS = {};
+
+ private static final String[] NAMED_CHARACTERS_INCLUDES = { "jArray",
+ "nscore", "nsDebug", "prlog", "mozilla/ArrayUtils" };
+
+ private static final String[] FORWARD_DECLARATIONS = { "nsHtml5StreamParser" };
+
+ private static final String[] CLASSES_THAT_NEED_SUPPLEMENT = {
+ "MetaScanner", "Tokenizer", "TreeBuilder", "UTF16Buffer", };
+
+ private static final String[] STATE_LOOP_POLICIES = {
+ "nsHtml5ViewSourcePolicy", "nsHtml5SilentPolicy" };
+
+ private final Map<String, String> atomMap = new HashMap<String, String>();
+
+ private final Writer atomWriter;
+
+ public CppTypes(File atomList) {
+ if (atomList == null) {
+ atomWriter = null;
+ } else {
+ try {
+ atomWriter = new OutputStreamWriter(new FileOutputStream(
+ atomList), "utf-8");
+ atomWriter.write(ATOM_LICENSE);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public void finished() {
+ try {
+ if (atomWriter != null) {
+ atomWriter.flush();
+ atomWriter.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String classPrefix() {
+ return "nsHtml5";
+ }
+
+ public String booleanType() {
+ return "bool";
+ }
+
+ public String byteType() {
+ return "int8_t";
+ }
+
+ public String charType() {
+ return "char16_t";
+ }
+
+ /**
+ * Only used for named characters.
+ *
+ * @return
+ */
+ public String unsignedShortType() {
+ return "uint16_t";
+ }
+
+ public String intType() {
+ return "int32_t";
+ }
+
+ public String stringType() {
+ return "nsString*";
+ }
+
+ public String localType() {
+ return "nsIAtom*";
+ }
+
+ public String prefixType() {
+ return "nsIAtom*";
+ }
+
+ public String nsUriType() {
+ return "int32_t";
+ }
+
+ public String falseLiteral() {
+ return "false";
+ }
+
+ public String trueLiteral() {
+ return "true";
+ }
+
+ public String nullLiteral() {
+ return "nullptr";
+ }
+
+ public String encodingDeclarationHandlerType() {
+ return "nsHtml5StreamParser*";
+ }
+
+ public String nodeType() {
+ return "nsIContentHandle*";
+ }
+
+ public String xhtmlNamespaceLiteral() {
+ return "kNameSpaceID_XHTML";
+ }
+
+ public String svgNamespaceLiteral() {
+ return "kNameSpaceID_SVG";
+ }
+
+ public String xmlnsNamespaceLiteral() {
+ return "kNameSpaceID_XMLNS";
+ }
+
+ public String xmlNamespaceLiteral() {
+ return "kNameSpaceID_XML";
+ }
+
+ public String noNamespaceLiteral() {
+ return "kNameSpaceID_None";
+ }
+
+ public String xlinkNamespaceLiteral() {
+ return "kNameSpaceID_XLink";
+ }
+
+ public String mathmlNamespaceLiteral() {
+ return "kNameSpaceID_MathML";
+ }
+
+ public String arrayTemplate() {
+ return "jArray";
+ }
+
+ public String autoArrayTemplate() {
+ return "autoJArray";
+ }
+
+ public String localForLiteral(String literal) {
+ String atom = atomMap.get(literal);
+ if (atom == null) {
+ atom = createAtomName(literal);
+ atomMap.put(literal, atom);
+ if (atomWriter != null) {
+ try {
+ atomWriter.write("HTML5_ATOM(" + atom + ", \"" + literal
+ + "\")\n");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ return "nsHtml5Atoms::" + atom;
+ }
+
+ private String createAtomName(String literal) {
+ String candidate = literal.replaceAll("[^a-zA-Z0-9_]", "_");
+ if ("".equals(candidate)) {
+ candidate = "emptystring";
+ }
+ while (atomMap.values().contains(candidate)
+ || reservedWords.contains(candidate)) {
+ candidate = candidate + '_';
+ }
+ return candidate;
+ }
+
+ public String stringForLiteral(String literal) {
+ return '"' + literal + '"';
+ }
+
+ public String staticArrayTemplate() {
+ return "staticJArray";
+ }
+
+ public String newArrayCreator() {
+ return "newJArray";
+ }
+
+ public String[] boilerplateIncludes(String javaClass) {
+ if ("TreeBuilder".equals(javaClass)) {
+ return TREE_BUILDER_INCLUDES;
+ } else if ("Tokenizer".equals(javaClass)) {
+ return TOKENIZER_INCLUDES;
+ } else {
+ return INCLUDES;
+ }
+ }
+
+ public String[] boilerplateDeclarations(String javaClass) {
+ if ("TreeBuilder".equals(javaClass)) {
+ return TREE_BUILDER_OTHER_DECLATIONS;
+ } else {
+ return OTHER_DECLATIONS;
+ }
+ }
+
+ public String[] namedCharactersIncludes() {
+ return NAMED_CHARACTERS_INCLUDES;
+ }
+
+ public String[] boilerplateForwardDeclarations() {
+ return FORWARD_DECLARATIONS;
+ }
+
+ public String documentModeHandlerType() {
+ return "nsHtml5TreeBuilder*";
+ }
+
+ public String documentModeType() {
+ return "nsHtml5DocumentMode";
+ }
+
+ public String arrayCopy() {
+ return "nsHtml5ArrayCopy::arraycopy";
+ }
+
+ public String maxInteger() {
+ return "INT32_MAX";
+ }
+
+ public String constructorBoilerplate(String className) {
+ return "MOZ_COUNT_CTOR(" + className + ");";
+ }
+
+ public String destructorBoilderplate(String className) {
+ return "MOZ_COUNT_DTOR(" + className + ");";
+ }
+
+ public String literalType() {
+ return "const char*";
+ }
+
+ public boolean hasSupplement(String javaClass) {
+ return Arrays.binarySearch(CLASSES_THAT_NEED_SUPPLEMENT, javaClass) > -1;
+ }
+
+ public String internerType() {
+ return "nsHtml5AtomTable*";
+ }
+
+ public String treeBuilderStateInterface() {
+ return "nsAHtml5TreeBuilderState";
+ }
+
+ public String treeBuilderStateType() {
+ return "nsAHtml5TreeBuilderState*";
+ }
+
+ public String arrayLengthMacro() {
+ return "MOZ_ARRAY_LENGTH";
+ }
+
+ public String staticAssert() {
+ return "PR_STATIC_ASSERT";
+ }
+
+ public String abortIfFalse() {
+ return "NS_ABORT_IF_FALSE";
+ }
+
+ public String continueMacro() {
+ return "NS_HTML5_CONTINUE";
+ }
+
+ public String breakMacro() {
+ return "NS_HTML5_BREAK";
+ }
+
+ public String characterNameType() {
+ return "nsHtml5CharacterName&";
+ }
+
+ public String characterNameTypeDeclaration() {
+ return "nsHtml5CharacterName";
+ }
+
+ public String transition() {
+ return "P::transition";
+ }
+
+ public String tokenizerErrorCondition() {
+ return "P::reportErrors";
+ }
+
+ public String firstTransitionArg() {
+ return "mViewSource";
+ }
+
+ public String errorHandler() {
+ return this.unlikely() + "(mViewSource)";
+ }
+
+ public String unlikely() {
+ return "MOZ_UNLIKELY";
+ }
+
+ public String completedCharacterReference() {
+ return "P::completedNamedCharacterReference(mViewSource)";
+ }
+
+ public String[] stateLoopPolicies() {
+ return STATE_LOOP_POLICIES;
+ }
+
+ public String assertionMacro() {
+ return "MOZ_ASSERT";
+ }
+
+ public String releaseAssertionMacro() {
+ return "MOZ_RELEASE_ASSERT";
+ }
+
+ public String crashMacro() {
+ return "MOZ_CRASH";
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java
new file mode 100644
index 000000000..66f7678aa
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/CppVisitor.java
@@ -0,0 +1,2421 @@
+/*
+ * Copyright (C) 2007 Júlio Vilmar Gesser.
+ * Copyright (C) 2008 Mozilla Foundation
+ *
+ * This file is part of HTML Parser C++ Translator. It was derived from DumpVisitor
+ * which was part of Java 1.5 parser and Abstract Syntax Tree and came with the following notice:
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 05/10/2006
+ */
+package nu.validator.htmlparser.cpptranslate;
+
+import japa.parser.ast.BlockComment;
+import japa.parser.ast.CompilationUnit;
+import japa.parser.ast.ImportDeclaration;
+import japa.parser.ast.LineComment;
+import japa.parser.ast.Node;
+import japa.parser.ast.PackageDeclaration;
+import japa.parser.ast.TypeParameter;
+import japa.parser.ast.body.AnnotationDeclaration;
+import japa.parser.ast.body.AnnotationMemberDeclaration;
+import japa.parser.ast.body.BodyDeclaration;
+import japa.parser.ast.body.ClassOrInterfaceDeclaration;
+import japa.parser.ast.body.ConstructorDeclaration;
+import japa.parser.ast.body.EmptyMemberDeclaration;
+import japa.parser.ast.body.EmptyTypeDeclaration;
+import japa.parser.ast.body.EnumConstantDeclaration;
+import japa.parser.ast.body.EnumDeclaration;
+import japa.parser.ast.body.FieldDeclaration;
+import japa.parser.ast.body.InitializerDeclaration;
+import japa.parser.ast.body.JavadocComment;
+import japa.parser.ast.body.MethodDeclaration;
+import japa.parser.ast.body.ModifierSet;
+import japa.parser.ast.body.Parameter;
+import japa.parser.ast.body.TypeDeclaration;
+import japa.parser.ast.body.VariableDeclarator;
+import japa.parser.ast.body.VariableDeclaratorId;
+import japa.parser.ast.expr.ArrayAccessExpr;
+import japa.parser.ast.expr.ArrayCreationExpr;
+import japa.parser.ast.expr.ArrayInitializerExpr;
+import japa.parser.ast.expr.AssignExpr;
+import japa.parser.ast.expr.BinaryExpr;
+import japa.parser.ast.expr.BooleanLiteralExpr;
+import japa.parser.ast.expr.CastExpr;
+import japa.parser.ast.expr.CharLiteralExpr;
+import japa.parser.ast.expr.ClassExpr;
+import japa.parser.ast.expr.ConditionalExpr;
+import japa.parser.ast.expr.DoubleLiteralExpr;
+import japa.parser.ast.expr.EnclosedExpr;
+import japa.parser.ast.expr.Expression;
+import japa.parser.ast.expr.FieldAccessExpr;
+import japa.parser.ast.expr.InstanceOfExpr;
+import japa.parser.ast.expr.IntegerLiteralExpr;
+import japa.parser.ast.expr.IntegerLiteralMinValueExpr;
+import japa.parser.ast.expr.LongLiteralExpr;
+import japa.parser.ast.expr.LongLiteralMinValueExpr;
+import japa.parser.ast.expr.MarkerAnnotationExpr;
+import japa.parser.ast.expr.MemberValuePair;
+import japa.parser.ast.expr.MethodCallExpr;
+import japa.parser.ast.expr.NameExpr;
+import japa.parser.ast.expr.NormalAnnotationExpr;
+import japa.parser.ast.expr.NullLiteralExpr;
+import japa.parser.ast.expr.ObjectCreationExpr;
+import japa.parser.ast.expr.QualifiedNameExpr;
+import japa.parser.ast.expr.SingleMemberAnnotationExpr;
+import japa.parser.ast.expr.StringLiteralExpr;
+import japa.parser.ast.expr.SuperExpr;
+import japa.parser.ast.expr.ThisExpr;
+import japa.parser.ast.expr.UnaryExpr;
+import japa.parser.ast.expr.VariableDeclarationExpr;
+import japa.parser.ast.stmt.AssertStmt;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.CatchClause;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.stmt.DoStmt;
+import japa.parser.ast.stmt.EmptyStmt;
+import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.ForStmt;
+import japa.parser.ast.stmt.ForeachStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.LabeledStmt;
+import japa.parser.ast.stmt.ReturnStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.stmt.SynchronizedStmt;
+import japa.parser.ast.stmt.ThrowStmt;
+import japa.parser.ast.stmt.TryStmt;
+import japa.parser.ast.stmt.TypeDeclarationStmt;
+import japa.parser.ast.stmt.WhileStmt;
+import japa.parser.ast.type.ClassOrInterfaceType;
+import japa.parser.ast.type.PrimitiveType;
+import japa.parser.ast.type.ReferenceType;
+import japa.parser.ast.type.Type;
+import japa.parser.ast.type.VoidType;
+import japa.parser.ast.type.WildcardType;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+
+public class CppVisitor extends AnnotationHelperVisitor<LocalSymbolTable> {
+
+ private static final String[] CLASS_NAMES = { "AttributeName",
+ "ElementName", "HtmlAttributes", "LocatorImpl", "MetaScanner",
+ "NamedCharacters", "NamedCharactersAccel", "Portability",
+ "StackNode", "Tokenizer", "TreeBuilder", "UTF16Buffer" };
+
+ private static final String[] METHODS_WITH_UNLIKELY_CONDITIONS = {
+ "appendStrBuf" };
+
+ public class SourcePrinter {
+
+ private int level = 0;
+
+ private boolean indented = false;
+
+ private final StringBuilder buf = new StringBuilder();
+
+ public void indent() {
+ level++;
+ }
+
+ public void unindent() {
+ level--;
+ }
+
+ private void makeIndent() {
+ for (int i = 0; i < level; i++) {
+ buf.append(" ");
+ }
+ }
+
+ public void printWithoutIndent(String arg) {
+ indented = false;
+ buf.append(arg);
+ }
+
+ public void print(String arg) {
+ if (!indented) {
+ makeIndent();
+ indented = true;
+ }
+ buf.append(arg);
+ }
+
+ public void printLn(String arg) {
+ print(arg);
+ printLn();
+ }
+
+ public void printLn() {
+ buf.append("\n");
+ indented = false;
+ }
+
+ public String getSource() {
+ return buf.toString();
+ }
+
+ @Override public String toString() {
+ return getSource();
+ }
+ }
+
+ private boolean supportErrorReporting = true;
+
+ protected SourcePrinter printer = new SourcePrinter();
+
+ private SourcePrinter staticInitializerPrinter = new SourcePrinter();
+
+ private SourcePrinter tempPrinterHolder;
+
+ protected final CppTypes cppTypes;
+
+ protected String className = "";
+
+ protected int currentArrayCount;
+
+ protected Set<String> forLoopsWithCondition = new HashSet<String>();
+
+ protected boolean inPrimitiveNoLengthFieldDeclarator = false;
+
+ protected final SymbolTable symbolTable;
+
+ protected String definePrefix;
+
+ protected String javaClassName;
+
+ protected boolean suppressPointer = false;
+
+ private final List<String> staticReleases = new LinkedList<String>();
+
+ private boolean inConstructorBody = false;
+
+ private String currentMethod = null;
+
+ private Set<String> labels = null;
+
+ private boolean destructor;
+
+ protected boolean inStatic = false;
+
+ private boolean reportTransitions = false;
+
+ private int stateLoopCallCount = 0;
+
+ /**
+ * @param cppTypes
+ */
+ public CppVisitor(CppTypes cppTypes, SymbolTable symbolTable) {
+ this.cppTypes = cppTypes;
+ this.symbolTable = symbolTable;
+ staticInitializerPrinter.indent();
+ }
+
+ public String getSource() {
+ return printer.getSource();
+ }
+
+ private String classNameFromExpression(Expression e) {
+ if (e instanceof NameExpr) {
+ NameExpr nameExpr = (NameExpr) e;
+ String name = nameExpr.getName();
+ if (Arrays.binarySearch(CLASS_NAMES, name) > -1) {
+ return name;
+ }
+ }
+ return null;
+ }
+
+ protected void printModifiers(int modifiers) {
+ }
+
+ private void printMembers(List<BodyDeclaration> members,
+ LocalSymbolTable arg) {
+ for (BodyDeclaration member : members) {
+ if ("Tokenizer".equals(javaClassName)
+ && member instanceof MethodDeclaration
+ && "stateLoop".equals(((MethodDeclaration) member).getName())) {
+ reportTransitions = true;
+ }
+ member.accept(this, arg);
+ reportTransitions = false;
+ }
+ }
+
+ private void printTypeArgs(List<Type> args, LocalSymbolTable arg) {
+ // if (args != null) {
+ // printer.print("<");
+ // for (Iterator<Type> i = args.iterator(); i.hasNext();) {
+ // Type t = i.next();
+ // t.accept(this, arg);
+ // if (i.hasNext()) {
+ // printer.print(", ");
+ // }
+ // }
+ // printer.print(">");
+ // }
+ }
+
+ private void printTypeParameters(List<TypeParameter> args,
+ LocalSymbolTable arg) {
+ // if (args != null) {
+ // printer.print("<");
+ // for (Iterator<TypeParameter> i = args.iterator(); i.hasNext();) {
+ // TypeParameter t = i.next();
+ // t.accept(this, arg);
+ // if (i.hasNext()) {
+ // printer.print(", ");
+ // }
+ // }
+ // printer.print(">");
+ // }
+ }
+
+ public void visit(Node n, LocalSymbolTable arg) {
+ throw new IllegalStateException(n.getClass().getName());
+ }
+
+ public void visit(CompilationUnit n, LocalSymbolTable arg) {
+ if (n.getTypes() != null) {
+ for (Iterator<TypeDeclaration> i = n.getTypes().iterator(); i.hasNext();) {
+ i.next().accept(this, arg);
+ printer.printLn();
+ if (i.hasNext()) {
+ printer.printLn();
+ }
+ }
+ }
+ }
+
+ public void visit(PackageDeclaration n, LocalSymbolTable arg) {
+ throw new IllegalStateException(n.getClass().getName());
+ }
+
+ public void visit(NameExpr n, LocalSymbolTable arg) {
+ if ("mappingLangToXmlLang".equals(n.getName())) {
+ printer.print("0");
+ } else if ("LANG_NS".equals(n.getName())) {
+ printer.print("ALL_NO_NS");
+ } else if ("LANG_PREFIX".equals(n.getName())) {
+ printer.print("ALL_NO_PREFIX");
+ } else if ("HTML_LOCAL".equals(n.getName())) {
+ printer.print(cppTypes.localForLiteral("html"));
+ } else if ("documentModeHandler".equals(n.getName())) {
+ printer.print("this");
+ } else if ("errorHandler".equals(n.getName())) {
+ printer.print(cppTypes.errorHandler());
+ } else {
+ String prefixedName = javaClassName + "." + n.getName();
+ String constant = symbolTable.cppDefinesByJavaNames.get(prefixedName);
+ if (constant != null) {
+ printer.print(constant);
+ } else {
+ printer.print(n.getName());
+ }
+ }
+ }
+
+ public void visit(QualifiedNameExpr n, LocalSymbolTable arg) {
+ n.getQualifier().accept(this, arg);
+ printer.print(".");
+ printer.print(n.getName());
+ }
+
+ public void visit(ImportDeclaration n, LocalSymbolTable arg) {
+ throw new IllegalStateException(n.getClass().getName());
+ }
+
+ public void visit(ClassOrInterfaceDeclaration n, LocalSymbolTable arg) {
+ javaClassName = n.getName();
+ className = cppTypes.classPrefix() + javaClassName;
+ definePrefix = makeDefinePrefix(className);
+
+ startClassDeclaration();
+
+ if (n.getMembers() != null) {
+ printMembers(n.getMembers(), arg);
+ }
+
+ endClassDeclaration();
+ }
+
+ private String makeDefinePrefix(String name) {
+ StringBuilder sb = new StringBuilder();
+ boolean prevWasLowerCase = true;
+ for (int i = 0; i < name.length(); i++) {
+ char c = name.charAt(i);
+ if (c >= 'a' && c <= 'z') {
+ sb.append((char) (c - 0x20));
+ prevWasLowerCase = true;
+ } else if (c >= 'A' && c <= 'Z') {
+ if (prevWasLowerCase) {
+ sb.append('_');
+ }
+ sb.append(c);
+ prevWasLowerCase = false;
+ } else if (c >= '0' && c <= '9') {
+ sb.append(c);
+ prevWasLowerCase = false;
+ }
+ }
+ sb.append('_');
+ return sb.toString();
+ }
+
+ protected void endClassDeclaration() {
+ printer.printLn("void");
+ printer.print(className);
+ printer.printLn("::initializeStatics()");
+ printer.printLn("{");
+ printer.print(staticInitializerPrinter.getSource());
+ printer.printLn("}");
+ printer.printLn();
+
+ printer.printLn("void");
+ printer.print(className);
+ printer.printLn("::releaseStatics()");
+ printer.printLn("{");
+ printer.indent();
+ for (String del : staticReleases) {
+ printer.print(del);
+ printer.printLn(";");
+ }
+ printer.unindent();
+ printer.printLn("}");
+ printer.printLn();
+
+ if (cppTypes.hasSupplement(javaClassName)) {
+ printer.printLn();
+ printer.print("#include \"");
+ printer.print(className);
+ printer.printLn("CppSupplement.h\"");
+ }
+ }
+
+ protected void startClassDeclaration() {
+ printer.print("#define ");
+ printer.print(className);
+ printer.printLn("_cpp__");
+ printer.printLn();
+
+ String[] incs = cppTypes.boilerplateIncludes(javaClassName);
+ for (int i = 0; i < incs.length; i++) {
+ String inc = incs[i];
+ printer.print("#include \"");
+ printer.print(inc);
+ printer.printLn(".h\"");
+ }
+
+ printer.printLn();
+
+ for (int i = 0; i < Main.H_LIST.length; i++) {
+ String klazz = Main.H_LIST[i];
+ if (!klazz.equals(javaClassName)) {
+ printer.print("#include \"");
+ printer.print(cppTypes.classPrefix());
+ printer.print(klazz);
+ printer.printLn(".h\"");
+ }
+ }
+
+ printer.printLn();
+ printer.print("#include \"");
+ printer.print(className);
+ printer.printLn(".h\"");
+ if ("AttributeName".equals(javaClassName)
+ || "ElementName".equals(javaClassName)) {
+ printer.print("#include \"");
+ printer.print(cppTypes.classPrefix());
+ printer.print("Releasable");
+ printer.print(javaClassName);
+ printer.printLn(".h\"");
+ }
+ printer.printLn();
+ }
+
+ public void visit(EmptyTypeDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(JavadocComment n, LocalSymbolTable arg) {
+ printer.print("/**");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+ public void visit(ClassOrInterfaceType n, LocalSymbolTable arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ throw new IllegalStateException("Can't translate nested classes.");
+ }
+ String name = n.getName();
+ if ("String".equals(name)) {
+ if (local()) {
+ name = cppTypes.localType();
+ } else if (prefix()) {
+ name = cppTypes.prefixType();
+ } else if (nsUri()) {
+ name = cppTypes.nsUriType();
+ } else if (literal()) {
+ name = cppTypes.literalType();
+ } else if (characterName()) {
+ name = cppTypes.characterNameType();
+ } else {
+ name = cppTypes.stringType();
+ }
+ } else if ("T".equals(name) || "Object".equals(name)) {
+ name = cppTypes.nodeType();
+ } else if ("TokenHandler".equals(name)) {
+ name = cppTypes.classPrefix() + "TreeBuilder*";
+ } else if ("EncodingDeclarationHandler".equals(name)) {
+ name = cppTypes.encodingDeclarationHandlerType();
+ } else if ("Interner".equals(name)) {
+ name = cppTypes.internerType();
+ } else if ("TreeBuilderState".equals(name)) {
+ name = cppTypes.treeBuilderStateType();
+ } else if ("DocumentModeHandler".equals(name)) {
+ name = cppTypes.documentModeHandlerType();
+ } else if ("DocumentMode".equals(name)) {
+ name = cppTypes.documentModeType();
+ } else {
+ name = cppTypes.classPrefix() + name + (suppressPointer ? "" : "*");
+ }
+ printer.print(name);
+ printTypeArgs(n.getTypeArgs(), arg);
+ }
+
+ protected boolean inHeader() {
+ return false;
+ }
+
+ public void visit(TypeParameter n, LocalSymbolTable arg) {
+ printer.print(n.getName());
+ if (n.getTypeBound() != null) {
+ printer.print(" extends ");
+ for (Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(" & ");
+ }
+ }
+ }
+ }
+
+ public void visit(PrimitiveType n, LocalSymbolTable arg) {
+ switch (n.getType()) {
+ case Boolean:
+ printer.print(cppTypes.booleanType());
+ break;
+ case Byte:
+ printer.print(cppTypes.byteType());
+ break;
+ case Char:
+ printer.print(cppTypes.charType());
+ break;
+ case Double:
+ throw new IllegalStateException("Unsupported primitive.");
+ case Float:
+ throw new IllegalStateException("Unsupported primitive.");
+ case Int:
+ printer.print(cppTypes.intType());
+ break;
+ case Long:
+ throw new IllegalStateException("Unsupported primitive.");
+ case Short:
+ throw new IllegalStateException("Unsupported primitive.");
+ }
+ }
+
+ public void visit(ReferenceType n, LocalSymbolTable arg) {
+ if (isConst()) {
+ printer.print("const ");
+ }
+ if (noLength()) {
+ n.getType().accept(this, arg);
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ if (!inPrimitiveNoLengthFieldDeclarator) {
+ printer.print("*");
+ }
+ }
+ } else {
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ if (inStatic) {
+ printer.print(cppTypes.staticArrayTemplate());
+ } else {
+ if (auto()) {
+ printer.print(cppTypes.autoArrayTemplate());
+ } else {
+ printer.print(cppTypes.arrayTemplate());
+ }
+ }
+ printer.print("<");
+ }
+ n.getType().accept(this, arg);
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print(",");
+ printer.print(cppTypes.intType());
+ printer.print(">");
+ }
+ }
+ }
+
+ public void visit(WildcardType n, LocalSymbolTable arg) {
+ printer.print("?");
+ if (n.getExtends() != null) {
+ printer.print(" extends ");
+ n.getExtends().accept(this, arg);
+ }
+ if (n.getSuper() != null) {
+ printer.print(" super ");
+ n.getSuper().accept(this, arg);
+ }
+ }
+
+ public void visit(FieldDeclaration n, LocalSymbolTable arg) {
+ currentAnnotations = n.getAnnotations();
+ fieldDeclaration(n, arg);
+ currentAnnotations = null;
+ }
+
+ protected boolean isNonToCharArrayMethodCall(Expression exp) {
+ if (exp instanceof MethodCallExpr) {
+ MethodCallExpr mce = (MethodCallExpr) exp;
+ return !"toCharArray".equals(mce.getName());
+ } else {
+ return false;
+ }
+ }
+
+ protected void fieldDeclaration(FieldDeclaration n, LocalSymbolTable arg) {
+ tempPrinterHolder = printer;
+ printer = staticInitializerPrinter;
+ int modifiers = n.getModifiers();
+ List<VariableDeclarator> variables = n.getVariables();
+ VariableDeclarator declarator = variables.get(0);
+ if (ModifierSet.isStatic(modifiers) && ModifierSet.isFinal(modifiers)
+ && !(n.getType() instanceof PrimitiveType)
+ && declarator.getInit() != null) {
+ if (n.getType() instanceof ReferenceType) {
+ ReferenceType rt = (ReferenceType) n.getType();
+ currentArrayCount = rt.getArrayCount();
+ if (currentArrayCount > 0) {
+ if (currentArrayCount != 1) {
+ throw new IllegalStateException(
+ "Multidimensional arrays not supported. " + n);
+ }
+ if (noLength()) {
+ if (rt.getType() instanceof PrimitiveType) {
+ inPrimitiveNoLengthFieldDeclarator = true;
+ printer = tempPrinterHolder;
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(className);
+ printer.print("::");
+ declarator.getId().accept(this, arg);
+
+ printer.print(" = ");
+
+ declarator.getInit().accept(this, arg);
+
+ printer.printLn(";");
+ printer = staticInitializerPrinter;
+ } else {
+ printer = tempPrinterHolder;
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(className);
+ printer.print("::");
+ declarator.getId().accept(this, arg);
+
+ printer.printLn(" = 0;");
+ printer = staticInitializerPrinter;
+
+ staticReleases.add("delete[] "
+ + declarator.getId().getName());
+
+ ArrayInitializerExpr aie = (ArrayInitializerExpr) declarator.getInit();
+
+ declarator.getId().accept(this, arg);
+ printer.print(" = new ");
+ // suppressPointer = true;
+ rt.getType().accept(this, arg);
+ // suppressPointer = false;
+ printer.print("[");
+ printer.print("" + aie.getValues().size());
+ printer.printLn("];");
+
+ printArrayInit(declarator.getId(), aie.getValues(),
+ arg);
+ }
+ } else if ((rt.getType() instanceof PrimitiveType) || "String".equals(rt.getType().toString())) {
+ printer = tempPrinterHolder;
+ printer.print("static ");
+ rt.getType().accept(this, arg);
+ printer.print(" const ");
+ declarator.getId().accept(this, arg);
+ printer.print("_DATA[] = ");
+ declarator.getInit().accept(this, arg);
+ printer.printLn(";");
+ printer.print(cppTypes.staticArrayTemplate());
+ printer.print("<");
+ suppressPointer = true;
+ rt.getType().accept(this, arg);
+ suppressPointer = false;
+ printer.print(",");
+ printer.print(cppTypes.intType());
+ printer.print("> ");
+ printer.print(className);
+ printer.print("::");
+ declarator.getId().accept(this, arg);
+ printer.print(" = { ");
+ declarator.getId().accept(this, arg);
+ printer.print("_DATA, ");
+ printer.print(cppTypes.arrayLengthMacro());
+ printer.print("(");
+ declarator.getId().accept(this, arg);
+ printer.printLn("_DATA) };");
+ printer = staticInitializerPrinter;
+ } else if (isNonToCharArrayMethodCall(declarator.getInit())) {
+ staticReleases.add(declarator.getId().getName()
+ + ".release()");
+ declarator.getId().accept(this, arg);
+ printer.print(" = ");
+ if (declarator.getInit() instanceof ArrayInitializerExpr) {
+
+ ArrayInitializerExpr aie = (ArrayInitializerExpr) declarator.getInit();
+ printer.print(cppTypes.arrayTemplate());
+ printer.print("<");
+ suppressPointer = true;
+ rt.getType().accept(this, arg);
+ suppressPointer = false;
+ printer.print(",");
+ printer.print(cppTypes.intType());
+ printer.print(">::");
+ printer.print(cppTypes.newArrayCreator());
+ printer.print("(");
+ printer.print("" + aie.getValues().size());
+ printer.printLn(");");
+ printArrayInit(declarator.getId(), aie.getValues(),
+ arg);
+ } else {
+ declarator.getInit().accept(this, arg);
+ printer.printLn(";");
+ }
+ }
+ } else {
+ if (ModifierSet.isStatic(modifiers)) {
+ printer = tempPrinterHolder;
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(className);
+ printer.print("::");
+ if ("AttributeName".equals(n.getType().toString())) {
+ printer.print("ATTR_");
+ } else if ("ElementName".equals(n.getType().toString())) {
+ printer.print("ELT_");
+ }
+ declarator.getId().accept(this, arg);
+ printer.print(" = ");
+ printer.print(cppTypes.nullLiteral());
+ printer.printLn(";");
+ printer = staticInitializerPrinter;
+ }
+
+ if ("AttributeName".equals(n.getType().toString())) {
+ printer.print("ATTR_");
+ staticReleases.add("delete ATTR_"
+ + declarator.getId().getName());
+ } else if ("ElementName".equals(n.getType().toString())) {
+ printer.print("ELT_");
+ staticReleases.add("delete ELT_"
+ + declarator.getId().getName());
+ } else {
+ staticReleases.add("delete "
+ + declarator.getId().getName());
+ }
+ declarator.accept(this, arg);
+ printer.printLn(";");
+ }
+ } else {
+ throw new IllegalStateException(
+ "Non-reference, non-primitive fields not supported.");
+ }
+ }
+ currentArrayCount = 0;
+ printer = tempPrinterHolder;
+ inPrimitiveNoLengthFieldDeclarator = false;
+ }
+
+ private void printArrayInit(VariableDeclaratorId variableDeclaratorId,
+ List<Expression> values, LocalSymbolTable arg) {
+ for (int i = 0; i < values.size(); i++) {
+ Expression exp = values.get(i);
+ variableDeclaratorId.accept(this, arg);
+ printer.print("[");
+ printer.print("" + i);
+ printer.print("] = ");
+ if (exp instanceof NameExpr) {
+ if ("AttributeName".equals(javaClassName)) {
+ printer.print("ATTR_");
+ } else if ("ElementName".equals(javaClassName)) {
+ printer.print("ELT_");
+ }
+ }
+ exp.accept(this, arg);
+ printer.printLn(";");
+ }
+ }
+
+ public void visit(VariableDeclarator n, LocalSymbolTable arg) {
+ n.getId().accept(this, arg);
+
+ if (n.getInit() != null) {
+ printer.print(" = ");
+ n.getInit().accept(this, arg);
+ }
+ }
+
+ public void visit(VariableDeclaratorId n, LocalSymbolTable arg) {
+ printer.print(n.getName());
+ if (noLength()) {
+ for (int i = 0; i < currentArrayCount; i++) {
+ if (inPrimitiveNoLengthFieldDeclarator) {
+ printer.print("[]");
+ }
+ }
+ }
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ }
+
+ public void visit(ArrayInitializerExpr n, LocalSymbolTable arg) {
+ printer.print("{");
+ if (n.getValues() != null) {
+ printer.print(" ");
+ for (Iterator<Expression> i = n.getValues().iterator(); i.hasNext();) {
+ Expression expr = i.next();
+ expr.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(" ");
+ }
+ printer.print("}");
+ }
+
+ public void visit(VoidType n, LocalSymbolTable arg) {
+ printer.print("void");
+ }
+
+ public void visit(ArrayAccessExpr n, LocalSymbolTable arg) {
+ n.getName().accept(this, arg);
+ printer.print("[");
+ n.getIndex().accept(this, arg);
+ printer.print("]");
+ }
+
+ public void visit(ArrayCreationExpr n, LocalSymbolTable arg) {
+ // printer.print("new ");
+ // n.getType().accept(this, arg);
+ // printTypeArgs(n.getTypeArgs(), arg);
+
+ if (n.getDimensions() != null) {
+ if (noLength()) {
+ for (Expression dim : n.getDimensions()) {
+ printer.print("new ");
+ n.getType().accept(this, arg);
+ printer.print("[");
+ dim.accept(this, arg);
+ printer.print("]");
+ }
+ } else {
+ for (Expression dim : n.getDimensions()) {
+ printer.print(cppTypes.arrayTemplate());
+ printer.print("<");
+ n.getType().accept(this, arg);
+ printer.print(",");
+ printer.print(cppTypes.intType());
+ printer.print(">::");
+ printer.print(cppTypes.newArrayCreator());
+ printer.print("(");
+ dim.accept(this, arg);
+ printer.print(")");
+ }
+ }
+ if (n.getArrayCount() > 0) {
+ throw new IllegalStateException(
+ "Nested array allocation not supported. "
+ + n.toString());
+ }
+ } else {
+ throw new IllegalStateException(
+ "Array initializer as part of array creation not supported. "
+ + n.toString());
+ }
+ }
+
+ public void visit(AssignExpr n, LocalSymbolTable arg) {
+ if (inConstructorBody) {
+ n.getTarget().accept(this, arg);
+ printer.print("(");
+ n.getValue().accept(this, arg);
+ printer.print(")");
+ } else {
+ n.getTarget().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case assign:
+ printer.print("=");
+ break;
+ case and:
+ printer.print("&=");
+ break;
+ case or:
+ printer.print("|=");
+ break;
+ case xor:
+ printer.print("^=");
+ break;
+ case plus:
+ printer.print("+=");
+ break;
+ case minus:
+ printer.print("-=");
+ break;
+ case rem:
+ printer.print("%=");
+ break;
+ case slash:
+ printer.print("/=");
+ break;
+ case star:
+ printer.print("*=");
+ break;
+ case lShift:
+ printer.print("<<=");
+ break;
+ case rSignedShift:
+ printer.print(">>=");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>=");
+ break;
+ }
+ printer.print(" ");
+ n.getValue().accept(this, arg);
+ }
+ }
+
+ public void visit(BinaryExpr n, LocalSymbolTable arg) {
+ Expression right = n.getRight();
+ switch (n.getOperator()) {
+ case notEquals:
+ if (right instanceof NullLiteralExpr) {
+ printer.print("!!");
+ n.getLeft().accept(this, arg);
+ return;
+ } else if (right instanceof IntegerLiteralExpr) {
+ IntegerLiteralExpr ile = (IntegerLiteralExpr) right;
+ if ("0".equals(ile.getValue())) {
+ n.getLeft().accept(this, arg);
+ return;
+ }
+ }
+ case equals:
+ if (right instanceof NullLiteralExpr) {
+ printer.print("!");
+ n.getLeft().accept(this, arg);
+ return;
+ } else if (right instanceof IntegerLiteralExpr) {
+ IntegerLiteralExpr ile = (IntegerLiteralExpr) right;
+ if ("0".equals(ile.getValue())) {
+ printer.print("!");
+ n.getLeft().accept(this, arg);
+ return;
+ }
+ }
+ default:
+ // fall thru
+ }
+
+ n.getLeft().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case or:
+ printer.print("||");
+ break;
+ case and:
+ printer.print("&&");
+ break;
+ case binOr:
+ printer.print("|");
+ break;
+ case binAnd:
+ printer.print("&");
+ break;
+ case xor:
+ printer.print("^");
+ break;
+ case equals:
+ printer.print("==");
+ break;
+ case notEquals:
+ printer.print("!=");
+ break;
+ case less:
+ printer.print("<");
+ break;
+ case greater:
+ printer.print(">");
+ break;
+ case lessEquals:
+ printer.print("<=");
+ break;
+ case greaterEquals:
+ printer.print(">=");
+ break;
+ case lShift:
+ printer.print("<<");
+ break;
+ case rSignedShift:
+ printer.print(">>");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>");
+ break;
+ case plus:
+ printer.print("+");
+ break;
+ case minus:
+ printer.print("-");
+ break;
+ case times:
+ printer.print("*");
+ break;
+ case divide:
+ printer.print("/");
+ break;
+ case remainder:
+ printer.print("%");
+ break;
+ }
+ printer.print(" ");
+ n.getRight().accept(this, arg);
+ }
+
+ public void visit(CastExpr n, LocalSymbolTable arg) {
+ printer.print("(");
+ n.getType().accept(this, arg);
+ printer.print(") ");
+ n.getExpr().accept(this, arg);
+ }
+
+ public void visit(ClassExpr n, LocalSymbolTable arg) {
+ n.getType().accept(this, arg);
+ printer.print(".class");
+ }
+
+ public void visit(ConditionalExpr n, LocalSymbolTable arg) {
+ n.getCondition().accept(this, arg);
+ printer.print(" ? ");
+ n.getThenExpr().accept(this, arg);
+ printer.print(" : ");
+ n.getElseExpr().accept(this, arg);
+ }
+
+ public void visit(EnclosedExpr n, LocalSymbolTable arg) {
+ printer.print("(");
+ n.getInner().accept(this, arg);
+ printer.print(")");
+ }
+
+ public void visit(FieldAccessExpr n, LocalSymbolTable arg) {
+ Expression scope = n.getScope();
+ String field = n.getField();
+ if (inConstructorBody && (scope instanceof ThisExpr)) {
+ printer.print(field);
+ } else if ("length".equals(field) && !(scope instanceof ThisExpr)) {
+ scope.accept(this, arg);
+ printer.print(".length");
+ } else if ("MAX_VALUE".equals(field)
+ && "Integer".equals(scope.toString())) {
+ printer.print(cppTypes.maxInteger());
+ } else {
+ String clazzName = classNameFromExpression(scope);
+ if (clazzName == null) {
+ if ("DocumentMode".equals(scope.toString())) {
+ // printer.print(cppTypes.documentModeType());
+ // printer.print(".");
+ } else {
+ scope.accept(this, arg);
+ printer.print("->");
+ }
+ } else {
+ String prefixedName = clazzName + "." + field;
+ String constant = symbolTable.cppDefinesByJavaNames.get(prefixedName);
+ if (constant != null) {
+ printer.print(constant);
+ return;
+ } else {
+ printer.print(cppTypes.classPrefix());
+ printer.print(clazzName);
+ printer.print("::");
+ if (symbolTable.isNotAnAttributeOrElementName(field)) {
+ if ("AttributeName".equals(clazzName)) {
+ printer.print("ATTR_");
+ } else if ("ElementName".equals(clazzName)) {
+ printer.print("ELT_");
+ }
+ }
+ }
+ }
+ printer.print(field);
+ }
+ }
+
+ public void visit(InstanceOfExpr n, LocalSymbolTable arg) {
+ n.getExpr().accept(this, arg);
+ printer.print(" instanceof ");
+ n.getType().accept(this, arg);
+ }
+
+ public void visit(CharLiteralExpr n, LocalSymbolTable arg) {
+ printCharLiteral(n.getValue());
+ }
+
+ private void printCharLiteral(String val) {
+ if (val.length() != 1) {
+ printer.print("'");
+ printer.print(val);
+ printer.print("'");
+ return;
+ }
+ char c = val.charAt(0);
+ switch (c) {
+ case 0:
+ printer.print("'\\0'");
+ break;
+ case '\n':
+ printer.print("'\\n'");
+ break;
+ case '\t':
+ printer.print("'\\t'");
+ break;
+ case 0xB:
+ printer.print("'\\v'");
+ break;
+ case '\b':
+ printer.print("'\\b'");
+ break;
+ case '\r':
+ printer.print("'\\r'");
+ break;
+ case 0xC:
+ printer.print("'\\f'");
+ break;
+ case 0x7:
+ printer.print("'\\a'");
+ break;
+ case '\\':
+ printer.print("'\\\\'");
+ break;
+ case '?':
+ printer.print("'\\?'");
+ break;
+ case '\'':
+ printer.print("'\\''");
+ break;
+ case '"':
+ printer.print("'\\\"'");
+ break;
+ default:
+ if (c >= 0x20 && c <= 0x7F) {
+ printer.print("'" + c);
+ printer.print("'");
+ } else {
+ printer.print("0x");
+ printer.print(Integer.toHexString(c));
+ }
+ break;
+ }
+ }
+
+ public void visit(DoubleLiteralExpr n, LocalSymbolTable arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralExpr n, LocalSymbolTable arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralExpr n, LocalSymbolTable arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralMinValueExpr n, LocalSymbolTable arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralMinValueExpr n, LocalSymbolTable arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(StringLiteralExpr n, LocalSymbolTable arg) {
+ String val = n.getValue();
+ if ("http://www.w3.org/1999/xhtml".equals(val)) {
+ printer.print(cppTypes.xhtmlNamespaceLiteral());
+ } else if ("http://www.w3.org/2000/svg".equals(val)) {
+ printer.print(cppTypes.svgNamespaceLiteral());
+ } else if ("http://www.w3.org/2000/xmlns/".equals(val)) {
+ printer.print(cppTypes.xmlnsNamespaceLiteral());
+ } else if ("http://www.w3.org/XML/1998/namespace".equals(val)) {
+ printer.print(cppTypes.xmlNamespaceLiteral());
+ } else if ("http://www.w3.org/1999/xlink".equals(val)) {
+ printer.print(cppTypes.xlinkNamespaceLiteral());
+ } else if ("http://www.w3.org/1998/Math/MathML".equals(val)) {
+ printer.print(cppTypes.mathmlNamespaceLiteral());
+ } else if ("".equals(val) && "AttributeName".equals(javaClassName)) {
+ printer.print(cppTypes.noNamespaceLiteral());
+ } else if (val.startsWith("-/") || val.startsWith("+//")
+ || val.startsWith("http://") || val.startsWith("XSLT")) {
+ printer.print(cppTypes.stringForLiteral(val));
+ } else if (("hidden".equals(val) || "isindex".equals(val)
+ || "text/html".equals(val)
+ || "application/xhtml+xml".equals(val) || "content-type".equals(val))
+ && "TreeBuilder".equals(javaClassName)) {
+ printer.print(cppTypes.stringForLiteral(val));
+ } else if ("isQuirky".equals(currentMethod) && "html".equals(val)) {
+ printer.print(cppTypes.stringForLiteral(val));
+ } else {
+ printer.print(cppTypes.localForLiteral(val));
+ }
+ }
+
+ public void visit(BooleanLiteralExpr n, LocalSymbolTable arg) {
+ if (n.getValue()) {
+ printer.print(cppTypes.trueLiteral());
+ } else {
+ printer.print(cppTypes.falseLiteral());
+ }
+ }
+
+ public void visit(NullLiteralExpr n, LocalSymbolTable arg) {
+ printer.print(cppTypes.nullLiteral());
+ }
+
+ public void visit(ThisExpr n, LocalSymbolTable arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("this");
+ }
+
+ public void visit(SuperExpr n, LocalSymbolTable arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("super");
+ }
+
+ public void visit(MethodCallExpr n, LocalSymbolTable arg) {
+ if ("releaseArray".equals(n.getName())
+ && "Portability".equals(n.getScope().toString())) {
+ n.getArgs().get(0).accept(this, arg);
+ printer.print(".release()");
+ } else if ("deleteArray".equals(n.getName())
+ && "Portability".equals(n.getScope().toString())) {
+ printer.print("delete[] ");
+ n.getArgs().get(0).accept(this, arg);
+ } else if ("delete".equals(n.getName())
+ && "Portability".equals(n.getScope().toString())) {
+ printer.print("delete ");
+ n.getArgs().get(0).accept(this, arg);
+ } else if (("retainElement".equals(n.getName()) || "releaseElement".equals(n.getName()))
+ && "Portability".equals(n.getScope().toString())) {
+ // ignore for now
+ } else if ("transition".equals(n.getName())
+ && n.getScope() == null) {
+ visitTransition(n, arg);
+ } else if ("arraycopy".equals(n.getName())
+ && "System".equals(n.getScope().toString())) {
+ printer.print(cppTypes.arrayCopy());
+ printer.print("(");
+ if (n.getArgs().get(0).toString().equals(
+ n.getArgs().get(2).toString())) {
+ n.getArgs().get(0).accept(this, arg);
+ printer.print(", ");
+ n.getArgs().get(1).accept(this, arg);
+ printer.print(", ");
+ n.getArgs().get(3).accept(this, arg);
+ printer.print(", ");
+ n.getArgs().get(4).accept(this, arg);
+ } else if (n.getArgs().get(1).toString().equals("0")
+ && n.getArgs().get(3).toString().equals("0")) {
+ n.getArgs().get(0).accept(this, arg);
+ printer.print(", ");
+ n.getArgs().get(2).accept(this, arg);
+ printer.print(", ");
+ n.getArgs().get(4).accept(this, arg);
+ } else {
+ for (Iterator<Expression> i = n.getArgs().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ } else if ("binarySearch".equals(n.getName())
+ && "Arrays".equals(n.getScope().toString())) {
+ n.getArgs().get(0).accept(this, arg);
+ printer.print(".binarySearch(");
+ n.getArgs().get(1).accept(this, arg);
+ printer.print(")");
+ } else {
+ Expression scope = n.getScope();
+ if (scope != null) {
+ if (scope instanceof StringLiteralExpr) {
+ StringLiteralExpr strLit = (StringLiteralExpr) scope;
+ String str = strLit.getValue();
+ if (!"toCharArray".equals(n.getName())) {
+ throw new IllegalStateException(
+ "Unsupported method call on string literal: "
+ + n.getName());
+ }
+ printer.print("{ ");
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (i != 0) {
+ printer.print(", ");
+ }
+ printCharLiteral("" + c);
+ }
+ printer.print(" }");
+ return;
+ } else {
+ String clazzName = classNameFromExpression(scope);
+ if (clazzName == null) {
+ scope.accept(this, arg);
+ if ("length".equals(n.getName())
+ || "charAt".equals(n.getName())) {
+ printer.print(".");
+ } else {
+ printer.print("->");
+ }
+ } else {
+ printer.print(cppTypes.classPrefix());
+ printer.print(clazzName);
+ printer.print("::");
+ }
+ }
+ }
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print(n.getName());
+ if ("stateLoop".equals(n.getName())
+ && "Tokenizer".equals(javaClassName)
+ && cppTypes.stateLoopPolicies().length > 0) {
+ printer.print("<");
+ printer.print(cppTypes.stateLoopPolicies()[stateLoopCallCount]);
+ printer.print(">");
+ stateLoopCallCount++;
+ }
+ printer.print("(");
+ if (n.getArgs() != null) {
+ for (Iterator<Expression> i = n.getArgs().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ }
+ }
+
+ public void visit(ObjectCreationExpr n, LocalSymbolTable arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+
+ printer.print("new ");
+
+ suppressPointer = true;
+ printTypeArgs(n.getTypeArgs(), arg);
+ if ("createAttributeName".equals(currentMethod)
+ || "elementNameByBuffer".equals(currentMethod)) {
+ printer.print(cppTypes.classPrefix());
+ printer.print("Releasable");
+ printer.print(n.getType().getName());
+ } else {
+ n.getType().accept(this, arg);
+ }
+ suppressPointer = false;
+
+ if ("AttributeName".equals(n.getType().getName())) {
+ List<Expression> args = n.getArgs();
+ while (args.size() > 3) {
+ args.remove(3);
+ }
+ }
+
+ printer.print("(");
+ if (n.getArgs() != null) {
+ for (Iterator<Expression> i = n.getArgs().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ if (n.getAnonymousClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMembers(n.getAnonymousClassBody(), arg);
+ printer.unindent();
+ printer.print("}");
+ }
+ }
+
+ public void visit(UnaryExpr n, LocalSymbolTable arg) {
+ switch (n.getOperator()) {
+ case positive:
+ printer.print("+");
+ break;
+ case negative:
+ printer.print("-");
+ break;
+ case inverse:
+ printer.print("~");
+ break;
+ case not:
+ printer.print("!");
+ break;
+ case preIncrement:
+ printer.print("++");
+ break;
+ case preDecrement:
+ printer.print("--");
+ break;
+ }
+
+ n.getExpr().accept(this, arg);
+
+ switch (n.getOperator()) {
+ case posIncrement:
+ printer.print("++");
+ break;
+ case posDecrement:
+ printer.print("--");
+ break;
+ }
+ }
+
+ public void visit(ConstructorDeclaration n, LocalSymbolTable arg) {
+ if ("TreeBuilder".equals(javaClassName)) {
+ return;
+ }
+
+ arg = new LocalSymbolTable(javaClassName, symbolTable);
+
+ // if (n.getJavaDoc() != null) {
+ // n.getJavaDoc().accept(this, arg);
+ // }
+ currentAnnotations = n.getAnnotations();
+
+ printModifiers(n.getModifiers());
+
+ printMethodNamespace();
+ printConstructorExplicit(n.getParameters());
+ printer.print(className);
+ currentAnnotations = null;
+
+ printer.print("(");
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ printConstructorBody(n.getBlock(), arg);
+ }
+
+ protected void printConstructorExplicit(List<Parameter> params) {
+ }
+
+ protected void printConstructorBody(BlockStmt block, LocalSymbolTable arg) {
+ inConstructorBody = true;
+ List<Statement> statements = block.getStmts();
+ List<Statement> nonAssigns = new LinkedList<Statement>();
+ int i = 0;
+ boolean needOutdent = false;
+ for (Statement statement : statements) {
+ if (statement instanceof ExpressionStmt
+ && ((ExpressionStmt) statement).getExpression() instanceof AssignExpr) {
+ if (i == 0) {
+ printer.printLn();
+ printer.indent();
+ printer.print(": ");
+ needOutdent = true;
+ } else {
+ printer.print(",");
+ printer.printLn();
+ printer.print(" ");
+ }
+ statement.accept(this, arg);
+ i++;
+ } else {
+ nonAssigns.add(statement);
+ }
+ }
+ if (needOutdent) {
+ printer.unindent();
+ }
+ inConstructorBody = false;
+ printer.printLn();
+ printer.printLn("{");
+ printer.indent();
+ String boilerplate = cppTypes.constructorBoilerplate(className);
+ if (boilerplate != null) {
+ printer.printLn(boilerplate);
+ }
+ for (Statement statement : nonAssigns) {
+ statement.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ printer.printLn("}");
+ printer.printLn();
+ }
+
+ public void visit(MethodDeclaration n, LocalSymbolTable arg) {
+ arg = new LocalSymbolTable(javaClassName, symbolTable);
+ if (isPrintableMethod(n.getModifiers())
+ && !(n.getName().equals("endCoalescing") || n.getName().equals(
+ "startCoalescing"))) {
+ printMethodDeclaration(n, arg);
+ }
+ }
+
+ private boolean isPrintableMethod(int modifiers) {
+ return !(ModifierSet.isAbstract(modifiers) || (ModifierSet.isProtected(modifiers) && !(ModifierSet.isFinal(modifiers) || "Tokenizer".equals(javaClassName))));
+ }
+
+ protected void printMethodDeclaration(MethodDeclaration n,
+ LocalSymbolTable arg) {
+ if (n.getName().startsWith("fatal") || n.getName().startsWith("err")
+ || n.getName().startsWith("warn")
+ || n.getName().startsWith("maybeErr")
+ || n.getName().startsWith("maybeWarn")
+ || n.getName().startsWith("note")
+ || "releaseArray".equals(n.getName())
+ || "deleteArray".equals(n.getName())
+ || "delete".equals(n.getName())) {
+ return;
+ }
+
+ currentMethod = n.getName();
+
+ destructor = "destructor".equals(currentMethod);
+
+ // if (n.getJavaDoc() != null) {
+ // n.getJavaDoc().accept(this, arg);
+ // }
+ currentAnnotations = n.getAnnotations();
+ boolean isInline = inline();
+ if (isInline && !inHeader()) {
+ return;
+ }
+
+ if (destructor) {
+ printModifiers(ModifierSet.PUBLIC);
+ } else {
+ printModifiers(n.getModifiers());
+ }
+
+ if ("stateLoop".equals(currentMethod)
+ && "Tokenizer".equals(javaClassName)
+ && cppTypes.stateLoopPolicies().length > 0) {
+ printer.print("template<class P>");
+ if (inHeader()) {
+ printer.print(" ");
+ } else {
+ printer.printLn();
+ }
+ }
+
+ printTypeParameters(n.getTypeParameters(), arg);
+ if (n.getTypeParameters() != null) {
+ printer.print(" ");
+ }
+ if (!destructor) {
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ }
+ printMethodNamespace();
+ if (destructor) {
+ printer.print("~");
+ printer.print(className);
+ } else {
+ printer.print(n.getName());
+ }
+
+ currentAnnotations = null;
+ printer.print("(");
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+
+ if (inHeader() == isInline) {
+ printMethodBody(n.getBody(), arg);
+ } else {
+ printer.printLn(";");
+ }
+ }
+
+ private void printMethodBody(BlockStmt n, LocalSymbolTable arg) {
+ if (n == null) {
+ printer.print(";");
+ } else {
+ printer.printLn();
+ printer.printLn("{");
+ printer.indent();
+ if (destructor) {
+ String boilerplate = cppTypes.destructorBoilderplate(className);
+ if (boilerplate != null) {
+ printer.printLn(boilerplate);
+ }
+ }
+ if (n.getStmts() != null) {
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+ printer.printLn();
+ printer.printLn();
+ }
+
+ protected void printMethodNamespace() {
+ printer.printLn();
+ printer.print(className);
+ printer.print("::");
+ }
+
+ public void visit(Parameter n, LocalSymbolTable arg) {
+ currentAnnotations = n.getAnnotations();
+
+ arg.putLocalType(n.getId().getName(), convertType(n.getType(),
+ n.getModifiers()));
+
+ n.getType().accept(this, arg);
+ if (n.isVarArgs()) {
+ printer.print("...");
+ }
+ printer.print(" ");
+ n.getId().accept(this, arg);
+ currentAnnotations = null;
+ }
+
+ public void visit(ExplicitConstructorInvocationStmt n, LocalSymbolTable arg) {
+ if (n.isThis()) {
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print("this");
+ } else {
+ if (n.getExpr() != null) {
+ n.getExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print("super");
+ }
+ printer.print("(");
+ if (n.getArgs() != null) {
+ for (Iterator<Expression> i = n.getArgs().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(");");
+ }
+
+ public void visit(VariableDeclarationExpr n, LocalSymbolTable arg) {
+ currentAnnotations = n.getAnnotations();
+
+ arg.putLocalType(n.getVars().get(0).toString(), convertType(
+ n.getType(), n.getModifiers()));
+
+ n.getType().accept(this, arg);
+ printer.print(" ");
+
+ for (Iterator<VariableDeclarator> i = n.getVars().iterator(); i.hasNext();) {
+ VariableDeclarator v = i.next();
+ v.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ currentAnnotations = null;
+ }
+
+ public void visit(TypeDeclarationStmt n, LocalSymbolTable arg) {
+ n.getTypeDeclaration().accept(this, arg);
+ }
+
+ public void visit(AssertStmt n, LocalSymbolTable arg) {
+ String message = null;
+ Expression msg = n.getMessage();
+ boolean hasCheck = true;
+ if (msg != null) {
+ if (msg instanceof StringLiteralExpr) {
+ StringLiteralExpr sle = (StringLiteralExpr) msg;
+ message = sle.getValue();
+ } else {
+ throw new RuntimeException("Bad assertion message.");
+ }
+ }
+ String macro = cppTypes.assertionMacro();
+ if (message != null && message.startsWith("RELEASE: ")) {
+ message = message.substring("RELEASE: ".length());
+ macro = cppTypes.releaseAssertionMacro();
+ Expression check = n.getCheck();
+ if (check instanceof BooleanLiteralExpr) {
+ BooleanLiteralExpr expr = (BooleanLiteralExpr) check;
+ if (!expr.getValue()) {
+ hasCheck = false;
+ macro = cppTypes.crashMacro();
+ }
+ }
+ }
+ if (macro != null) {
+ printer.print(macro);
+ printer.print("(");
+ if (hasCheck) {
+ n.getCheck().accept(this, arg);
+ }
+ if (message != null) {
+ if (hasCheck) {
+ printer.print(", ");
+ }
+ printer.print("\"");
+ for (int i = 0; i < message.length(); i++) {
+ char c = message.charAt(i);
+ if (c == '"') {
+ printer.print("\"");
+ } else if (c >= ' ' && c <= '~') {
+ printer.print("" + c);
+ } else {
+ throw new RuntimeException("Bad assertion message string.");
+ }
+ }
+ printer.print("\"");
+ }
+ printer.print(");");
+ }
+ }
+
+ public void visit(BlockStmt n, LocalSymbolTable arg) {
+ printer.printLn("{");
+ if (n.getStmts() != null) {
+ printer.indent();
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+
+ }
+
+ public void visit(LabeledStmt n, LocalSymbolTable arg) {
+ // Only conditionless for loops are needed and supported
+ // Not implementing general Java continue semantics in order
+ // to keep the generated C++ more readable.
+ Statement stmt = n.getStmt();
+ if (stmt instanceof ForStmt) {
+ ForStmt forLoop = (ForStmt) stmt;
+ if (!(forLoop.getInit() == null && forLoop.getCompare() == null && forLoop.getUpdate() == null)) {
+ forLoopsWithCondition.add(n.getLabel());
+ }
+ } else {
+ throw new IllegalStateException(
+ "Only for loop supported as labeled statement. Line: "
+ + n.getBeginLine());
+ }
+ String label = n.getLabel();
+ if (labels.contains(label)) {
+ printer.print(label);
+ printer.print(": ");
+ }
+ stmt.accept(this, arg);
+ printer.printLn();
+ label += "_end";
+ if (labels.contains(label)) {
+ printer.print(label);
+ printer.print(": ;");
+ }
+ }
+
+ public void visit(EmptyStmt n, LocalSymbolTable arg) {
+ printer.print(";");
+ }
+
+ public void visit(ExpressionStmt n, LocalSymbolTable arg) {
+ Expression e = n.getExpression();
+ if (isCompletedCharacterReference(e)) {
+ printer.print(cppTypes.completedCharacterReference());
+ printer.print(";");
+ return;
+ }
+ boolean needsCondition = isTokenizerErrorReportingExpression(e);
+ if (!needsCondition && isDroppedExpression(e)) {
+ return;
+ }
+ if (needsCondition) {
+ printer.print("if (");
+ printer.print(cppTypes.tokenizerErrorCondition());
+ printer.printLn(") {");
+ printer.indent();
+ }
+ e.accept(this, arg);
+ if (!inConstructorBody) {
+ printer.print(";");
+ }
+ if (needsCondition) {
+ printer.printLn();
+ printer.unindent();
+ printer.print("}");
+ }
+ }
+
+ private void visitTransition(MethodCallExpr call, LocalSymbolTable arg) {
+ List<Expression> args = call.getArgs();
+ if (reportTransitions) {
+ printer.print(cppTypes.transition());
+ printer.print("(");
+ printer.print(cppTypes.firstTransitionArg());
+ printer.print(", ");
+ args.get(1).accept(this, arg);
+ printer.print(", ");
+ args.get(2).accept(this, arg);
+ printer.print(", ");
+ args.get(3).accept(this, arg);
+ printer.print(")");
+ } else {
+ args.get(1).accept(this, arg);
+ }
+ }
+
+ private boolean isTokenizerErrorReportingExpression(Expression e) {
+ if (!reportTransitions) {
+ return false;
+ }
+ if (e instanceof MethodCallExpr) {
+ MethodCallExpr methodCallExpr = (MethodCallExpr) e;
+ String name = methodCallExpr.getName();
+ if (supportErrorReporting && !name.startsWith("errHtml4")
+ && ("stateLoop".equals(currentMethod))
+ && (name.startsWith("err") || name.startsWith("maybeErr"))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isCompletedCharacterReference(Expression e) {
+ if (!reportTransitions) {
+ return false;
+ }
+ if (e instanceof MethodCallExpr) {
+ MethodCallExpr methodCallExpr = (MethodCallExpr) e;
+ String name = methodCallExpr.getName();
+ if (name.equals("completedNamedCharacterReference")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isDroppedExpression(Expression e) {
+ if (e instanceof MethodCallExpr) {
+ MethodCallExpr methodCallExpr = (MethodCallExpr) e;
+ String name = methodCallExpr.getName();
+ if (name.startsWith("fatal") || name.startsWith("note")
+ || name.startsWith("errHtml4") || name.startsWith("warn")
+ || name.startsWith("maybeWarn")) {
+ return true;
+ }
+ if (supportErrorReporting
+ && ("stateLoop".equals(currentMethod) && !reportTransitions)
+ && (name.startsWith("err") || name.startsWith("maybeErr"))) {
+ return true;
+ }
+ if (name.equals("completedNamedCharacterReference")
+ && !reportTransitions) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void visit(SwitchStmt n, LocalSymbolTable arg) {
+ printer.print("switch(");
+ n.getSelector().accept(this, arg);
+ printer.printLn(") {");
+ if (n.getEntries() != null) {
+ printer.indent();
+ for (SwitchEntryStmt e : n.getEntries()) {
+ e.accept(this, arg);
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+
+ }
+
+ public void visit(SwitchEntryStmt n, LocalSymbolTable arg) {
+ if (n.getLabel() != null) {
+ boolean isMenuitem = n.getLabel().toString().equals("MENUITEM");
+ if (isMenuitem) {
+ printer.printWithoutIndent("#ifdef ENABLE_VOID_MENUITEM\n");
+ }
+ printer.print("case ");
+ n.getLabel().accept(this, arg);
+ printer.print(":");
+ if (isMenuitem) {
+ printer.printWithoutIndent("\n#endif");
+ }
+ } else {
+ printer.print("default:");
+ }
+ if (isNoStatement(n.getStmts())) {
+ printer.printLn();
+ printer.indent();
+ if (n.getLabel() == null) {
+ printer.printLn("; // fall through");
+ }
+ printer.unindent();
+ } else {
+ printer.printLn(" {");
+ printer.indent();
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ printer.printLn("}");
+ }
+ }
+
+ private boolean isNoStatement(List<Statement> stmts) {
+ if (stmts == null) {
+ return true;
+ }
+ for (Statement statement : stmts) {
+ if (!isDroppableStatement(statement)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isDroppableStatement(Statement statement) {
+ if (statement instanceof AssertStmt) {
+ return true;
+ } else if (statement instanceof ExpressionStmt) {
+ ExpressionStmt es = (ExpressionStmt) statement;
+ if (isDroppedExpression(es.getExpression())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void visit(BreakStmt n, LocalSymbolTable arg) {
+ if (n.getId() != null) {
+ printer.print(cppTypes.breakMacro());
+ printer.print("(");
+ printer.print(n.getId());
+ printer.print(")");
+ } else {
+ printer.print("break");
+ }
+ printer.print(";");
+ }
+
+ public void visit(ReturnStmt n, LocalSymbolTable arg) {
+ printer.print("return");
+ if (n.getExpr() != null) {
+ printer.print(" ");
+ n.getExpr().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(EnumDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ currentAnnotations = n.getAnnotations();
+ // if (annotations != null) {
+ // for (AnnotationExpr a : annotations) {
+ // a.accept(this, arg);
+ // printer.printLn();
+ // }
+ // }
+ printModifiers(n.getModifiers());
+
+ printer.print("enum ");
+ printer.print(n.getName());
+
+ currentAnnotations = null;
+
+ if (n.getImplements() != null) {
+ printer.print(" implements ");
+ for (Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getEntries() != null) {
+ printer.printLn();
+ for (Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext();) {
+ EnumConstantDeclaration e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ if (n.getMembers() != null) {
+ printer.printLn(";");
+ printMembers(n.getMembers(), arg);
+ } else {
+ if (n.getEntries() != null) {
+ printer.printLn();
+ }
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+
+ public void visit(EnumConstantDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ currentAnnotations = n.getAnnotations();
+ // if (annotations != null) {
+ // for (AnnotationExpr a : annotations) {
+ // a.accept(this, arg);
+ // printer.printLn();
+ // }
+ // }
+ printer.print(n.getName());
+
+ currentAnnotations = null;
+
+ if (n.getArgs() != null) {
+ printer.print("(");
+ for (Iterator<Expression> i = n.getArgs().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(")");
+ }
+
+ if (n.getClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMembers(n.getClassBody(), arg);
+ printer.unindent();
+ printer.printLn("}");
+ }
+ }
+
+ public void visit(EmptyMemberDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(InitializerDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ if (n.isStatic()) {
+ printer.print("static ");
+ }
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(IfStmt n, LocalSymbolTable arg) {
+ if (TranslatorUtils.isDocumentModeHandlerNullCheck(n.getCondition())) {
+ Statement then = n.getThenStmt();
+ if (then instanceof BlockStmt) {
+ BlockStmt block = (BlockStmt) then;
+ List<Statement> statements = block.getStmts();
+ if (statements != null && statements.size() == 1) {
+ statements.get(0).accept(this, arg);
+ } else {
+ then.accept(this, arg);
+ }
+ } else {
+ then.accept(this, arg);
+ }
+ } else if (!TranslatorUtils.isErrorHandlerIf(n.getCondition(), supportErrorReporting)) {
+ if (TranslatorUtils.isErrorOnlyBlock(n.getThenStmt(), supportErrorReporting)) {
+ if (n.getElseStmt() != null
+ && !TranslatorUtils.isErrorOnlyBlock(n.getElseStmt(), supportErrorReporting)) {
+ printer.print("if (");
+ if (n.getCondition() instanceof BinaryExpr) {
+ BinaryExpr binExpr = (BinaryExpr) n.getCondition();
+ switch (binExpr.getOperator()) {
+ case equals:
+ binExpr.getLeft().accept(this, arg);
+ printer.print(" != ");
+ binExpr.getRight().accept(this, arg);
+ break;
+ case notEquals:
+ binExpr.getLeft().accept(this, arg);
+ printer.print(" == ");
+ binExpr.getRight().accept(this, arg);
+ break;
+ default:
+ printer.print("!(");
+ formatCondition(n.getCondition(), arg);
+ printer.print(")");
+ break;
+ }
+ } else {
+ printer.print("!(");
+ formatCondition(n.getCondition(), arg);
+ printer.print(")");
+ }
+ printer.print(") ");
+ n.getElseStmt().accept(this, arg);
+ }
+ } else {
+ boolean unlikely = (currentMethod != null)
+ && (Arrays.binarySearch(
+ METHODS_WITH_UNLIKELY_CONDITIONS,
+ currentMethod) >= 0);
+ printer.print("if (");
+ if (unlikely) {
+ printer.print(cppTypes.unlikely());
+ printer.print("(");
+ }
+ formatCondition(n.getCondition(), arg);
+ if (unlikely) {
+ printer.print(")");
+ }
+ printer.print(") ");
+ n.getThenStmt().accept(this, arg);
+ if (n.getElseStmt() != null
+ && !TranslatorUtils.isErrorOnlyBlock(n.getElseStmt(), supportErrorReporting)) {
+ printer.print(" else ");
+ n.getElseStmt().accept(this, arg);
+ }
+ }
+ }
+ }
+
+ private void formatCondition(Expression expr, LocalSymbolTable arg) {
+ if (expr instanceof BinaryExpr) {
+ BinaryExpr binExpr = (BinaryExpr) expr;
+ switch (binExpr.getOperator()) {
+ case notEquals:
+ if (binExpr.getRight() instanceof NullLiteralExpr) {
+ binExpr.getLeft().accept(this, arg);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ expr.accept(this, arg);
+ }
+
+
+ public void visit(WhileStmt n, LocalSymbolTable arg) {
+ printer.print("while (");
+ n.getCondition().accept(this, arg);
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ContinueStmt n, LocalSymbolTable arg) {
+ // Not supporting the general Java continue semantics.
+ // Instead, making the generated code more readable for the
+ // case at hand.
+ if (n.getId() != null) {
+ printer.print(cppTypes.continueMacro());
+ printer.print("(");
+ printer.print(n.getId());
+ printer.print(")");
+ if (forLoopsWithCondition.contains(n.getId())) {
+ throw new IllegalStateException(
+ "Continue attempted with a loop that has a condition. "
+ + className + " " + n.getId());
+ }
+ } else {
+ printer.print("continue");
+ }
+ printer.print(";");
+ }
+
+ public void visit(DoStmt n, LocalSymbolTable arg) {
+ printer.print("do ");
+ n.getBody().accept(this, arg);
+ printer.print(" while (");
+ n.getCondition().accept(this, arg);
+ printer.print(");");
+ }
+
+ public void visit(ForeachStmt n, LocalSymbolTable arg) {
+ printer.print("for (");
+ n.getVariable().accept(this, arg);
+ printer.print(" : ");
+ n.getIterable().accept(this, arg);
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ForStmt n, LocalSymbolTable arg) {
+ printer.print("for (");
+ if (n.getInit() != null) {
+ for (Iterator<Expression> i = n.getInit().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print("; ");
+ if (n.getCompare() != null) {
+ n.getCompare().accept(this, arg);
+ }
+ printer.print("; ");
+ if (n.getUpdate() != null) {
+ for (Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ThrowStmt n, LocalSymbolTable arg) {
+ printer.print("throw ");
+ n.getExpr().accept(this, arg);
+ printer.print(";");
+ }
+
+ public void visit(SynchronizedStmt n, LocalSymbolTable arg) {
+ printer.print("synchronized (");
+ n.getExpr().accept(this, arg);
+ printer.print(") ");
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(TryStmt n, LocalSymbolTable arg) {
+ printer.print("try ");
+ n.getTryBlock().accept(this, arg);
+ if (n.getCatchs() != null) {
+ for (CatchClause c : n.getCatchs()) {
+ c.accept(this, arg);
+ }
+ }
+ if (n.getFinallyBlock() != null) {
+ printer.print(" finally ");
+ n.getFinallyBlock().accept(this, arg);
+ }
+ }
+
+ public void visit(CatchClause n, LocalSymbolTable arg) {
+ printer.print(" catch (");
+ n.getExcept().accept(this, arg);
+ printer.print(") ");
+ n.getCatchBlock().accept(this, arg);
+
+ }
+
+ public void visit(AnnotationDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ currentAnnotations = n.getAnnotations();
+ // if (annotations != null) {
+ // for (AnnotationExpr a : annotations) {
+ // a.accept(this, arg);
+ // printer.printLn();
+ // }
+ // }
+ printModifiers(n.getModifiers());
+
+ printer.print("@interface ");
+ printer.print(n.getName());
+ currentAnnotations = null;
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getMembers() != null) {
+ printMembers(n.getMembers(), arg);
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+
+ public void visit(AnnotationMemberDeclaration n, LocalSymbolTable arg) {
+ if (n.getJavaDoc() != null) {
+ n.getJavaDoc().accept(this, arg);
+ }
+ currentAnnotations = n.getAnnotations();
+ // if (annotations != null) {
+ // for (AnnotationExpr a : annotations) {
+ // a.accept(this, arg);
+ // printer.printLn();
+ // }
+ // }
+ printModifiers(n.getModifiers());
+
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(n.getName());
+ currentAnnotations = null;
+ printer.print("()");
+ if (n.getDefaultValue() != null) {
+ printer.print(" default ");
+ n.getDefaultValue().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(MarkerAnnotationExpr n, LocalSymbolTable arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ }
+
+ public void visit(SingleMemberAnnotationExpr n, LocalSymbolTable arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ printer.print("(");
+ n.getMemberValue().accept(this, arg);
+ printer.print(")");
+ }
+
+ public void visit(NormalAnnotationExpr n, LocalSymbolTable arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ printer.print("(");
+ if (n.getPairs() != null) {
+ for (Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext();) {
+ MemberValuePair m = i.next();
+ m.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ }
+
+ public void visit(MemberValuePair n, LocalSymbolTable arg) {
+ printer.print(n.getName());
+ printer.print(" = ");
+ n.getValue().accept(this, arg);
+ }
+
+ public void visit(LineComment n, LocalSymbolTable arg) {
+ printer.print("//");
+ printer.printLn(n.getContent());
+ }
+
+ public void visit(BlockComment n, LocalSymbolTable arg) {
+ printer.print("/*");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+ public void setLabels(Set<String> labels) {
+ this.labels = labels;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/GkAtomParser.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/GkAtomParser.java
new file mode 100644
index 000000000..3d642c0e0
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/GkAtomParser.java
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class GkAtomParser {
+
+ private static final Pattern ATOM = Pattern.compile("^GK_ATOM\\(([^,]+),\\s*\"([^\"]*)\"\\).*$");
+
+ private final BufferedReader reader;
+
+ public GkAtomParser(Reader reader) {
+ this.reader = new BufferedReader(reader);
+ }
+
+ public Map<String, String> parse() throws IOException {
+ Map<String, String> map = new HashMap<String, String>();
+ String line;
+ while((line = reader.readLine()) != null) {
+ Matcher m = ATOM.matcher(line);
+ if (m.matches()) {
+ map.put(m.group(2), m.group(1));
+ }
+ }
+ return map;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/HVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/HVisitor.java
new file mode 100644
index 000000000..25cf7aef1
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/HVisitor.java
@@ -0,0 +1,306 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import japa.parser.ast.body.FieldDeclaration;
+import japa.parser.ast.body.MethodDeclaration;
+import japa.parser.ast.body.ModifierSet;
+import japa.parser.ast.body.Parameter;
+import japa.parser.ast.body.VariableDeclarator;
+import japa.parser.ast.expr.IntegerLiteralExpr;
+import japa.parser.ast.expr.MethodCallExpr;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.type.PrimitiveType;
+import japa.parser.ast.type.ReferenceType;
+import japa.parser.ast.type.Type;
+
+public class HVisitor extends CppVisitor {
+
+ private enum Visibility {
+ NONE, PRIVATE, PUBLIC, PROTECTED,
+ }
+
+ private Visibility previousVisibility = Visibility.NONE;
+
+ private List<String> defines = new LinkedList<String>();
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#printMethodNamespace()
+ */
+ @Override protected void printMethodNamespace() {
+ }
+
+ public HVisitor(CppTypes cppTypes, SymbolTable symbolTable) {
+ super(cppTypes, symbolTable);
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#startClassDeclaration()
+ */
+ @Override protected void startClassDeclaration() {
+ printer.print("#ifndef ");
+ printer.print(className);
+ printer.printLn("_h");
+ printer.print("#define ");
+ printer.print(className);
+ printer.printLn("_h");
+
+ printer.printLn();
+
+ String[] incs = cppTypes.boilerplateIncludes(javaClassName);
+ for (int i = 0; i < incs.length; i++) {
+ String inc = incs[i];
+ if (className.equals(inc)) {
+ continue;
+ }
+ printer.print("#include \"");
+ printer.print(inc);
+ printer.printLn(".h\"");
+ }
+
+ printer.printLn();
+
+ String[] forwDecls = cppTypes.boilerplateForwardDeclarations();
+ for (int i = 0; i < forwDecls.length; i++) {
+ String decl = forwDecls[i];
+ printer.print("class ");
+ printer.print(decl);
+ printer.printLn(";");
+ }
+
+ printer.printLn();
+
+ for (int i = 0; i < Main.H_LIST.length; i++) {
+ String klazz = Main.H_LIST[i];
+ if (!(klazz.equals(javaClassName) || klazz.equals("StackNode"))) {
+ printer.print("class ");
+ printer.print(cppTypes.classPrefix());
+ printer.print(klazz);
+ printer.printLn(";");
+ }
+ }
+
+ printer.printLn();
+
+ String[] otherDecls = cppTypes.boilerplateDeclarations(javaClassName);
+ for (int i = 0; i < otherDecls.length; i++) {
+ String decl = otherDecls[i];
+ printer.printLn(decl);
+ }
+
+ printer.printLn();
+
+ printer.print("class ");
+ printer.print(className);
+ if ("StateSnapshot".equals(javaClassName) || "TreeBuilder".equals(javaClassName)) {
+ printer.print(" : public ");
+ printer.print(cppTypes.treeBuilderStateInterface());
+ }
+ printer.printLn();
+ printer.printLn("{");
+ printer.indent();
+ printer.indent();
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#endClassDeclaration()
+ */
+ @Override protected void endClassDeclaration() {
+ printModifiers(ModifierSet.PUBLIC | ModifierSet.STATIC);
+ printer.printLn("void initializeStatics();");
+ printModifiers(ModifierSet.PUBLIC | ModifierSet.STATIC);
+ printer.printLn("void releaseStatics();");
+
+ printer.unindent();
+ printer.unindent();
+
+ if (cppTypes.hasSupplement(javaClassName)) {
+ printer.printLn();
+ printer.print("#include \"");
+ printer.print(className);
+ printer.printLn("HSupplement.h\"");
+ }
+
+ printer.printLn("};");
+ printer.printLn();
+
+ for (String define : defines) {
+ printer.printLn(define);
+ }
+
+ printer.printLn();
+ printer.printLn();
+ printer.printLn("#endif");
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#printModifiers(int)
+ */
+ @Override protected void printModifiers(int modifiers) {
+ if (ModifierSet.isPrivate(modifiers)) {
+ if (previousVisibility != Visibility.PRIVATE) {
+ printer.unindent();
+ printer.printLn("private:");
+ printer.indent();
+ previousVisibility = Visibility.PRIVATE;
+ }
+ } else if (ModifierSet.isProtected(modifiers)) {
+ if (previousVisibility != Visibility.PROTECTED) {
+ printer.unindent();
+ printer.printLn("protected:");
+ printer.indent();
+ previousVisibility = Visibility.PROTECTED;
+ }
+ } else {
+ if (previousVisibility != Visibility.PUBLIC) {
+ printer.unindent();
+ printer.printLn("public:");
+ printer.indent();
+ previousVisibility = Visibility.PUBLIC;
+ }
+ }
+ if (inline()) {
+ printer.print("inline ");
+ }
+ if (virtual()) {
+ printer.print("virtual ");
+ }
+ if (ModifierSet.isStatic(modifiers)) {
+ printer.print("static ");
+ }
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#fieldDeclaration(japa.parser.ast.body.FieldDeclaration, java.lang.LocalSymbolTable)
+ */
+ @Override protected void fieldDeclaration(FieldDeclaration n, LocalSymbolTable arg) {
+ int modifiers = n.getModifiers();
+ List<VariableDeclarator> variables = n.getVariables();
+ VariableDeclarator declarator = variables.get(0);
+ if (ModifierSet.isStatic(modifiers) && ModifierSet.isFinal(modifiers)
+ && n.getType() instanceof PrimitiveType) {
+ PrimitiveType type = (PrimitiveType) n.getType();
+ if (type.getType() != PrimitiveType.Primitive.Int) {
+ throw new IllegalStateException(
+ "Only int constant #defines supported.");
+ }
+ if (variables.size() != 1) {
+ throw new IllegalStateException(
+ "More than one variable declared by one declarator.");
+ }
+ String name = javaClassName + "." + declarator.getId().getName();
+ String value = declarator.getInit().toString();
+ if ("Integer.MAX_VALUE".equals(value)) {
+ value = cppTypes.maxInteger();
+ }
+ String longName = definePrefix + declarator.getId().getName();
+ if (symbolTable.cppDefinesByJavaNames.containsKey(name)) {
+ throw new IllegalStateException(
+ "Duplicate #define constant local name: " + name);
+ }
+ symbolTable.cppDefinesByJavaNames.put(name, longName);
+ defines.add("#define " + longName + " " + value);
+ } else {
+ if (n.getType() instanceof ReferenceType) {
+ ReferenceType rt = (ReferenceType) n.getType();
+ currentArrayCount = rt.getArrayCount();
+ if (currentArrayCount > 0
+ && (rt.getType() instanceof PrimitiveType) && declarator.getInit() != null) {
+ if (!ModifierSet.isStatic(modifiers)) {
+ throw new IllegalStateException(
+ "Non-static array case not supported here." + declarator);
+ }
+ if (noLength()) {
+ inPrimitiveNoLengthFieldDeclarator = true;
+ }
+ }
+ }
+ printModifiers(modifiers);
+ inStatic = ModifierSet.isStatic(modifiers);
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ if (ModifierSet.isStatic(modifiers)) {
+ if ("AttributeName".equals(n.getType().toString())) {
+ printer.print("ATTR_");
+ } else if ("ElementName".equals(n.getType().toString())) {
+ printer.print("ELT_");
+ }
+ }
+ declarator.getId().accept(this, arg);
+ printer.printLn(";");
+ currentArrayCount = 0;
+ inStatic = false;
+ inPrimitiveNoLengthFieldDeclarator = false;
+ }
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#printConstructorExplicit(java.util.List<japa.parser.ast.body.Parameter>)
+ */
+ @Override protected void printConstructorExplicit(List<Parameter> params) {
+ if (params != null && params.size() == 1) {
+ printer.print("explicit ");
+ }
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#printConstructorBody(japa.parser.ast.stmt.BlockStmt, java.lang.LocalSymbolTable)
+ */
+ @Override protected void printConstructorBody(BlockStmt block, LocalSymbolTable arg) {
+ printer.printLn(";");
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#visit(japa.parser.ast.body.MethodDeclaration, java.lang.LocalSymbolTable)
+ */
+ @Override public void visit(MethodDeclaration n, LocalSymbolTable arg) {
+ arg = new LocalSymbolTable(javaClassName, symbolTable);
+ printMethodDeclaration(n, arg);
+ }
+
+ /**
+ * @see nu.validator.htmlparser.cpptranslate.CppVisitor#inHeader()
+ */
+ @Override protected boolean inHeader() {
+ return true;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LabelVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LabelVisitor.java
new file mode 100644
index 000000000..f27d465a3
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LabelVisitor.java
@@ -0,0 +1,84 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.visitor.VoidVisitorAdapter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class LabelVisitor extends VoidVisitorAdapter<Object> {
+
+ private final Set<String> labels = new HashSet<String>();
+
+ public LabelVisitor() {
+ }
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.stmt.BreakStmt, java.lang.Object)
+ */
+ @Override
+ public void visit(BreakStmt n, Object arg) {
+ String label = n.getId();
+ if (label != null) {
+ labels.add(label + "_end");
+ }
+ }
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.stmt.ContinueStmt, java.lang.Object)
+ */
+ @Override
+ public void visit(ContinueStmt n, Object arg) {
+ String label = n.getId();
+ if (label != null) {
+ labels.add(label);
+ }
+ }
+
+ /**
+ * Returns the labels.
+ *
+ * @return the labels
+ */
+ public Set<String> getLabels() {
+ return labels;
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LicenseExtractor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LicenseExtractor.java
new file mode 100644
index 000000000..e4030f438
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LicenseExtractor.java
@@ -0,0 +1,75 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+public class LicenseExtractor {
+
+ private final Reader reader;
+
+ public LicenseExtractor(File file) throws IOException {
+ this.reader = new InputStreamReader(new FileInputStream(file), "utf-8");
+ }
+
+ public String extract() throws IOException {
+ boolean prevWasAsterisk = false;
+ StringBuilder sb = new StringBuilder();
+ int c;
+ while ((c = reader.read()) != -1) {
+ sb.append((char)c);
+ switch (c) {
+ case '*':
+ prevWasAsterisk = true;
+ continue;
+ case '/':
+ if (prevWasAsterisk) {
+ return sb.toString();
+ }
+ default:
+ prevWasAsterisk = false;
+ continue;
+ }
+ }
+ return "";
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LocalSymbolTable.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LocalSymbolTable.java
new file mode 100644
index 000000000..a9375e88a
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/LocalSymbolTable.java
@@ -0,0 +1,89 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class LocalSymbolTable {
+
+ private final Map<String, Type> locals = new HashMap<String, Type>();
+
+ private final String javaClassName;
+
+ private final SymbolTable delegate;
+
+ /**
+ * @param javaClassName
+ * @param delegate
+ */
+ public LocalSymbolTable(String javaClassName, SymbolTable delegate) {
+ this.javaClassName = javaClassName;
+ this.delegate = delegate;
+ }
+
+ public void putLocalType(String name, Type type) {
+ locals.put(name, type);
+ }
+
+ /**
+ * @param klazz
+ * @param variable
+ * @return
+ * @see nu.validator.htmlparser.cpptranslate.SymbolTable#getFieldType(java.lang.String, java.lang.String)
+ */
+ public Type getVariableType(String klazz, String variable) {
+ if (klazz == null) {
+ Type type = locals.get(variable);
+ if (type != null) {
+ return type;
+ }
+ }
+ return delegate.getFieldType(((klazz == null || "this".equals(klazz)) ? javaClassName : klazz), variable);
+ }
+
+ /**
+ * @param klazz may be <code>null</code> or "this"
+ * @param method
+ * @return
+ * @see nu.validator.htmlparser.cpptranslate.SymbolTable#getMethodReturnType(java.lang.String, java.lang.String)
+ */
+ public Type getMethodReturnType(String klazz, String method) {
+ return delegate.getMethodReturnType(((klazz == null || "this".equals(klazz)) ? javaClassName : klazz), method);
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Main.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Main.java
new file mode 100644
index 000000000..53347bd42
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Main.java
@@ -0,0 +1,148 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import japa.parser.JavaParser;
+import japa.parser.ParseException;
+import japa.parser.ast.CompilationUnit;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+public class Main {
+
+ static final String[] H_LIST = {
+ "Tokenizer",
+ "TreeBuilder",
+ "MetaScanner",
+ "AttributeName",
+ "ElementName",
+ "HtmlAttributes",
+ "StackNode",
+ "UTF16Buffer",
+ "StateSnapshot",
+ "Portability",
+ };
+
+ private static final String[] CPP_LIST = {
+ "Tokenizer",
+ "TreeBuilder",
+ "MetaScanner",
+ "AttributeName",
+ "ElementName",
+ "HtmlAttributes",
+ "StackNode",
+ "UTF16Buffer",
+ "StateSnapshot",
+ };
+
+ /**
+ * @param args
+ * @throws ParseException
+ * @throws IOException
+ */
+ public static void main(String[] args) throws ParseException, IOException {
+ CppTypes cppTypes = new CppTypes(new File(args[2]));
+ SymbolTable symbolTable = new SymbolTable();
+
+ File javaDirectory = new File(args[0]);
+ File targetDirectory = new File(args[1]);
+ File cppDirectory = targetDirectory;
+ File javaCopyDirectory = new File(targetDirectory, "javasrc");
+
+ for (int i = 0; i < H_LIST.length; i++) {
+ parseFile(cppTypes, javaDirectory, cppDirectory, H_LIST[i], ".h", new HVisitor(cppTypes, symbolTable));
+ copyFile(new File(javaDirectory, H_LIST[i] + ".java"), new File(javaCopyDirectory, H_LIST[i] + ".java"));
+ }
+ for (int i = 0; i < CPP_LIST.length; i++) {
+ parseFile(cppTypes, javaDirectory, cppDirectory, CPP_LIST[i], ".cpp", new CppVisitor(cppTypes, symbolTable));
+ }
+ cppTypes.finished();
+ }
+
+ private static void copyFile(File input, File output) throws IOException {
+ if (input.getCanonicalFile().equals(output.getCanonicalFile())) {
+ return; // files are the same!
+ }
+ // This is horribly inefficient, but perf is not really much of a concern here.
+ FileInputStream in = new FileInputStream(input);
+ FileOutputStream out = new FileOutputStream(output);
+ int b;
+ while ((b = in.read()) != -1) {
+ out.write(b);
+ }
+ out.flush();
+ out.close();
+ in.close();
+ }
+
+ private static void parseFile(CppTypes cppTypes, File javaDirectory,
+ File cppDirectory, String className, String fne, CppVisitor visitor)
+ throws FileNotFoundException, UnsupportedEncodingException,
+ IOException {
+ File file = null;
+ try {
+ file = new File(javaDirectory, className + ".java");
+ String license = new LicenseExtractor(file).extract();
+ CompilationUnit cu = JavaParser.parse(new NoCppInputStream(
+ new CppOnlyInputStream(new FileInputStream(file))), "utf-8");
+ LabelVisitor labelVisitor = new LabelVisitor();
+ cu.accept(labelVisitor, null);
+ visitor.setLabels(labelVisitor.getLabels());
+ cu.accept(visitor, null);
+ FileOutputStream out = new FileOutputStream(new File(cppDirectory,
+ cppTypes.classPrefix() + className + fne));
+ OutputStreamWriter w = new OutputStreamWriter(out, "utf-8");
+ w.write(license);
+ w.write("\n\n/*\n * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.\n * Please edit "
+ + className + ".java instead and regenerate.\n */\n\n");
+ w.write(visitor.getSource());
+ w.close();
+ } catch (ParseException e) {
+ System.err.println(file);
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/NoCppInputStream.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/NoCppInputStream.java
new file mode 100644
index 000000000..86f9ae7ff
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/NoCppInputStream.java
@@ -0,0 +1,86 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class NoCppInputStream extends InputStream {
+
+ private final static char[] START = "[NOCPP[".toCharArray();
+
+ private final static char[] END = "]NOCPP]".toCharArray();
+
+ private int state;
+
+ private final InputStream delegate;
+
+
+
+ /**
+ * @param delegate
+ */
+ public NoCppInputStream(InputStream delegate) {
+ this.delegate = delegate;
+ this.state = 0;
+ }
+
+ @Override public int read() throws IOException {
+ int c;
+ if (state == START.length) {
+ int endState = 0;
+ while (endState != END.length) {
+ c = delegate.read();
+ if (END[endState] == c) {
+ endState++;
+ } else {
+ endState = 0;
+ }
+ }
+ state = 0;
+ }
+ c = delegate.read();
+ if (START[state] == c) {
+ state++;
+ } else {
+ state = 0;
+ }
+ return c;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringLiteralParser.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringLiteralParser.java
new file mode 100644
index 000000000..305f516a7
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringLiteralParser.java
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringLiteralParser {
+
+ private static final Pattern STRING_DECL = Pattern.compile("^.*\\(([^ ]+) = new nsString\\(\\)\\)->Assign\\(NS_LITERAL_STRING\\(\"([^\"]*)\"\\)\\);.*$");
+
+ private final BufferedReader reader;
+
+ public StringLiteralParser(Reader reader) {
+ this.reader = new BufferedReader(reader);
+ }
+
+ public Map<String, String> parse() throws IOException {
+ Map<String, String> map = new HashMap<String, String>();
+ String line;
+ while((line = reader.readLine()) != null) {
+ Matcher m = STRING_DECL.matcher(line);
+ if (m.matches()) {
+ map.put(m.group(2), m.group(1));
+ }
+ }
+ return map;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringPair.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringPair.java
new file mode 100644
index 000000000..e24247f7e
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/StringPair.java
@@ -0,0 +1,73 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+public class StringPair {
+
+ /**
+ * @param first
+ * @param second
+ */
+ public StringPair(String first, String second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ private final String first;
+
+ private final String second;
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override public boolean equals(Object o) {
+ if (o instanceof StringPair) {
+ StringPair other = (StringPair) o;
+ return first.equals(other.first) && second.equals(other.second);
+ }
+ return false;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override public int hashCode() {
+ return first.hashCode() ^ second.hashCode();
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTable.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTable.java
new file mode 100644
index 000000000..970a2b64b
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTable.java
@@ -0,0 +1,80 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SymbolTable {
+
+ public final Map<String, String> cppDefinesByJavaNames = new HashMap<String, String>();
+
+ private final Map<StringPair, Type> fields = new HashMap<StringPair, Type>();
+
+ private final Map<StringPair, Type> methodReturns = new HashMap<StringPair, Type>();
+
+ /**
+ * This is a sad hack to work around the fact the there's no real symbol
+ * table yet.
+ *
+ * @param name
+ * @return
+ */
+ public boolean isNotAnAttributeOrElementName(String name) {
+ return !("ATTRIBUTE_HASHES".equals(name)
+ || "ATTRIBUTE_NAMES".equals(name)
+ || "ELEMENT_HASHES".equals(name)
+ || "ELEMENT_NAMES".equals(name) || "ALL_NO_NS".equals(name));
+ }
+
+ public void putFieldType(String klazz, String field, Type type) {
+ fields.put(new StringPair(klazz, field), type);
+ }
+
+ public void putMethodReturnType(String klazz, String method, Type type) {
+ methodReturns.put(new StringPair(klazz, method), type);
+ }
+
+ public Type getFieldType(String klazz, String field) {
+ return fields.get(new StringPair(klazz, field));
+ }
+
+ public Type getMethodReturnType(String klazz, String method) {
+ return methodReturns.get(new StringPair(klazz, method));
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTableVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTableVisitor.java
new file mode 100644
index 000000000..00f7c5741
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/SymbolTableVisitor.java
@@ -0,0 +1,71 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+import japa.parser.ast.body.ClassOrInterfaceDeclaration;
+import japa.parser.ast.body.FieldDeclaration;
+import japa.parser.ast.body.MethodDeclaration;
+
+public class SymbolTableVisitor extends AnnotationHelperVisitor<SymbolTable> {
+
+ private String javaClassName;
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.body.FieldDeclaration, java.lang.Object)
+ */
+ @Override public void visit(FieldDeclaration n, SymbolTable arg) {
+ currentAnnotations = n.getAnnotations();
+ arg.putFieldType(javaClassName, n.getVariables().get(0).getId().getName(), convertType(n.getType(), n.getModifiers()));
+ }
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.body.MethodDeclaration, java.lang.Object)
+ */
+ @Override public void visit(MethodDeclaration n, SymbolTable arg) {
+ currentAnnotations = n.getAnnotations();
+ arg.putMethodReturnType(javaClassName, n.getName(), convertType(n.getType(), n.getModifiers()));
+ }
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.body.ClassOrInterfaceDeclaration, java.lang.Object)
+ */
+ @Override public void visit(ClassOrInterfaceDeclaration n, SymbolTable arg) {
+ javaClassName = n.getName();
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/TranslatorUtils.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/TranslatorUtils.java
new file mode 100644
index 000000000..866db093d
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/TranslatorUtils.java
@@ -0,0 +1,81 @@
+package nu.validator.htmlparser.cpptranslate;
+
+import japa.parser.ast.expr.BinaryExpr;
+import japa.parser.ast.expr.BinaryExpr.Operator;
+import japa.parser.ast.expr.Expression;
+import japa.parser.ast.expr.MethodCallExpr;
+import japa.parser.ast.expr.NameExpr;
+import japa.parser.ast.expr.NullLiteralExpr;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.Statement;
+
+import java.util.List;
+
+public class TranslatorUtils {
+ public static boolean isErrorOnlyBlock(Statement elseStmt, boolean supportErrorReporting) {
+ if (supportErrorReporting) {
+ return false;
+ }
+ if (elseStmt instanceof BlockStmt) {
+ BlockStmt block = (BlockStmt) elseStmt;
+ List<Statement> statements = block.getStmts();
+ if (statements == null) {
+ return false;
+ }
+ if (statements.size() != 1) {
+ return false;
+ }
+ Statement statement = statements.get(0);
+ if (statement instanceof ExpressionStmt) {
+ ExpressionStmt exprStmt = (ExpressionStmt) statement;
+ Expression expr = exprStmt.getExpression();
+ if (expr instanceof MethodCallExpr) {
+ MethodCallExpr call = (MethodCallExpr) expr;
+ if (call.getName().startsWith("err")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean isErrorHandlerIf(Expression condition, boolean supportErrorReporting) {
+ if (supportErrorReporting) {
+ return false;
+ }
+ while (condition instanceof BinaryExpr) {
+ BinaryExpr binex = (BinaryExpr) condition;
+ condition = binex.getLeft();
+ if (condition instanceof NameExpr) {
+ NameExpr name = (NameExpr) condition;
+ if ("errorHandler".equals(name.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean isDocumentModeHandlerNullCheck(Expression condition) {
+ if (condition instanceof BinaryExpr) {
+ BinaryExpr binex = (BinaryExpr) condition;
+ if (binex.getOperator() != Operator.notEquals) {
+ return false;
+ }
+ if (!(binex.getRight() instanceof NullLiteralExpr)) {
+ return false;
+ }
+ Expression left = binex.getLeft();
+ if (left instanceof NameExpr) {
+ NameExpr name = (NameExpr) left;
+ if ("documentModeHandler".equals(name.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Type.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Type.java
new file mode 100644
index 000000000..783a3bbd0
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/cpptranslate/Type.java
@@ -0,0 +1,99 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.cpptranslate;
+
+public class Type {
+
+ /**
+ * @param type
+ * @param arrayCount
+ * @param noLength
+ * @param modifiers
+ */
+ public Type(String type, int arrayCount, boolean noLength, int modifiers) {
+ this.type = type;
+ this.arrayCount = arrayCount;
+ this.noLength = noLength;
+ this.modifiers = modifiers;
+ }
+
+ private final String type;
+
+ private final int arrayCount;
+
+ private final boolean noLength;
+
+ private final int modifiers;
+
+ /**
+ * Returns the type.
+ *
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the arrayCount.
+ *
+ * @return the arrayCount
+ */
+ public int getArrayCount() {
+ return arrayCount;
+ }
+
+ /**
+ * Returns the noLength.
+ *
+ * @return the noLength
+ */
+ public boolean isNoLength() {
+ return noLength;
+ }
+
+ /**
+ * Returns the modifiers.
+ *
+ * @return the modifiers
+ */
+ public int getModifiers() {
+ return modifiers;
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/ApplyHotSpotWorkaround.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/ApplyHotSpotWorkaround.java
new file mode 100644
index 000000000..eb580e70c
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/ApplyHotSpotWorkaround.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010-2011 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.generator;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Applies a workaround that splits the <code>stateLoop</code> method in the
+ * tokenizer into two methods. This way, each method stays under 8000 bytes in
+ * size. By default, HotSpot doesn't compile methods that are over 8000 bytes in
+ * size, which is a performance problem.
+ *
+ * This program should have been written in Perl, but to avoid introducing new
+ * dependencies, it's written in Java. No attempt at efficiency has been made.
+ *
+ * Warning! This modifies Tokenizer.java in place!
+ *
+ * @version $Id$
+ * @author hsivonen
+ */
+public class ApplyHotSpotWorkaround {
+
+ private static final String BEGIN_WORKAROUND = "// BEGIN HOTSPOT WORKAROUND";
+
+ private static final String END_WORKAROUND = "// END HOTSPOT WORKAROUND";
+
+ public static void main(String[] args) throws Throwable {
+ String tokenizer = readFileIntoString(args[0]);
+ String workaround = readFileIntoString(args[1]);
+
+ int beginIndex = tokenizer.indexOf(BEGIN_WORKAROUND);
+ int endIndex = tokenizer.indexOf(END_WORKAROUND);
+ String tokenizerHead = tokenizer.substring(0, beginIndex);
+ String tokenizerMiddle = tokenizer.substring(beginIndex, endIndex);
+ String tokenizerTail = tokenizer.substring(endIndex);
+
+ beginIndex = workaround.indexOf(BEGIN_WORKAROUND);
+ endIndex = workaround.indexOf(END_WORKAROUND);
+ String workaroundHead = workaround.substring(0, beginIndex);
+ String workaroundMiddle = workaround.substring(beginIndex, endIndex);
+ String workaroundTail = workaround.substring(endIndex);
+
+ String newTokenizer = tokenizerHead + workaroundMiddle + tokenizerTail;
+ String newWorkaround = workaroundHead + tokenizerMiddle
+ + workaroundTail;
+
+ int insertionPoint = newTokenizer.indexOf("// HOTSPOT WORKAROUND INSERTION POINT");
+
+ tokenizerHead = newTokenizer.substring(0, insertionPoint);
+ tokenizerTail = newTokenizer.substring(insertionPoint);
+
+ newTokenizer = tokenizerHead + newWorkaround + tokenizerTail;
+
+ Pattern pat = Pattern.compile("state = transition\\(state, ([^,]*), reconsume, pos\\)");
+ Matcher m = pat.matcher(newTokenizer);
+ newTokenizer = m.replaceAll("state = $1");
+
+ Writer out = new OutputStreamWriter(new FileOutputStream(args[0]),
+ "utf-8");
+ out.write(newTokenizer);
+ out.flush();
+ out.close();
+ }
+
+ private static String readFileIntoString(String name) throws IOException {
+ Reader in = new InputStreamReader(new FileInputStream(name), "UTF-8");
+ StringBuilder builder = new StringBuilder();
+ int c;
+ while ((c = in.read()) != -1) {
+ builder.append((char) c);
+ }
+ in.close();
+ return builder.toString();
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharacters.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharacters.java
new file mode 100644
index 000000000..69ddb318e
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharacters.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2008-2009 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.generator;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class GenerateNamedCharacters {
+
+ private static final int LEAD_OFFSET = 0xD800 - (0x10000 >> 10);
+
+ private static final Pattern LINE_PATTERN = Pattern.compile("<td> <code title=\"\">([^<]*)</code> </td> <td> U\\+(\\S*) (?:U\\+(\\S*) )?</td>");
+
+ private static String toUString(int c) {
+ String hexString = Integer.toHexString(c);
+ switch (hexString.length()) {
+ case 1:
+ return "\\u000" + hexString;
+ case 2:
+ return "\\u00" + hexString;
+ case 3:
+ return "\\u0" + hexString;
+ case 4:
+ return "\\u" + hexString;
+ default:
+ throw new RuntimeException("Unreachable.");
+ }
+ }
+
+ private static int charToIndex(char c) {
+ if (c >= 'a' && c <= 'z') {
+ return c - 'a' + 26;
+ } else if (c >= 'A' && c <= 'Z') {
+ return c - 'A';
+ }
+ throw new IllegalArgumentException("Bad char in named character name: "
+ + c);
+ }
+
+ private static boolean allZero(int[] arr) {
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @param args
+ * @throws IOException
+ */
+ public static void main(String[] args) throws IOException {
+ TreeMap<String, String> entities = new TreeMap<String, String>();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ System.in, "utf-8"));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ Matcher m = LINE_PATTERN.matcher(line);
+ while (m.find()) {
+ String value;
+ if (m.group(3) != null) {
+ // two BMP chars
+ int firstIntVal = Integer.parseInt(m.group(2), 16);
+ int secondIntVal = Integer.parseInt(m.group(3), 16);
+ value = ("" + (char)firstIntVal) + (char)secondIntVal;
+ } else {
+ // one code point
+ int intVal = Integer.parseInt(m.group(2), 16);
+ if (intVal <= 0xFFFF) {
+ value = "" + (char)intVal;
+ } else {
+ int high = (LEAD_OFFSET + (intVal >> 10));
+ int low = (0xDC00 + (intVal & 0x3FF));
+ value = ("" + (char)high) + (char)low;
+ }
+ }
+ entities.put(m.group(1), value);
+ }
+ }
+
+ // Java initializes arrays to zero. Zero is our magic value for no hilo
+ // value.
+ int[][] hiLoTable = new int['z' + 1]['Z' - 'A' + 1 + 'z' - 'a' + 1];
+
+ String firstName = entities.entrySet().iterator().next().getKey();
+ int firstKey = charToIndex(firstName.charAt(0));
+ int secondKey = firstName.charAt(1);
+ int row = 0;
+ int lo = 0;
+
+ System.out.print("static final @NoLength @CharacterName String[] NAMES = {\n");
+ for (Map.Entry<String, String> entity : entities.entrySet()) {
+ String name = entity.getKey();
+ int newFirst = charToIndex(name.charAt(0));
+ int newSecond = name.charAt(1);
+ assert !(newFirst == 0 && newSecond == 0) : "Not prepared for name starting with AA";
+ if (firstKey != newFirst || secondKey != newSecond) {
+ hiLoTable[secondKey][firstKey] = ((row - 1) << 16) | lo;
+ lo = row;
+ firstKey = newFirst;
+ secondKey = newSecond;
+ }
+ System.out.print("\"");
+ System.out.print(name.substring(2));
+ System.out.print("\",\n");
+ row++;
+ }
+ System.out.print("};\n");
+
+ hiLoTable[secondKey][firstKey] = ((entities.size() - 1) << 16) | lo;
+
+ System.out.print("static final @NoLength char[][] VALUES = {\n");
+ for (Map.Entry<String, String> entity : entities.entrySet()) {
+ String value = entity.getValue();
+ System.out.print("{");
+ if (value.length() == 1) {
+ char c = value.charAt(0);
+ if (c == '\'') {
+ System.out.print("\'\\\'\'");
+ } else if (c == '\n') {
+ System.out.print("\'\\n\'");
+ } else if (c == '\\') {
+ System.out.print("\'\\\\\'");
+ } else if (c <= 0xFFFF) {
+ System.out.print("\'");
+ System.out.print(toUString(c));
+ System.out.print("\'");
+ }
+ } else {
+ System.out.print("\'");
+ System.out.print(toUString(value.charAt(0)));
+ System.out.print("\', \'");
+ System.out.print(toUString(value.charAt(1)));
+ System.out.print("\'");
+ }
+ System.out.print("},\n");
+ }
+ System.out.print("};\n");
+
+ System.out.print("static final @NoLength int[][] HILO_ACCEL = {\n");
+ for (int i = 0; i < hiLoTable.length; i++) {
+ if (allZero(hiLoTable[i])) {
+ System.out.print("null,\n");
+ } else {
+ System.out.print("{");
+ for (int j = 0; j < hiLoTable[i].length; j++) {
+ System.out.print(hiLoTable[i][j]);
+ System.out.print(", ");
+ }
+ System.out.print("},\n");
+ }
+ }
+ System.out.print("};\n");
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharactersCpp.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharactersCpp.java
new file mode 100644
index 000000000..2cfe7b112
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/generator/GenerateNamedCharactersCpp.java
@@ -0,0 +1,580 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser C++ Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.generator;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import nu.validator.htmlparser.cpptranslate.CppTypes;
+
+public class GenerateNamedCharactersCpp {
+
+ /**
+ * The license for the output of this program except for data files.
+ */
+ private static final String OUTPUT_LICENSE = "/*\n"
+ + " * Copyright (c) 2008-2010 Mozilla Foundation\n"
+ + " *\n"
+ + " * Permission is hereby granted, free of charge, to any person obtaining a \n"
+ + " * copy of this software and associated documentation files (the \"Software\"), \n"
+ + " * to deal in the Software without restriction, including without limitation \n"
+ + " * the rights to use, copy, modify, merge, publish, distribute, sublicense, \n"
+ + " * and/or sell copies of the Software, and to permit persons to whom the \n"
+ + " * Software is furnished to do so, subject to the following conditions:\n"
+ + " *\n"
+ + " * The above copyright notice and this permission notice shall be included in \n"
+ + " * all copies or substantial portions of the Software.\n"
+ + " *\n"
+ + " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \n"
+ + " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n"
+ + " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \n"
+ + " * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n"
+ + " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \n"
+ + " * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n"
+ + " * DEALINGS IN THE SOFTWARE.\n" + " */\n\n";
+
+ /**
+ * The license for the generated data files.
+ */
+ private static final String DATA_LICENSE = "/*\n"
+ + " * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera \n"
+ + " * Software ASA.\n"
+ + " * \n"
+ + " * You are granted a license to use, reproduce and create derivative works of \n"
+ + " * this document.\n" + " */\n\n";
+
+ private static final int LEAD_OFFSET = 0xD800 - (0x10000 >> 10);
+
+ private static final Pattern LINE_PATTERN = Pattern.compile("<td> <code title=\"\">([^<]*)</code> </td> <td> U\\+(\\S*) (?:U\\+(\\S*) )?</td>");
+
+ private static String toHexString(int c) {
+ String hexString = Integer.toHexString(c);
+ switch (hexString.length()) {
+ case 1:
+ return "0x000" + hexString;
+ case 2:
+ return "0x00" + hexString;
+ case 3:
+ return "0x0" + hexString;
+ case 4:
+ return "0x" + hexString;
+ default:
+ throw new RuntimeException("Unreachable.");
+ }
+ }
+
+ /**
+ * @param args
+ * @throws IOException
+ */
+ public static void main(String[] args) throws IOException {
+ TreeMap<String, String> entities = new TreeMap<String, String>();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(args[0]), "utf-8"));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ Matcher m = LINE_PATTERN.matcher(line);
+ while (m.find()) {
+ String value;
+ if (m.group(3) != null) {
+ // two BMP chars
+ int firstIntVal = Integer.parseInt(m.group(2), 16);
+ int secondIntVal = Integer.parseInt(m.group(3), 16);
+ value = ("" + (char)firstIntVal) + (char)secondIntVal;
+ } else {
+ // one code point
+ int intVal = Integer.parseInt(m.group(2), 16);
+ if (intVal <= 0xFFFF) {
+ value = "" + (char)intVal;
+ } else {
+ int high = (LEAD_OFFSET + (intVal >> 10));
+ int low = (0xDC00 + (intVal & 0x3FF));
+ value = ("" + (char)high) + (char)low;
+ }
+ }
+ entities.put(m.group(1), value);
+ }
+ }
+
+ CppTypes cppTypes = new CppTypes(null);
+ File targetDirectory = new File(args[1]);
+
+ generateH(targetDirectory, cppTypes, entities);
+ generateInclude(targetDirectory, cppTypes, entities);
+ generateCpp(targetDirectory, cppTypes, entities);
+ generateAccelH(targetDirectory, cppTypes, entities);
+ generateAccelCpp(targetDirectory, cppTypes, entities);
+ }
+
+ private static void generateAccelCpp(File targetDirectory,
+ CppTypes cppTypes, TreeMap<String, String> entities) throws IOException {
+ String includeFile = cppTypes.classPrefix()
+ + "NamedCharactersInclude.h";
+ File cppFile = new File(targetDirectory, cppTypes.classPrefix()
+ + "NamedCharactersAccel.cpp");
+ Writer out = new OutputStreamWriter(new FileOutputStream(cppFile),
+ "utf-8");
+
+ out.write(DATA_LICENSE);
+ out.write('\n');
+ out.write("#include \"" + cppTypes.classPrefix()
+ + "NamedCharactersAccel.h\"\n");
+ out.write("\n");
+
+ // Java initializes arrays to zero. Zero is our magic value for no hilo
+ // value.
+ int[][] hiLoTable = new int['z' + 1]['Z' - 'A' + 1 + 'z' - 'a' + 1];
+
+ String firstName = entities.entrySet().iterator().next().getKey();
+ int firstKey = charToIndex(firstName.charAt(0));
+ int secondKey = firstName.charAt(1);
+ int row = 0;
+ int lo = 0;
+
+ for (Map.Entry<String, String> entity : entities.entrySet()) {
+ String name = entity.getKey();
+ int newFirst = charToIndex(name.charAt(0));
+ int newSecond = name.charAt(1);
+ assert !(newFirst == 0 && newSecond == 0) : "Not prepared for name starting with AA";
+ if (firstKey != newFirst || secondKey != newSecond) {
+ hiLoTable[secondKey][firstKey] = ((row - 1) << 16) | lo;
+ lo = row;
+ firstKey = newFirst;
+ secondKey = newSecond;
+ }
+ row++;
+ }
+
+ hiLoTable[secondKey][firstKey] = ((entities.size() - 1) << 16) | lo;
+
+ for (int i = 0; i < hiLoTable.length; i++) {
+ if (!allZero(hiLoTable[i])) {
+ out.write("static " + cppTypes.intType() + " const HILO_ACCEL_"
+ + i + "[] = {\n");
+ for (int j = 0; j < hiLoTable[i].length; j++) {
+ if (j != 0) {
+ out.write(", ");
+ }
+ out.write("" + hiLoTable[i][j]);
+ }
+ out.write("\n};\n\n");
+ }
+ }
+
+ out.write("const int32_t* const " + cppTypes.classPrefix()
+ + "NamedCharactersAccel::HILO_ACCEL[] = {\n");
+ for (int i = 0; i < hiLoTable.length; i++) {
+ if (i != 0) {
+ out.write(",\n");
+ }
+ if (allZero(hiLoTable[i])) {
+ out.write(" 0");
+ } else {
+ out.write(" HILO_ACCEL_" + i);
+ }
+ }
+ out.write("\n};\n\n");
+
+ out.flush();
+ out.close();
+ }
+
+ private static void generateAccelH(File targetDirectory, CppTypes cppTypes,
+ TreeMap<String, String> entities) throws IOException {
+ File hFile = new File(targetDirectory, cppTypes.classPrefix()
+ + "NamedCharactersAccel.h");
+ Writer out = new OutputStreamWriter(new FileOutputStream(hFile),
+ "utf-8");
+ out.write(DATA_LICENSE);
+ out.write("#ifndef " + cppTypes.classPrefix() + "NamedCharactersAccel_h\n");
+ out.write("#define " + cppTypes.classPrefix() + "NamedCharactersAccel_h\n");
+ out.write('\n');
+
+ String[] includes = cppTypes.namedCharactersIncludes();
+ for (int i = 0; i < includes.length; i++) {
+ String include = includes[i];
+ out.write("#include \"" + include + ".h\"\n");
+ }
+
+ out.write('\n');
+
+ out.write("class " + cppTypes.classPrefix() + "NamedCharactersAccel\n");
+ out.write("{\n");
+ out.write(" public:\n");
+ out.write(" static const " + cppTypes.intType()
+ + "* const HILO_ACCEL[];\n");
+ out.write("};\n");
+
+ out.write("\n#endif // " + cppTypes.classPrefix()
+ + "NamedCharactersAccel_h\n");
+ out.flush();
+ out.close();
+ }
+
+ private static void generateH(File targetDirectory, CppTypes cppTypes,
+ Map<String, String> entities) throws IOException {
+ File hFile = new File(targetDirectory, cppTypes.classPrefix()
+ + "NamedCharacters.h");
+ Writer out = new OutputStreamWriter(new FileOutputStream(hFile),
+ "utf-8");
+ out.write(OUTPUT_LICENSE);
+ out.write("#ifndef " + cppTypes.classPrefix() + "NamedCharacters_h\n");
+ out.write("#define " + cppTypes.classPrefix() + "NamedCharacters_h\n");
+ out.write('\n');
+
+ String[] includes = cppTypes.namedCharactersIncludes();
+ for (int i = 0; i < includes.length; i++) {
+ String include = includes[i];
+ out.write("#include \"" + include + ".h\"\n");
+ }
+
+ out.write("\nstruct ");
+ out.write(cppTypes.characterNameTypeDeclaration());
+ out.write(" {\n ");
+ out.write(cppTypes.unsignedShortType());
+ out.write(" nameStart;\n ");
+ out.write(cppTypes.unsignedShortType());
+ out.write(" nameLen;\n #ifdef DEBUG\n ");
+ out.write(cppTypes.intType());
+ out.write(" n;\n #endif\n ");
+ out.write(cppTypes.intType());
+ out.write(" length() const;\n ");
+ out.write(cppTypes.charType());
+ out.write(" charAt(");
+ out.write(cppTypes.intType());
+ out.write(" index) const;\n};\n\n");
+
+ out.write("class " + cppTypes.classPrefix() + "NamedCharacters\n");
+ out.write("{\n");
+ out.write(" public:\n");
+ out.write(" static const " + cppTypes.characterNameTypeDeclaration() + " NAMES[];\n");
+ out.write(" static const " + cppTypes.charType() + " VALUES[][2];\n");
+ out.write(" static " + cppTypes.charType() + "** WINDOWS_1252;\n");
+ out.write(" static void initializeStatics();\n");
+ out.write(" static void releaseStatics();\n");
+ out.write("};\n");
+
+ out.write("\n#endif // " + cppTypes.classPrefix()
+ + "NamedCharacters_h\n");
+ out.flush();
+ out.close();
+ }
+
+ private static void generateInclude(File targetDirectory,
+ CppTypes cppTypes, Map<String, String> entities) throws IOException {
+ File includeFile = new File(targetDirectory, cppTypes.classPrefix()
+ + "NamedCharactersInclude.h");
+ Writer out = new OutputStreamWriter(new FileOutputStream(includeFile),
+ "utf-8");
+
+ out.write(DATA_LICENSE);
+ out.write("/* Data generated from the table of named character references found at\n");
+ out.write(" *\n");
+ out.write(" * http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html#named-character-references\n");
+ out.write(" *\n");
+ out.write(" * Files that #include this file must #define NAMED_CHARACTER_REFERENCE as a\n");
+ out.write(" * macro of four parameters:\n");
+ out.write(" *\n");
+ out.write(" * 1. a unique integer N identifying the Nth [0,1,..] macro expansion in this file,\n");
+ out.write(" * 2. a comma-separated sequence of characters comprising the character name,\n");
+ out.write(" * without the first two letters or 0 if the sequence would be empty. \n");
+ out.write(" * See Tokenizer.java.\n");
+ out.write(" * 3. the length of this sequence of characters,\n");
+ out.write(" * 4. placeholder flag (0 if argument #is not a placeholder and 1 if it is),\n");
+ out.write(" * 5. a comma-separated sequence of char16_t literals corresponding\n");
+ out.write(" * to the code-point(s) of the named character.\n");
+ out.write(" *\n");
+ out.write(" * The macro expansion doesn't have to refer to all or any of these parameters,\n");
+ out.write(" * but common sense dictates that it should involve at least one of them.\n");
+ out.write(" */\n");
+ out.write("\n");
+ out.write("// This #define allows the NAMED_CHARACTER_REFERENCE macro to accept comma-\n");
+ out.write("// separated sequences as single macro arguments. Using commas directly would\n");
+ out.write("// split the sequence into multiple macro arguments.\n");
+ out.write("#define _ ,\n");
+ out.write("\n");
+
+ int i = 0;
+ for (Map.Entry<String, String> entity : entities.entrySet()) {
+ out.write("NAMED_CHARACTER_REFERENCE(" + i++ + ", ");
+ String name = entity.getKey();
+ writeNameInitializer(out, name, " _ ");
+ out.write(", " + (name.length() - 2) + ", ");
+ out.write((name.length() == 2 ? "1" : "0") + ", ");
+ writeValueInitializer(out, entity.getValue(), " _ ");
+ out.write(")\n");
+ }
+
+ out.write("\n");
+ out.write("#undef _\n");
+
+ out.flush();
+ out.close();
+ }
+
+ private static void writeNameInitializer(Writer out,
+ String name, String separator)
+ throws IOException {
+ out.write("/* " + name.charAt(0) + " " + name.charAt(1) + " */ ");
+ if (name.length() == 2) {
+ out.write("0");
+ } else {
+ for (int i = 2; i < name.length(); i++) {
+ out.write("'" + name.charAt(i) + "'");
+ if (i < name.length() - 1)
+ out.write(separator);
+ }
+ }
+ }
+
+ private static void writeValueInitializer(Writer out,
+ String value, String separator)
+ throws IOException {
+ if (value.length() == 1) {
+ out.write(toHexString(value.charAt(0)));
+ out.write(separator);
+ out.write("0");
+ } else {
+ out.write(toHexString(value.charAt(0)));
+ out.write(separator);
+ out.write(toHexString(value.charAt(1)));
+ }
+ }
+
+ private static void defineMacroAndInclude(Writer out, String expansion,
+ String includeFile) throws IOException {
+ out.write("#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \\\n"
+ + expansion + "\n");
+ out.write("#include \"" + includeFile + "\"\n");
+ out.write("#undef NAMED_CHARACTER_REFERENCE\n");
+ }
+
+ private static void defineMacroAndInclude(Writer out, String expansion,
+ String debugExpansion, String includeFile) throws IOException {
+ out.write("#ifdef DEBUG\n");
+ out.write(" #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \\\n"
+ + debugExpansion + "\n");
+ out.write("#else\n");
+ out.write(" #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \\\n"
+ + expansion + "\n");
+ out.write("#endif\n");
+ out.write("#include \"" + includeFile + "\"\n");
+ out.write("#undef NAMED_CHARACTER_REFERENCE\n");
+ }
+
+ private static void writeStaticMemberDeclaration(Writer out,
+ CppTypes cppTypes, String type, String name) throws IOException {
+ out.write(type + " " + cppTypes.classPrefix() + "NamedCharacters::"
+ + name + ";\n");
+ }
+
+ private static int charToIndex(char c) {
+ if (c >= 'a' && c <= 'z') {
+ return c - 'a' + 26;
+ } else if (c >= 'A' && c <= 'Z') {
+ return c - 'A';
+ }
+ throw new IllegalArgumentException("Bad char in named character name: "
+ + c);
+ }
+
+ private static boolean allZero(int[] arr) {
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void generateCpp(File targetDirectory, CppTypes cppTypes,
+ Map<String, String> entities) throws IOException {
+ String includeFile = cppTypes.classPrefix()
+ + "NamedCharactersInclude.h";
+ File cppFile = new File(targetDirectory, cppTypes.classPrefix()
+ + "NamedCharacters.cpp");
+ Writer out = new OutputStreamWriter(new FileOutputStream(cppFile),
+ "utf-8");
+
+ out.write(OUTPUT_LICENSE);
+ out.write("#define " + cppTypes.classPrefix()
+ + "NamedCharacters_cpp_\n");
+
+ String[] includes = cppTypes.namedCharactersIncludes();
+ for (int i = 0; i < includes.length; i++) {
+ String include = includes[i];
+ out.write("#include \"" + include + ".h\"\n");
+ }
+
+ out.write('\n');
+ out.write("#include \"" + cppTypes.classPrefix()
+ + "NamedCharacters.h\"\n");
+ out.write("\n");
+
+ out.write("const " + cppTypes.charType() + " " + cppTypes.classPrefix()
+ + "NamedCharacters::VALUES[][2] = {\n");
+ defineMacroAndInclude(out, "{ VALUE },", includeFile);
+ // The useless terminator entry makes the above macro simpler with
+ // compilers that whine about a comma after the last item
+ out.write("{0, 0} };\n\n");
+
+ String staticMemberType = cppTypes.charType() + "**";
+ writeStaticMemberDeclaration(out, cppTypes, staticMemberType,
+ "WINDOWS_1252");
+
+ out.write("static " + cppTypes.charType()
+ + " const WINDOWS_1252_DATA[] = {\n");
+ out.write(" 0x20AC,\n");
+ out.write(" 0x0081,\n");
+ out.write(" 0x201A,\n");
+ out.write(" 0x0192,\n");
+ out.write(" 0x201E,\n");
+ out.write(" 0x2026,\n");
+ out.write(" 0x2020,\n");
+ out.write(" 0x2021,\n");
+ out.write(" 0x02C6,\n");
+ out.write(" 0x2030,\n");
+ out.write(" 0x0160,\n");
+ out.write(" 0x2039,\n");
+ out.write(" 0x0152,\n");
+ out.write(" 0x008D,\n");
+ out.write(" 0x017D,\n");
+ out.write(" 0x008F,\n");
+ out.write(" 0x0090,\n");
+ out.write(" 0x2018,\n");
+ out.write(" 0x2019,\n");
+ out.write(" 0x201C,\n");
+ out.write(" 0x201D,\n");
+ out.write(" 0x2022,\n");
+ out.write(" 0x2013,\n");
+ out.write(" 0x2014,\n");
+ out.write(" 0x02DC,\n");
+ out.write(" 0x2122,\n");
+ out.write(" 0x0161,\n");
+ out.write(" 0x203A,\n");
+ out.write(" 0x0153,\n");
+ out.write(" 0x009D,\n");
+ out.write(" 0x017E,\n");
+ out.write(" 0x0178\n");
+ out.write("};\n\n");
+
+ out.write("/**\n");
+ out.write(" * To avoid having lots of pointers in the |charData| array, below,\n");
+ out.write(" * which would cause us to have to do lots of relocations at library\n");
+ out.write(" * load time, store all the string data for the names in one big array.\n");
+ out.write(" * Then use tricks with enums to help us build an array that contains\n");
+ out.write(" * the positions of each within the big arrays.\n");
+ out.write(" */\n\n");
+
+ out.write("static const " + cppTypes.byteType() + " ALL_NAMES[] = {\n");
+
+ defineMacroAndInclude(out, "CHARS ,", includeFile);
+
+ out.write("};\n\n");
+
+ out.write("enum NamePositions {\n");
+ out.write(" DUMMY_INITIAL_NAME_POSITION = 0,\n");
+
+ out.write("/* enums don't take up space, so generate _START and _END */\n");
+ defineMacroAndInclude(out,
+ "NAME_##N##_DUMMY, /* automatically one higher than previous */ \\\n"
+ + "NAME_##N##_START = NAME_##N##_DUMMY - 1, \\\n"
+ + "NAME_##N##_END = NAME_##N##_START + LEN + FLAG,",
+ includeFile);
+
+ out.write(" DUMMY_FINAL_NAME_VALUE\n");
+ out.write("};\n\n");
+
+ String arrayLengthMacro = cppTypes.arrayLengthMacro();
+ String staticAssert = cppTypes.staticAssert();
+ if (staticAssert != null && arrayLengthMacro != null) {
+ out.write("/* check that the start positions will fit in 16 bits */\n");
+ out.write(staticAssert + "(" + arrayLengthMacro
+ + "(ALL_NAMES) < 0x10000);\n\n");
+ }
+
+ out.write("const " + cppTypes.characterNameTypeDeclaration() + " " + cppTypes.classPrefix()
+ + "NamedCharacters::NAMES[] = {\n");
+ defineMacroAndInclude(out, "{ NAME_##N##_START, LEN, },", "{ NAME_##N##_START, LEN, N },", includeFile);
+ out.write("};\n\n");
+
+ out.write(cppTypes.intType());
+ out.write("\n");
+ out.write(cppTypes.characterNameTypeDeclaration());
+ out.write("::length() const\n{\n return nameLen;\n}\n\n");
+ out.write(cppTypes.charType());
+ out.write("\n");
+ out.write(cppTypes.characterNameTypeDeclaration());
+ out.write("::charAt(");
+ out.write("int32_t");
+ out.write(" index) const\n{\n return static_cast<");
+ out.write(cppTypes.charType());
+ out.write("> (ALL_NAMES[nameStart + index]);\n}\n\n");
+
+ out.write("void\n");
+ out.write(cppTypes.classPrefix()
+ + "NamedCharacters::initializeStatics()\n");
+ out.write("{\n");
+ out.write(" WINDOWS_1252 = new " + cppTypes.charType() + "*[32];\n");
+ out.write(" for (" + cppTypes.intType() + " i = 0; i < 32; ++i) {\n");
+ out.write(" WINDOWS_1252[i] = (" + cppTypes.charType()
+ + "*)&(WINDOWS_1252_DATA[i]);\n");
+ out.write(" }\n");
+ out.write("}\n");
+ out.write("\n");
+
+ out.write("void\n");
+ out.write(cppTypes.classPrefix()
+ + "NamedCharacters::releaseStatics()\n");
+ out.write("{\n");
+ out.write(" delete[] WINDOWS_1252;\n");
+ out.write("}\n");
+ out.flush();
+ out.close();
+ }
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/DuplicatingFallThroughRemover.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/DuplicatingFallThroughRemover.java
new file mode 100644
index 000000000..b88107361
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/DuplicatingFallThroughRemover.java
@@ -0,0 +1,79 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser Rust Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.visitor.VoidVisitorAdapter;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class DuplicatingFallThroughRemover extends VoidVisitorAdapter<Object> {
+
+ private static final SwitchBreakAnalyzerVisitor ANALYZER_VISITOR = new SwitchBreakAnalyzerVisitor();
+
+ @Override public void visit(SwitchStmt sw, Object arg) {
+ if ("state".equals(sw.getSelector().toString())) {
+ super.visit(sw, arg);
+ return;
+ }
+
+ List<Statement> tail = new LinkedList<Statement>();
+ tail.add(new BreakStmt());
+
+ List<SwitchEntryStmt> entries = sw.getEntries();
+ for (int i = entries.size() - 1; i >= 0; i--) {
+ SwitchEntryStmt stmt = entries.get(i);
+ List<Statement> list = stmt.getStmts();
+ if (list != null) {
+ if (!(list.size() > 0
+ && list.get(list.size() - 1).accept(ANALYZER_VISITOR, true))) {
+ list.addAll(tail);
+ }
+ tail = list;
+ for (Statement statement : list) {
+ statement.accept(this, arg);
+ }
+ }
+ }
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/JavaVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/JavaVisitor.java
new file mode 100644
index 000000000..97ded525f
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/JavaVisitor.java
@@ -0,0 +1,1349 @@
+/*
+ * Copyright (C) 2007 Júlio Vilmar Gesser.
+ * Copyright (C) 2012 Mozilla Foundation
+ *
+ * This file is part of Java 1.5 parser and Abstract Syntax Tree.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 05/10/2006
+ */
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.ast.BlockComment;
+import japa.parser.ast.CompilationUnit;
+import japa.parser.ast.ImportDeclaration;
+import japa.parser.ast.LineComment;
+import japa.parser.ast.PackageDeclaration;
+import japa.parser.ast.TypeParameter;
+import japa.parser.ast.body.AnnotationDeclaration;
+import japa.parser.ast.body.AnnotationMemberDeclaration;
+import japa.parser.ast.body.BodyDeclaration;
+import japa.parser.ast.body.ClassOrInterfaceDeclaration;
+import japa.parser.ast.body.ConstructorDeclaration;
+import japa.parser.ast.body.EmptyMemberDeclaration;
+import japa.parser.ast.body.EmptyTypeDeclaration;
+import japa.parser.ast.body.EnumConstantDeclaration;
+import japa.parser.ast.body.EnumDeclaration;
+import japa.parser.ast.body.FieldDeclaration;
+import japa.parser.ast.body.InitializerDeclaration;
+import japa.parser.ast.body.JavadocComment;
+import japa.parser.ast.body.MethodDeclaration;
+import japa.parser.ast.body.ModifierSet;
+import japa.parser.ast.body.Parameter;
+import japa.parser.ast.body.TypeDeclaration;
+import japa.parser.ast.body.VariableDeclarator;
+import japa.parser.ast.body.VariableDeclaratorId;
+import japa.parser.ast.expr.AnnotationExpr;
+import japa.parser.ast.expr.ArrayAccessExpr;
+import japa.parser.ast.expr.ArrayCreationExpr;
+import japa.parser.ast.expr.ArrayInitializerExpr;
+import japa.parser.ast.expr.AssignExpr;
+import japa.parser.ast.expr.BinaryExpr;
+import japa.parser.ast.expr.BooleanLiteralExpr;
+import japa.parser.ast.expr.CastExpr;
+import japa.parser.ast.expr.CharLiteralExpr;
+import japa.parser.ast.expr.ClassExpr;
+import japa.parser.ast.expr.ConditionalExpr;
+import japa.parser.ast.expr.DoubleLiteralExpr;
+import japa.parser.ast.expr.EnclosedExpr;
+import japa.parser.ast.expr.Expression;
+import japa.parser.ast.expr.FieldAccessExpr;
+import japa.parser.ast.expr.InstanceOfExpr;
+import japa.parser.ast.expr.IntegerLiteralExpr;
+import japa.parser.ast.expr.IntegerLiteralMinValueExpr;
+import japa.parser.ast.expr.LongLiteralExpr;
+import japa.parser.ast.expr.LongLiteralMinValueExpr;
+import japa.parser.ast.expr.MarkerAnnotationExpr;
+import japa.parser.ast.expr.MemberValuePair;
+import japa.parser.ast.expr.MethodCallExpr;
+import japa.parser.ast.expr.NameExpr;
+import japa.parser.ast.expr.NormalAnnotationExpr;
+import japa.parser.ast.expr.NullLiteralExpr;
+import japa.parser.ast.expr.ObjectCreationExpr;
+import japa.parser.ast.expr.QualifiedNameExpr;
+import japa.parser.ast.expr.SingleMemberAnnotationExpr;
+import japa.parser.ast.expr.StringLiteralExpr;
+import japa.parser.ast.expr.SuperExpr;
+import japa.parser.ast.expr.ThisExpr;
+import japa.parser.ast.expr.UnaryExpr;
+import japa.parser.ast.expr.VariableDeclarationExpr;
+import japa.parser.ast.stmt.AssertStmt;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.CatchClause;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.stmt.DoStmt;
+import japa.parser.ast.stmt.EmptyStmt;
+import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.ForStmt;
+import japa.parser.ast.stmt.ForeachStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.LabeledStmt;
+import japa.parser.ast.stmt.ReturnStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.stmt.SynchronizedStmt;
+import japa.parser.ast.stmt.ThrowStmt;
+import japa.parser.ast.stmt.TryStmt;
+import japa.parser.ast.stmt.TypeDeclarationStmt;
+import japa.parser.ast.stmt.WhileStmt;
+import japa.parser.ast.type.ClassOrInterfaceType;
+import japa.parser.ast.type.PrimitiveType;
+import japa.parser.ast.type.ReferenceType;
+import japa.parser.ast.type.Type;
+import japa.parser.ast.type.VoidType;
+import japa.parser.ast.type.WildcardType;
+import japa.parser.ast.visitor.VoidVisitor;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+
+public final class JavaVisitor implements VoidVisitor<Object> {
+
+ private static class SourcePrinter {
+
+ private int level = 0;
+
+ private boolean indented = false;
+
+ private final StringBuilder buf = new StringBuilder();
+
+ public void indent() {
+ level++;
+ }
+
+ public void unindent() {
+ level--;
+ }
+
+ private void makeIndent() {
+ for (int i = 0; i < level; i++) {
+ buf.append(" ");
+ }
+ }
+
+ public void print(String arg) {
+ if (!indented) {
+ makeIndent();
+ indented = true;
+ }
+ buf.append(arg);
+ }
+
+ public void printLn(String arg) {
+ print(arg);
+ printLn();
+ }
+
+ public void printLn() {
+ buf.append("\n");
+ indented = false;
+ }
+
+ public String getSource() {
+ return buf.toString();
+ }
+
+ @Override
+ public String toString() {
+ return getSource();
+ }
+ }
+
+ private final SourcePrinter printer = new SourcePrinter();
+
+ public String getSource() {
+ return printer.getSource();
+ }
+
+ private void printModifiers(int modifiers) {
+ if (ModifierSet.isPrivate(modifiers)) {
+ printer.print("private ");
+ }
+ if (ModifierSet.isProtected(modifiers)) {
+ printer.print("protected ");
+ }
+ if (ModifierSet.isPublic(modifiers)) {
+ printer.print("public ");
+ }
+ if (ModifierSet.isAbstract(modifiers)) {
+ printer.print("abstract ");
+ }
+ if (ModifierSet.isStatic(modifiers)) {
+ printer.print("static ");
+ }
+ if (ModifierSet.isFinal(modifiers)) {
+ printer.print("final ");
+ }
+ if (ModifierSet.isNative(modifiers)) {
+ printer.print("native ");
+ }
+ if (ModifierSet.isStrictfp(modifiers)) {
+ printer.print("strictfp ");
+ }
+ if (ModifierSet.isSynchronized(modifiers)) {
+ printer.print("synchronized ");
+ }
+ if (ModifierSet.isTransient(modifiers)) {
+ printer.print("transient ");
+ }
+ if (ModifierSet.isVolatile(modifiers)) {
+ printer.print("volatile ");
+ }
+ }
+
+ private void printMembers(List<BodyDeclaration> members, Object arg) {
+ for (BodyDeclaration member : members) {
+ printer.printLn();
+ member.accept(this, arg);
+ printer.printLn();
+ }
+ }
+
+ private void printMemberAnnotations(List<AnnotationExpr> annotations, Object arg) {
+ if (annotations != null) {
+ for (AnnotationExpr a : annotations) {
+ a.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ }
+
+ private void printAnnotations(List<AnnotationExpr> annotations, Object arg) {
+ if (annotations != null) {
+ for (AnnotationExpr a : annotations) {
+ a.accept(this, arg);
+ printer.print(" ");
+ }
+ }
+ }
+
+ private void printTypeArgs(List<Type> args, Object arg) {
+ if (args != null) {
+ printer.print("<");
+ for (Iterator<Type> i = args.iterator(); i.hasNext();) {
+ Type t = i.next();
+ t.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(">");
+ }
+ }
+
+ private void printTypeParameters(List<TypeParameter> args, Object arg) {
+ if (args != null) {
+ printer.print("<");
+ for (Iterator<TypeParameter> i = args.iterator(); i.hasNext();) {
+ TypeParameter t = i.next();
+ t.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(">");
+ }
+ }
+
+ private void printArguments(List<Expression> args, Object arg) {
+ printer.print("(");
+ if (args != null) {
+ for (Iterator<Expression> i = args.iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ }
+
+ private void printJavadoc(JavadocComment javadoc, Object arg) {
+ if (javadoc != null) {
+ javadoc.accept(this, arg);
+ }
+ }
+
+ public void visit(CompilationUnit n, Object arg) {
+ if (n.getPackage() != null) {
+ n.getPackage().accept(this, arg);
+ }
+ if (n.getImports() != null) {
+ for (ImportDeclaration i : n.getImports()) {
+ i.accept(this, arg);
+ }
+ printer.printLn();
+ }
+ if (n.getTypes() != null) {
+ for (Iterator<TypeDeclaration> i = n.getTypes().iterator(); i.hasNext();) {
+ i.next().accept(this, arg);
+ printer.printLn();
+ if (i.hasNext()) {
+ printer.printLn();
+ }
+ }
+ }
+ }
+
+ public void visit(PackageDeclaration n, Object arg) {
+ printAnnotations(n.getAnnotations(), arg);
+ printer.print("package ");
+ n.getName().accept(this, arg);
+ printer.printLn(";");
+ printer.printLn();
+ }
+
+ public void visit(NameExpr n, Object arg) {
+ printer.print(n.getName());
+ }
+
+ public void visit(QualifiedNameExpr n, Object arg) {
+ n.getQualifier().accept(this, arg);
+ printer.print(".");
+ printer.print(n.getName());
+ }
+
+ public void visit(ImportDeclaration n, Object arg) {
+ printer.print("import ");
+ if (n.isStatic()) {
+ printer.print("static ");
+ }
+ n.getName().accept(this, arg);
+ if (n.isAsterisk()) {
+ printer.print(".*");
+ }
+ printer.printLn(";");
+ }
+
+ public void visit(ClassOrInterfaceDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ if (n.isInterface()) {
+ printer.print("interface ");
+ } else {
+ printer.print("class ");
+ }
+
+ printer.print(n.getName());
+
+ printTypeParameters(n.getTypeParameters(), arg);
+
+ if (n.getExtends() != null) {
+ printer.print(" extends ");
+ for (Iterator<ClassOrInterfaceType> i = n.getExtends().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ if (n.getImplements() != null) {
+ printer.print(" implements ");
+ for (Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getMembers() != null) {
+ printMembers(n.getMembers(), arg);
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+
+ public void visit(EmptyTypeDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printer.print(";");
+ }
+
+ public void visit(JavadocComment n, Object arg) {
+ printer.print("/**");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+ public void visit(ClassOrInterfaceType n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print(n.getName());
+ printTypeArgs(n.getTypeArgs(), arg);
+ }
+
+ public void visit(TypeParameter n, Object arg) {
+ printer.print(n.getName());
+ if (n.getTypeBound() != null) {
+ printer.print(" extends ");
+ for (Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(" & ");
+ }
+ }
+ }
+ }
+
+ public void visit(PrimitiveType n, Object arg) {
+ switch (n.getType()) {
+ case Boolean:
+ printer.print("boolean");
+ break;
+ case Byte:
+ printer.print("byte");
+ break;
+ case Char:
+ printer.print("char");
+ break;
+ case Double:
+ printer.print("double");
+ break;
+ case Float:
+ printer.print("float");
+ break;
+ case Int:
+ printer.print("int");
+ break;
+ case Long:
+ printer.print("long");
+ break;
+ case Short:
+ printer.print("short");
+ break;
+ }
+ }
+
+ public void visit(ReferenceType n, Object arg) {
+ n.getType().accept(this, arg);
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ }
+
+ public void visit(WildcardType n, Object arg) {
+ printer.print("?");
+ if (n.getExtends() != null) {
+ printer.print(" extends ");
+ n.getExtends().accept(this, arg);
+ }
+ if (n.getSuper() != null) {
+ printer.print(" super ");
+ n.getSuper().accept(this, arg);
+ }
+ }
+
+ public void visit(FieldDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+ n.getType().accept(this, arg);
+
+ printer.print(" ");
+ for (Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext();) {
+ VariableDeclarator var = i.next();
+ var.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+
+ printer.print(";");
+ }
+
+ public void visit(VariableDeclarator n, Object arg) {
+ n.getId().accept(this, arg);
+ if (n.getInit() != null) {
+ printer.print(" = ");
+ n.getInit().accept(this, arg);
+ }
+ }
+
+ public void visit(VariableDeclaratorId n, Object arg) {
+ printer.print(n.getName());
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ }
+
+ public void visit(ArrayInitializerExpr n, Object arg) {
+ printer.print("{");
+ if (n.getValues() != null) {
+ printer.print(" ");
+ for (Iterator<Expression> i = n.getValues().iterator(); i.hasNext();) {
+ Expression expr = i.next();
+ expr.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(" ");
+ }
+ printer.print("}");
+ }
+
+ public void visit(VoidType n, Object arg) {
+ printer.print("void");
+ }
+
+ public void visit(ArrayAccessExpr n, Object arg) {
+ n.getName().accept(this, arg);
+ printer.print("[");
+ n.getIndex().accept(this, arg);
+ printer.print("]");
+ }
+
+ public void visit(ArrayCreationExpr n, Object arg) {
+ printer.print("new ");
+ n.getType().accept(this, arg);
+
+ if (n.getDimensions() != null) {
+ for (Expression dim : n.getDimensions()) {
+ printer.print("[");
+ dim.accept(this, arg);
+ printer.print("]");
+ }
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ } else {
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ printer.print(" ");
+ n.getInitializer().accept(this, arg);
+ }
+ }
+
+ public void visit(AssignExpr n, Object arg) {
+ n.getTarget().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case assign:
+ printer.print("=");
+ break;
+ case and:
+ printer.print("&=");
+ break;
+ case or:
+ printer.print("|=");
+ break;
+ case xor:
+ printer.print("^=");
+ break;
+ case plus:
+ printer.print("+=");
+ break;
+ case minus:
+ printer.print("-=");
+ break;
+ case rem:
+ printer.print("%=");
+ break;
+ case slash:
+ printer.print("/=");
+ break;
+ case star:
+ printer.print("*=");
+ break;
+ case lShift:
+ printer.print("<<=");
+ break;
+ case rSignedShift:
+ printer.print(">>=");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>=");
+ break;
+ }
+ printer.print(" ");
+ n.getValue().accept(this, arg);
+ }
+
+ public void visit(BinaryExpr n, Object arg) {
+ n.getLeft().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case or:
+ printer.print("||");
+ break;
+ case and:
+ printer.print("&&");
+ break;
+ case binOr:
+ printer.print("|");
+ break;
+ case binAnd:
+ printer.print("&");
+ break;
+ case xor:
+ printer.print("^");
+ break;
+ case equals:
+ printer.print("==");
+ break;
+ case notEquals:
+ printer.print("!=");
+ break;
+ case less:
+ printer.print("<");
+ break;
+ case greater:
+ printer.print(">");
+ break;
+ case lessEquals:
+ printer.print("<=");
+ break;
+ case greaterEquals:
+ printer.print(">=");
+ break;
+ case lShift:
+ printer.print("<<");
+ break;
+ case rSignedShift:
+ printer.print(">>");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>");
+ break;
+ case plus:
+ printer.print("+");
+ break;
+ case minus:
+ printer.print("-");
+ break;
+ case times:
+ printer.print("*");
+ break;
+ case divide:
+ printer.print("/");
+ break;
+ case remainder:
+ printer.print("%");
+ break;
+ }
+ printer.print(" ");
+ n.getRight().accept(this, arg);
+ }
+
+ public void visit(CastExpr n, Object arg) {
+ printer.print("(");
+ n.getType().accept(this, arg);
+ printer.print(") ");
+ n.getExpr().accept(this, arg);
+ }
+
+ public void visit(ClassExpr n, Object arg) {
+ n.getType().accept(this, arg);
+ printer.print(".class");
+ }
+
+ public void visit(ConditionalExpr n, Object arg) {
+ n.getCondition().accept(this, arg);
+ printer.print(" ? ");
+ n.getThenExpr().accept(this, arg);
+ printer.print(" : ");
+ n.getElseExpr().accept(this, arg);
+ }
+
+ public void visit(EnclosedExpr n, Object arg) {
+ printer.print("(");
+ n.getInner().accept(this, arg);
+ printer.print(")");
+ }
+
+ public void visit(FieldAccessExpr n, Object arg) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ printer.print(n.getField());
+ }
+
+ public void visit(InstanceOfExpr n, Object arg) {
+ n.getExpr().accept(this, arg);
+ printer.print(" instanceof ");
+ n.getType().accept(this, arg);
+ }
+
+ public void visit(CharLiteralExpr n, Object arg) {
+ printer.print("'");
+ char c = n.getValue().charAt(0);
+ switch (c) {
+ case '\b':
+ printer.print("\\b");
+ break;
+ case '\t':
+ printer.print("\\t");
+ break;
+ case '\n':
+ printer.print("\\n");
+ break;
+ case '\f':
+ printer.print("\\f");
+ break;
+ case '\r':
+ printer.print("\\r");
+ break;
+ case '\'':
+ printer.print("\\'");
+ break;
+ case '\\':
+ printer.print(n.getValue());
+ break;
+ default:
+ if (c < ' ' || c > '~') {
+ String hex = Integer.toHexString(c);
+ switch (hex.length()) {
+ case 1:
+ printer.print("\\u000"+hex);
+ break;
+ case 2:
+ printer.print("\\u00"+hex);
+ break;
+ case 3:
+ printer.print("\\u0"+hex);
+ break;
+ case 4:
+ printer.print("\\u"+hex);
+ break;
+ }
+ } else {
+ printer.print(""+c);
+ }
+ break;
+ }
+ printer.print("'");
+ }
+
+ public void visit(DoubleLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralMinValueExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralMinValueExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(StringLiteralExpr n, Object arg) {
+ printer.print("\"");
+ printer.print(n.getValue());
+ printer.print("\"");
+ }
+
+ public void visit(BooleanLiteralExpr n, Object arg) {
+ printer.print(String.valueOf(n.getValue()));
+ }
+
+ public void visit(NullLiteralExpr n, Object arg) {
+ printer.print("null");
+ }
+
+ public void visit(ThisExpr n, Object arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("this");
+ }
+
+ public void visit(SuperExpr n, Object arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("super");
+ }
+
+ public void visit(MethodCallExpr n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print(n.getName());
+ printArguments(n.getArgs(), arg);
+ }
+
+ public void visit(ObjectCreationExpr n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+
+ printer.print("new ");
+
+ printTypeArgs(n.getTypeArgs(), arg);
+ n.getType().accept(this, arg);
+
+ printArguments(n.getArgs(), arg);
+
+ if (n.getAnonymousClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMembers(n.getAnonymousClassBody(), arg);
+ printer.unindent();
+ printer.print("}");
+ }
+ }
+
+ public void visit(UnaryExpr n, Object arg) {
+ switch (n.getOperator()) {
+ case positive:
+ printer.print("+");
+ break;
+ case negative:
+ printer.print("-");
+ break;
+ case inverse:
+ printer.print("~");
+ break;
+ case not:
+ printer.print("!");
+ break;
+ case preIncrement:
+ printer.print("++");
+ break;
+ case preDecrement:
+ printer.print("--");
+ break;
+ }
+
+ n.getExpr().accept(this, arg);
+
+ switch (n.getOperator()) {
+ case posIncrement:
+ printer.print("++");
+ break;
+ case posDecrement:
+ printer.print("--");
+ break;
+ }
+ }
+
+ public void visit(ConstructorDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ printTypeParameters(n.getTypeParameters(), arg);
+ if (n.getTypeParameters() != null) {
+ printer.print(" ");
+ }
+ printer.print(n.getName());
+
+ printer.print("(");
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ if (n.getThrows() != null) {
+ printer.print(" throws ");
+ for (Iterator<NameExpr> i = n.getThrows().iterator(); i.hasNext();) {
+ NameExpr name = i.next();
+ name.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(" ");
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(MethodDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ printTypeParameters(n.getTypeParameters(), arg);
+ if (n.getTypeParameters() != null) {
+ printer.print(" ");
+ }
+
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(n.getName());
+
+ printer.print("(");
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+
+ if (n.getThrows() != null) {
+ printer.print(" throws ");
+ for (Iterator<NameExpr> i = n.getThrows().iterator(); i.hasNext();) {
+ NameExpr name = i.next();
+ name.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ if (n.getBody() == null) {
+ printer.print(";");
+ } else {
+ printer.print(" ");
+ n.getBody().accept(this, arg);
+ }
+ }
+
+ public void visit(Parameter n, Object arg) {
+ printAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ n.getType().accept(this, arg);
+ if (n.isVarArgs()) {
+ printer.print("...");
+ }
+ printer.print(" ");
+ n.getId().accept(this, arg);
+ }
+
+ public void visit(ExplicitConstructorInvocationStmt n, Object arg) {
+ if (n.isThis()) {
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print("this");
+ } else {
+ if (n.getExpr() != null) {
+ n.getExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printTypeArgs(n.getTypeArgs(), arg);
+ printer.print("super");
+ }
+ printArguments(n.getArgs(), arg);
+ printer.print(";");
+ }
+
+ public void visit(VariableDeclarationExpr n, Object arg) {
+ printAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ n.getType().accept(this, arg);
+ printer.print(" ");
+
+ for (Iterator<VariableDeclarator> i = n.getVars().iterator(); i.hasNext();) {
+ VariableDeclarator v = i.next();
+ v.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ public void visit(TypeDeclarationStmt n, Object arg) {
+ n.getTypeDeclaration().accept(this, arg);
+ }
+
+ public void visit(AssertStmt n, Object arg) {
+ printer.print("assert ");
+ n.getCheck().accept(this, arg);
+ if (n.getMessage() != null) {
+ printer.print(" : ");
+ n.getMessage().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(BlockStmt n, Object arg) {
+ printer.printLn("{");
+ if (n.getStmts() != null) {
+ printer.indent();
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+
+ }
+
+ public void visit(LabeledStmt n, Object arg) {
+ printer.print(n.getLabel());
+ printer.print(": ");
+ n.getStmt().accept(this, arg);
+ }
+
+ public void visit(EmptyStmt n, Object arg) {
+ printer.print(";");
+ }
+
+ public void visit(ExpressionStmt n, Object arg) {
+ n.getExpression().accept(this, arg);
+ printer.print(";");
+ }
+
+ public void visit(SwitchStmt n, Object arg) {
+ printer.print("switch(");
+ n.getSelector().accept(this, arg);
+ printer.printLn(") {");
+ if (n.getEntries() != null) {
+ printer.indent();
+ for (SwitchEntryStmt e : n.getEntries()) {
+ e.accept(this, arg);
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+
+ }
+
+ public void visit(SwitchEntryStmt n, Object arg) {
+ if (n.getLabel() != null) {
+ printer.print("case ");
+ n.getLabel().accept(this, arg);
+ printer.print(":");
+ } else {
+ printer.print("default:");
+ }
+ printer.printLn();
+ printer.indent();
+ if (n.getStmts() != null) {
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ printer.unindent();
+ }
+
+ public void visit(BreakStmt n, Object arg) {
+ printer.print("break");
+ if (n.getId() != null) {
+ printer.print(" ");
+ printer.print(n.getId());
+ }
+ printer.print(";");
+ }
+
+ public void visit(ReturnStmt n, Object arg) {
+ printer.print("return");
+ if (n.getExpr() != null) {
+ printer.print(" ");
+ n.getExpr().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(EnumDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ printer.print("enum ");
+ printer.print(n.getName());
+
+ if (n.getImplements() != null) {
+ printer.print(" implements ");
+ for (Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getEntries() != null) {
+ printer.printLn();
+ for (Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext();) {
+ EnumConstantDeclaration e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ if (n.getMembers() != null) {
+ printer.printLn(";");
+ printMembers(n.getMembers(), arg);
+ } else {
+ if (n.getEntries() != null) {
+ printer.printLn();
+ }
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+
+ public void visit(EnumConstantDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printer.print(n.getName());
+
+ if (n.getArgs() != null) {
+ printArguments(n.getArgs(), arg);
+ }
+
+ if (n.getClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMembers(n.getClassBody(), arg);
+ printer.unindent();
+ printer.printLn("}");
+ }
+ }
+
+ public void visit(EmptyMemberDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printer.print(";");
+ }
+
+ public void visit(InitializerDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ if (n.isStatic()) {
+ printer.print("static ");
+ }
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(IfStmt n, Object arg) {
+ printer.print("if (");
+ n.getCondition().accept(this, arg);
+ printer.print(") ");
+ n.getThenStmt().accept(this, arg);
+ if (n.getElseStmt() != null) {
+ printer.print(" else ");
+ n.getElseStmt().accept(this, arg);
+ }
+ }
+
+ public void visit(WhileStmt n, Object arg) {
+ printer.print("while (");
+ n.getCondition().accept(this, arg);
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ContinueStmt n, Object arg) {
+ printer.print("continue");
+ if (n.getId() != null) {
+ printer.print(" ");
+ printer.print(n.getId());
+ }
+ printer.print(";");
+ }
+
+ public void visit(DoStmt n, Object arg) {
+ printer.print("do ");
+ n.getBody().accept(this, arg);
+ printer.print(" while (");
+ n.getCondition().accept(this, arg);
+ printer.print(");");
+ }
+
+ public void visit(ForeachStmt n, Object arg) {
+ printer.print("for (");
+ n.getVariable().accept(this, arg);
+ printer.print(" : ");
+ n.getIterable().accept(this, arg);
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ForStmt n, Object arg) {
+ printer.print("for (");
+ if (n.getInit() != null) {
+ for (Iterator<Expression> i = n.getInit().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print("; ");
+ if (n.getCompare() != null) {
+ n.getCompare().accept(this, arg);
+ }
+ printer.print("; ");
+ if (n.getUpdate() != null) {
+ for (Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ThrowStmt n, Object arg) {
+ printer.print("throw ");
+ n.getExpr().accept(this, arg);
+ printer.print(";");
+ }
+
+ public void visit(SynchronizedStmt n, Object arg) {
+ printer.print("synchronized (");
+ n.getExpr().accept(this, arg);
+ printer.print(") ");
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(TryStmt n, Object arg) {
+ printer.print("try ");
+ n.getTryBlock().accept(this, arg);
+ if (n.getCatchs() != null) {
+ for (CatchClause c : n.getCatchs()) {
+ c.accept(this, arg);
+ }
+ }
+ if (n.getFinallyBlock() != null) {
+ printer.print(" finally ");
+ n.getFinallyBlock().accept(this, arg);
+ }
+ }
+
+ public void visit(CatchClause n, Object arg) {
+ printer.print(" catch (");
+ n.getExcept().accept(this, arg);
+ printer.print(") ");
+ n.getCatchBlock().accept(this, arg);
+
+ }
+
+ public void visit(AnnotationDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ printer.print("@interface ");
+ printer.print(n.getName());
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getMembers() != null) {
+ printMembers(n.getMembers(), arg);
+ }
+ printer.unindent();
+ printer.print("}");
+ }
+
+ public void visit(AnnotationMemberDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ n.getType().accept(this, arg);
+ printer.print(" ");
+ printer.print(n.getName());
+ printer.print("()");
+ if (n.getDefaultValue() != null) {
+ printer.print(" default ");
+ n.getDefaultValue().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(MarkerAnnotationExpr n, Object arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ }
+
+ public void visit(SingleMemberAnnotationExpr n, Object arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ printer.print("(");
+ n.getMemberValue().accept(this, arg);
+ printer.print(")");
+ }
+
+ public void visit(NormalAnnotationExpr n, Object arg) {
+ printer.print("@");
+ n.getName().accept(this, arg);
+ printer.print("(");
+ if (n.getPairs() != null) {
+ for (Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext();) {
+ MemberValuePair m = i.next();
+ m.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ }
+
+ public void visit(MemberValuePair n, Object arg) {
+ printer.print(n.getName());
+ printer.print(" = ");
+ n.getValue().accept(this, arg);
+ }
+
+ public void visit(LineComment n, Object arg) {
+ printer.print("//");
+ printer.printLn(n.getContent());
+ }
+
+ public void visit(BlockComment n, Object arg) {
+ printer.print("/*");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+} \ No newline at end of file
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/LoopBreakAnalyzerVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/LoopBreakAnalyzerVisitor.java
new file mode 100644
index 000000000..384716e0b
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/LoopBreakAnalyzerVisitor.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2008 Júlio Vilmar Gesser.
+ * Copyright (C) 2012 Mozilla Foundation
+ *
+ * This file is part of Java 1.5 parser and Abstract Syntax Tree.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 09/06/2008
+ */
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.ast.stmt.AssertStmt;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.CatchClause;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.stmt.DoStmt;
+import japa.parser.ast.stmt.EmptyStmt;
+import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.ForStmt;
+import japa.parser.ast.stmt.ForeachStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.LabeledStmt;
+import japa.parser.ast.stmt.ReturnStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.stmt.SynchronizedStmt;
+import japa.parser.ast.stmt.ThrowStmt;
+import japa.parser.ast.stmt.TryStmt;
+import japa.parser.ast.stmt.TypeDeclarationStmt;
+import japa.parser.ast.stmt.WhileStmt;
+import japa.parser.ast.type.WildcardType;
+import japa.parser.ast.visitor.GenericVisitorAdapter;
+
+import java.util.List;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+public class LoopBreakAnalyzerVisitor extends GenericVisitorAdapter<Boolean, Boolean> {
+
+ public Boolean visit(AssertStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(BlockStmt n, Boolean arg) {
+ for (Statement stmt : n.getStmts()) {
+ if (stmt.accept(this, arg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Boolean visit(BreakStmt n, Boolean arg) {
+ return n.getId() != null;
+ }
+
+ public Boolean visit(CatchClause n, Boolean arg) {
+ return n.getCatchBlock().accept(this, arg);
+ }
+
+ public Boolean visit(ContinueStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(DoStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(EmptyStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ExplicitConstructorInvocationStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ExpressionStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ForeachStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(ForStmt n, Boolean arg) {
+ //bogus
+ return false;
+ }
+
+ public Boolean visit(IfStmt n, Boolean arg) {
+ if (n.getElseStmt() != null) {
+ if (n.getElseStmt().accept(this, arg)) {
+ return true;
+ }
+ }
+ if (n.getThenStmt().accept(this, arg)) {
+ return true;
+ }
+ return false;
+ }
+
+ public Boolean visit(LabeledStmt n, Boolean arg) {
+ return n.getStmt().accept(this, arg);
+ }
+
+ public Boolean visit(ReturnStmt n, Boolean arg) {
+ return true;
+ }
+
+ public Boolean visit(SwitchEntryStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(SwitchStmt n, Boolean arg) {
+ /*
+ List<SwitchEntryStmt> entries = n.getEntries();
+ for (int i = 0; i < array.length; i++) {
+ array_type array_element = array[i];
+
+ }
+ */
+ return true;
+ }
+
+ public Boolean visit(SynchronizedStmt n, Boolean arg) {
+ return n.getBlock().accept(this, arg);
+ }
+
+ public Boolean visit(ThrowStmt n, Boolean arg) {
+ return true;
+ }
+
+ public Boolean visit(TryStmt n, Boolean arg) {
+ if (n.getFinallyBlock() != null) {
+ return n.getFinallyBlock().accept(this, arg);
+ }
+ if (n.getCatchs() != null) {
+ for (CatchClause c : n.getCatchs()) {
+ boolean brk = c.accept(this, arg);
+ if (!brk) {
+ return false;
+ }
+ }
+ }
+ return n.getTryBlock().accept(this, arg);
+ }
+
+ public Boolean visit(TypeDeclarationStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(WhileStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(WildcardType n, Boolean arg) {
+ if (n.getExtends() != null) {
+ n.getExtends().accept(this, arg);
+ }
+ if (n.getSuper() != null) {
+ n.getSuper().accept(this, arg);
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/Main.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/Main.java
new file mode 100644
index 000000000..4e1b0a7dd
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/Main.java
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML Parser Rust Translator code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.JavaParser;
+import japa.parser.ParseException;
+import japa.parser.ast.CompilationUnit;
+import japa.parser.ast.visitor.DumpVisitor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import nu.validator.htmlparser.cpptranslate.CppOnlyInputStream;
+import nu.validator.htmlparser.cpptranslate.LicenseExtractor;
+import nu.validator.htmlparser.cpptranslate.NoCppInputStream;
+
+public class Main {
+
+ private static final String[] CLASSLIST = {
+ "Tokenizer",
+ "TreeBuilder",
+ "MetaScanner",
+ "AttributeName",
+ "ElementName",
+ "HtmlAttributes",
+ "StackNode",
+ "UTF16Buffer",
+ "StateSnapshot",
+ };
+
+ /**
+ * @param args
+ * @throws ParseException
+ * @throws IOException
+ */
+ public static void main(String[] args) throws ParseException, IOException {
+ File javaDirectory = new File(args[0]);
+ File targetDirectory = new File(args[1]);
+
+ for (int i = 0; i < CLASSLIST.length; i++) {
+ parseFile(javaDirectory, targetDirectory, CLASSLIST[i], ".java");
+ }
+ }
+
+ private static void parseFile(File javaDirectory,
+ File targetDirectory, String className, String fne)
+ throws FileNotFoundException, UnsupportedEncodingException,
+ IOException {
+ File file = null;
+// try {
+// file = new File(javaDirectory, className + ".java");
+// String license = new LicenseExtractor(file).extract();
+// CompilationUnit cu = JavaParser.parse(new FileInputStream(file), "utf-8");
+//
+// ModeFallThroughRemover mftr = new ModeFallThroughRemover();
+// cu.accept(mftr, null);
+//
+// DuplicatingFallThroughRemover dftr = new DuplicatingFallThroughRemover();
+// cu.accept(dftr, null);
+//
+// JavaVisitor visitor = new JavaVisitor();
+// cu.accept(visitor, null);
+// FileOutputStream out = new FileOutputStream(new File(targetDirectory,
+// className + fne));
+// OutputStreamWriter w = new OutputStreamWriter(out, "utf-8");
+// w.write(license);
+// w.write("\n\n/*\n * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.\n * Please edit "
+// + className + ".java instead and regenerate.\n */\n\n");
+// w.write(visitor.getSource());
+// w.close();
+// } catch (ParseException e) {
+// System.err.println(file);
+// e.printStackTrace();
+// }
+ try {
+ file = new File(javaDirectory, className + ".java");
+ String license = new LicenseExtractor(file).extract();
+ CompilationUnit cu = JavaParser.parse(new NoCppInputStream(
+ new CppOnlyInputStream(new FileInputStream(file))), "utf-8");
+
+ ModeFallThroughRemover mftr = new ModeFallThroughRemover();
+ cu.accept(mftr, null);
+
+ DuplicatingFallThroughRemover dftr = new DuplicatingFallThroughRemover();
+ cu.accept(dftr, null);
+
+ RustVisitor visitor = new RustVisitor();
+ cu.accept(visitor, null);
+ FileOutputStream out = new FileOutputStream(new File(targetDirectory,
+ className + ".rs"));
+ OutputStreamWriter w = new OutputStreamWriter(out, "utf-8");
+ w.write(license);
+ w.write("\n\n/*\n * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.\n * Please edit "
+ + className + ".java instead and regenerate.\n */\n\n");
+ w.write(visitor.getSource());
+ w.close();
+ } catch (ParseException e) {
+ System.err.println(file);
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/ModeFallThroughRemover.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/ModeFallThroughRemover.java
new file mode 100644
index 000000000..a89926748
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/ModeFallThroughRemover.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 Júlio Vilmar Gesser.
+ * Copyright (C) 2012 Mozilla Foundation
+ *
+ * This file is part of Java 1.5 parser and Abstract Syntax Tree.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 09/06/2008
+ */
+package nu.validator.htmlparser.rusttranslate;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import japa.parser.ast.body.MethodDeclaration;
+import japa.parser.ast.expr.BinaryExpr;
+import japa.parser.ast.expr.BinaryExpr.Operator;
+import japa.parser.ast.expr.Expression;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.visitor.VoidVisitorAdapter;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+public class ModeFallThroughRemover extends VoidVisitorAdapter<Object> {
+
+ private String method;
+
+ public void visit(BlockStmt n, Object arg) {
+ if (!("startTag".equals(method) || "endTag".equals(method))) {
+ super.visit(n, arg);
+ return;
+ }
+ List<Statement> list = n.getStmts();
+ if (list != null) {
+ for (int i = 0; i < list.size(); i++) {
+ Statement s = list.get(i);
+ if (s instanceof SwitchStmt) {
+ SwitchStmt sw = (SwitchStmt) s;
+ if ("mode".equals(sw.getSelector().toString())) {
+ list.remove(i);
+ int j = 0;
+ for (SwitchEntryStmt entry : sw.getEntries()) {
+ List<Statement> statements = entry.getStmts();
+ if (statements == null) {
+ continue;
+ }
+ Statement last = statements.get(statements.size() - 1);
+ if (last instanceof BreakStmt) {
+ BreakStmt brk = (BreakStmt) last;
+ if (brk.getId() == null) {
+ statements.remove(last);
+ }
+ }
+ Statement stm;
+ Expression label = entry.getLabel();
+ if (label == null) {
+ stm = new BlockStmt(statements);
+ } else {
+ Expression lte = new BinaryExpr(
+ sw.getSelector(), label,
+ Operator.lessEquals);
+ stm = new IfStmt(lte,
+ new BlockStmt(statements), null);
+ }
+ list.add(i + j, stm);
+ j++;
+ }
+ } else {
+ s.accept(this, arg);
+ }
+ } else {
+ s.accept(this, arg);
+ }
+ }
+ }
+ }
+
+ /**
+ * @see japa.parser.ast.visitor.VoidVisitorAdapter#visit(japa.parser.ast.body.MethodDeclaration, java.lang.Object)
+ */
+ @Override public void visit(MethodDeclaration md, Object arg) {
+ method = md.getName();
+ super.visit(md, arg);
+ }
+
+} \ No newline at end of file
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/RustVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/RustVisitor.java
new file mode 100644
index 000000000..36feced04
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/RustVisitor.java
@@ -0,0 +1,1586 @@
+/*
+ * Copyright (C) 2007 Júlio Vilmar Gesser.
+ * Copyright (C) 2012 Mozilla Foundation
+ *
+ * This file is part of Java 1.5 parser and Abstract Syntax Tree.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 05/10/2006
+ */
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.ast.BlockComment;
+import japa.parser.ast.CompilationUnit;
+import japa.parser.ast.LineComment;
+import japa.parser.ast.TypeParameter;
+import japa.parser.ast.body.BodyDeclaration;
+import japa.parser.ast.body.ClassOrInterfaceDeclaration;
+import japa.parser.ast.body.ConstructorDeclaration;
+import japa.parser.ast.body.EmptyMemberDeclaration;
+import japa.parser.ast.body.EmptyTypeDeclaration;
+import japa.parser.ast.body.EnumConstantDeclaration;
+import japa.parser.ast.body.EnumDeclaration;
+import japa.parser.ast.body.FieldDeclaration;
+import japa.parser.ast.body.InitializerDeclaration;
+import japa.parser.ast.body.JavadocComment;
+import japa.parser.ast.body.MethodDeclaration;
+import japa.parser.ast.body.ModifierSet;
+import japa.parser.ast.body.Parameter;
+import japa.parser.ast.body.TypeDeclaration;
+import japa.parser.ast.body.VariableDeclarator;
+import japa.parser.ast.body.VariableDeclaratorId;
+import japa.parser.ast.expr.AnnotationExpr;
+import japa.parser.ast.expr.ArrayAccessExpr;
+import japa.parser.ast.expr.ArrayCreationExpr;
+import japa.parser.ast.expr.ArrayInitializerExpr;
+import japa.parser.ast.expr.AssignExpr;
+import japa.parser.ast.expr.BinaryExpr;
+import japa.parser.ast.expr.BooleanLiteralExpr;
+import japa.parser.ast.expr.CastExpr;
+import japa.parser.ast.expr.CharLiteralExpr;
+import japa.parser.ast.expr.ClassExpr;
+import japa.parser.ast.expr.ConditionalExpr;
+import japa.parser.ast.expr.DoubleLiteralExpr;
+import japa.parser.ast.expr.EnclosedExpr;
+import japa.parser.ast.expr.Expression;
+import japa.parser.ast.expr.FieldAccessExpr;
+import japa.parser.ast.expr.InstanceOfExpr;
+import japa.parser.ast.expr.IntegerLiteralExpr;
+import japa.parser.ast.expr.IntegerLiteralMinValueExpr;
+import japa.parser.ast.expr.LongLiteralExpr;
+import japa.parser.ast.expr.LongLiteralMinValueExpr;
+import japa.parser.ast.expr.MemberValuePair;
+import japa.parser.ast.expr.MethodCallExpr;
+import japa.parser.ast.expr.NameExpr;
+import japa.parser.ast.expr.NullLiteralExpr;
+import japa.parser.ast.expr.ObjectCreationExpr;
+import japa.parser.ast.expr.QualifiedNameExpr;
+import japa.parser.ast.expr.StringLiteralExpr;
+import japa.parser.ast.expr.SuperExpr;
+import japa.parser.ast.expr.ThisExpr;
+import japa.parser.ast.expr.UnaryExpr;
+import japa.parser.ast.expr.UnaryExpr.Operator;
+import japa.parser.ast.expr.VariableDeclarationExpr;
+import japa.parser.ast.stmt.AssertStmt;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.CatchClause;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.stmt.DoStmt;
+import japa.parser.ast.stmt.EmptyStmt;
+import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.ForStmt;
+import japa.parser.ast.stmt.ForeachStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.LabeledStmt;
+import japa.parser.ast.stmt.ReturnStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.stmt.SynchronizedStmt;
+import japa.parser.ast.stmt.ThrowStmt;
+import japa.parser.ast.stmt.TryStmt;
+import japa.parser.ast.stmt.TypeDeclarationStmt;
+import japa.parser.ast.stmt.WhileStmt;
+import japa.parser.ast.type.ClassOrInterfaceType;
+import japa.parser.ast.type.PrimitiveType;
+import japa.parser.ast.type.ReferenceType;
+import japa.parser.ast.type.Type;
+import japa.parser.ast.type.VoidType;
+import japa.parser.ast.type.WildcardType;
+import japa.parser.ast.visitor.VoidVisitorAdapter;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import nu.validator.htmlparser.cpptranslate.TranslatorUtils;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+
+public final class RustVisitor extends VoidVisitorAdapter<Object> {
+
+ private static final String[] MODS = {
+ "Tokenizer",
+ "TreeBuilder",
+ "MetaScanner",
+ "AttributeName",
+ "ElementName",
+ "HtmlAttributes",
+ "StackNode",
+ "UTF16Buffer",
+ "StateSnapshot",
+ };
+
+ private boolean inMethodSignature = false;
+
+ private Set<String> fields = new HashSet<String>();
+
+ private Set<String> constants = new HashSet<String>();
+
+ private Expression loopUpdate = null;
+
+ private static class SourcePrinter {
+
+ private int level = 0;
+
+ private boolean indented = false;
+
+ private final StringBuilder buf = new StringBuilder();
+
+ public void indent() {
+ level++;
+ }
+
+ public void unindent() {
+ level--;
+ }
+
+ private void makeIndent() {
+ for (int i = 0; i < level; i++) {
+ buf.append(" ");
+ }
+ }
+
+ public void print(String arg) {
+ if (!indented) {
+ makeIndent();
+ indented = true;
+ }
+ buf.append(arg);
+ }
+
+ public void printLn(String arg) {
+ print(arg);
+ printLn();
+ }
+
+ public void printLn() {
+ buf.append("\n");
+ indented = false;
+ }
+
+ public String getSource() {
+ return buf.toString();
+ }
+
+ @Override
+ public String toString() {
+ return getSource();
+ }
+ }
+
+ private final SourcePrinter printer = new SourcePrinter();
+
+ public String getSource() {
+ return printer.getSource();
+ }
+
+ private void printModifiers(int modifiers) {
+ if (ModifierSet.isPrivate(modifiers)) {
+ printer.print("private ");
+ }
+ if (ModifierSet.isProtected(modifiers)) {
+ printer.print("protected ");
+ }
+ if (ModifierSet.isPublic(modifiers)) {
+ printer.print("public ");
+ }
+ if (ModifierSet.isAbstract(modifiers)) {
+ printer.print("abstract ");
+ }
+ if (ModifierSet.isStatic(modifiers)) {
+ printer.print("static ");
+ }
+ if (ModifierSet.isFinal(modifiers)) {
+ printer.print("final ");
+ }
+ if (ModifierSet.isNative(modifiers)) {
+ printer.print("native ");
+ }
+ if (ModifierSet.isStrictfp(modifiers)) {
+ printer.print("strictfp ");
+ }
+ if (ModifierSet.isSynchronized(modifiers)) {
+ printer.print("synchronized ");
+ }
+ if (ModifierSet.isTransient(modifiers)) {
+ printer.print("transient ");
+ }
+ if (ModifierSet.isVolatile(modifiers)) {
+ printer.print("volatile ");
+ }
+ }
+
+ private void printMethods(List<BodyDeclaration> members, Object arg) {
+ for (BodyDeclaration member : members) {
+ if (member instanceof MethodDeclaration) {
+ MethodDeclaration meth = (MethodDeclaration) member;
+ if (meth.getName().startsWith("fatal") || meth.getName().startsWith("err")
+ || meth.getName().startsWith("warn")
+ || meth.getName().startsWith("maybeErr")
+ || meth.getName().startsWith("maybeWarn")
+ || meth.getName().startsWith("note")
+ || "releaseArray".equals(meth.getName())
+ || "deleteArray".equals(meth.getName())
+ || "delete".equals(meth.getName())) {
+ continue;
+ }
+ printer.printLn();
+ member.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ }
+
+ private void printFields(List<BodyDeclaration> members, Object arg) {
+ for (BodyDeclaration member : members) {
+ if (member instanceof FieldDeclaration) {
+ FieldDeclaration field = (FieldDeclaration) member;
+ int mods = field.getModifiers();
+ if (ModifierSet.isStatic(mods) && ModifierSet.isFinal(mods)) {
+ continue;
+ }
+ fields.add(field.getVariables().get(0).getId().getName());
+ printer.printLn();
+ member.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ }
+
+ private void printConstants(List<BodyDeclaration> members, Object arg) {
+ for (BodyDeclaration member : members) {
+ if (member instanceof FieldDeclaration) {
+ FieldDeclaration field = (FieldDeclaration) member;
+ int mods = field.getModifiers();
+ if (!(ModifierSet.isStatic(mods) && ModifierSet.isFinal(mods))) {
+ continue;
+ }
+ constants.add(field.getVariables().get(0).getId().getName());
+ printer.printLn();
+ member.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ }
+
+ private void printMemberAnnotations(List<AnnotationExpr> annotations, Object arg) {
+ if (annotations != null) {
+ for (AnnotationExpr a : annotations) {
+ a.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ }
+
+ private void printArguments(List<Expression> args, Object arg) {
+ printer.print("(");
+ if (args != null) {
+ for (Iterator<Expression> i = args.iterator(); i.hasNext();) {
+ Expression e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+ }
+
+ private void printJavadoc(JavadocComment javadoc, Object arg) {
+ if (javadoc != null) {
+ javadoc.accept(this, arg);
+ }
+ }
+
+ public void visit(CompilationUnit n, Object arg) {
+ if (n.getTypes() != null) {
+ for (Iterator<TypeDeclaration> i = n.getTypes().iterator(); i.hasNext();) {
+ i.next().accept(this, arg);
+ printer.printLn();
+ if (i.hasNext()) {
+ printer.printLn();
+ }
+ }
+ }
+ }
+
+ public void visit(NameExpr n, Object arg) {
+ if (fields.contains(n.getName())) {
+ printer.print("self.");
+ }
+ printer.print(n.getName());
+ }
+
+ public void visit(QualifiedNameExpr n, Object arg) {
+ n.getQualifier().accept(this, arg);
+ printer.print(".");
+ printer.print(n.getName());
+ }
+
+ public void visit(ClassOrInterfaceDeclaration n, Object arg) {
+ for (int i = 0; i < MODS.length; i++) {
+ String mod = MODS[i];
+ if (!mod.equals(n.getName())) {
+ printer.print("mod ");
+ printer.print(mod);
+ printer.printLn(";");
+ }
+ }
+
+ printJavadoc(n.getJavaDoc(), arg);
+
+
+ if (n.getMembers() != null) {
+ printConstants(n.getMembers(), arg);
+ }
+ printer.printLn();
+ printer.printLn();
+
+ printer.print("struct ");
+
+ printer.print(n.getName());
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getMembers() != null) {
+ printFields(n.getMembers(), arg);
+ }
+ printer.unindent();
+ printer.print("}");
+
+ printer.printLn();
+ printer.printLn();
+
+ printer.print("impl ");
+
+ printer.print(n.getName());
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getMembers() != null) {
+ printMethods(n.getMembers(), arg);
+ }
+ printer.unindent();
+ printer.print("}");
+
+ }
+
+ public void visit(EmptyTypeDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printer.print(";");
+ }
+
+ public void visit(JavadocComment n, Object arg) {
+ printer.print("/**");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+ public void visit(ClassOrInterfaceType n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print(n.getName());
+ }
+
+ public void visit(TypeParameter n, Object arg) {
+ printer.print(n.getName());
+ if (n.getTypeBound() != null) {
+ printer.print(" extends ");
+ for (Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(" & ");
+ }
+ }
+ }
+ }
+
+ public void visit(PrimitiveType n, Object arg) {
+ switch (n.getType()) {
+ case Boolean:
+ printer.print("bool");
+ break;
+ case Byte:
+ printer.print("i8");
+ break;
+ case Char:
+ printer.print("u16");
+ break;
+ case Double:
+ printer.print("f64");
+ break;
+ case Float:
+ printer.print("f32");
+ break;
+ case Int:
+ printer.print("i32");
+ break;
+ case Long:
+ printer.print("i64");
+ break;
+ case Short:
+ printer.print("i16");
+ break;
+ }
+ }
+
+ public void visit(ReferenceType n, Object arg) {
+// if (inMethodSignature) {
+// printer.print("&");
+// } else {
+// printer.print("~");
+// }
+ printer.print("@");
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[");
+ }
+ n.getType().accept(this, arg);
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("]");
+ }
+ }
+
+ public void visit(WildcardType n, Object arg) {
+ printer.print("?");
+ if (n.getExtends() != null) {
+ printer.print(" extends ");
+ n.getExtends().accept(this, arg);
+ }
+ if (n.getSuper() != null) {
+ printer.print(" super ");
+ n.getSuper().accept(this, arg);
+ }
+ }
+
+ public void visit(FieldDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+// printMemberAnnotations(n.getAnnotations(), arg);
+
+ boolean field = true;
+ int mods = n.getModifiers();
+ if (ModifierSet.isStatic(mods) && ModifierSet.isFinal(mods)) {
+ if (!ModifierSet.isPrivate(mods)) {
+ printer.print("pub ");
+ }
+ printer.print("const ");
+ field = false;
+ } else if (!ModifierSet.isFinal(mods)) {
+ printer.print("mut ");
+ }
+
+ List<VariableDeclarator> vars = n.getVariables();
+
+ printVariableDeclarator(n.getType(), vars, arg, field);
+
+ printer.print(field ? "," : ";");
+ }
+
+ private void printVariableDeclarator(Type type, List<VariableDeclarator> vars,
+ Object arg, boolean field) {
+ if (vars.size() != 1) {
+ throw new RuntimeException();
+ }
+
+ VariableDeclarator decl = vars.get(0);
+
+ VariableDeclaratorId id = decl.getId();
+
+ printer.print(id.getName());
+
+ printer.print(": ");
+
+ for (int i = 0; i < id.getArrayCount(); i++) {
+ printer.print("[");
+ }
+
+ type.accept(this, arg);
+
+ for (int i = 0; i < id.getArrayCount(); i++) {
+ printer.print("]");
+ }
+
+ Expression init = decl.getInit();
+
+ if (init != null && !field) {
+ printer.print(" = ");
+ init.accept(this, arg);
+ }
+ }
+
+ public void visit(ArrayInitializerExpr n, Object arg) {
+ printer.print("[");
+ if (n.getValues() != null) {
+ printer.print(" ");
+ for (Iterator<Expression> i = n.getValues().iterator(); i.hasNext();) {
+ Expression expr = i.next();
+ expr.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ printer.print(" ");
+ }
+ printer.print("]");
+ }
+
+ public void visit(VoidType n, Object arg) {
+ printer.print("void");
+ }
+
+ public void visit(ArrayAccessExpr n, Object arg) {
+ n.getName().accept(this, arg);
+ printer.print("[");
+ n.getIndex().accept(this, arg);
+ printer.print("]");
+ }
+
+ public void visit(ArrayCreationExpr n, Object arg) {
+ printer.print("new ");
+ n.getType().accept(this, arg);
+
+ if (n.getDimensions() != null) {
+ for (Expression dim : n.getDimensions()) {
+ printer.print("[");
+ dim.accept(this, arg);
+ printer.print("]");
+ }
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ } else {
+ for (int i = 0; i < n.getArrayCount(); i++) {
+ printer.print("[]");
+ }
+ printer.print(" ");
+ n.getInitializer().accept(this, arg);
+ }
+ }
+
+ public void visit(AssignExpr n, Object arg) {
+ n.getTarget().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case assign:
+ printer.print("=");
+ break;
+ case and:
+ printer.print("&=");
+ break;
+ case or:
+ printer.print("|=");
+ break;
+ case xor:
+ printer.print("^=");
+ break;
+ case plus:
+ printer.print("+=");
+ break;
+ case minus:
+ printer.print("-=");
+ break;
+ case rem:
+ printer.print("%=");
+ break;
+ case slash:
+ printer.print("/=");
+ break;
+ case star:
+ printer.print("*=");
+ break;
+ case lShift:
+ printer.print("<<=");
+ break;
+ case rSignedShift:
+ printer.print(">>=");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>=");
+ break;
+ }
+ printer.print(" ");
+ n.getValue().accept(this, arg);
+ }
+
+ public void visit(BinaryExpr n, Object arg) {
+ n.getLeft().accept(this, arg);
+ printer.print(" ");
+ switch (n.getOperator()) {
+ case or:
+ printer.print("||");
+ break;
+ case and:
+ printer.print("&&");
+ break;
+ case binOr:
+ printer.print("|");
+ break;
+ case binAnd:
+ printer.print("&");
+ break;
+ case xor:
+ printer.print("^");
+ break;
+ case equals:
+ printer.print("==");
+ break;
+ case notEquals:
+ printer.print("!=");
+ break;
+ case less:
+ printer.print("<");
+ break;
+ case greater:
+ printer.print(">");
+ break;
+ case lessEquals:
+ printer.print("<=");
+ break;
+ case greaterEquals:
+ printer.print(">=");
+ break;
+ case lShift:
+ printer.print("<<");
+ break;
+ case rSignedShift:
+ printer.print(">>");
+ break;
+ case rUnsignedShift:
+ printer.print(">>>");
+ break;
+ case plus:
+ printer.print("+");
+ break;
+ case minus:
+ printer.print("-");
+ break;
+ case times:
+ printer.print("*");
+ break;
+ case divide:
+ printer.print("/");
+ break;
+ case remainder:
+ printer.print("%");
+ break;
+ }
+ printer.print(" ");
+ n.getRight().accept(this, arg);
+ }
+
+ public void visit(CastExpr n, Object arg) {
+ printer.print("(");
+ n.getType().accept(this, arg);
+ printer.print(") ");
+ n.getExpr().accept(this, arg);
+ }
+
+ public void visit(ClassExpr n, Object arg) {
+ n.getType().accept(this, arg);
+ printer.print(".class");
+ }
+
+ public void visit(ConditionalExpr n, Object arg) {
+ n.getCondition().accept(this, arg);
+ printer.print(" ? ");
+ n.getThenExpr().accept(this, arg);
+ printer.print(" : ");
+ n.getElseExpr().accept(this, arg);
+ }
+
+ public void visit(EnclosedExpr n, Object arg) {
+ printer.print("(");
+ n.getInner().accept(this, arg);
+ printer.print(")");
+ }
+
+ public void visit(FieldAccessExpr n, Object arg) {
+ String scope = n.getScope().toString();
+ printer.print(scope);
+ boolean mod = false;
+ for (int i = 0; i < MODS.length; i++) {
+ if (MODS[i].equals(scope)) {
+ mod = true;
+ break;
+ }
+ }
+ printer.print(mod ? "::" : ".");
+ if ("length".equals(n.getField())) {
+ printer.print("len() as i32");
+ } else {
+ printer.print(n.getField());
+ }
+ }
+
+ public void visit(InstanceOfExpr n, Object arg) {
+ n.getExpr().accept(this, arg);
+ printer.print(" instanceof ");
+ n.getType().accept(this, arg);
+ }
+
+ public void visit(CharLiteralExpr n, Object arg) {
+// printer.print("'");
+// char c = n.getValue().charAt(0);
+// switch (c) {
+// case '\b':
+// printer.print("\\b");
+// break;
+// case '\t':
+// printer.print("\\t");
+// break;
+// case '\n':
+// printer.print("\\n");
+// break;
+// case '\f':
+// printer.print("\\f");
+// break;
+// case '\r':
+// printer.print("\\r");
+// break;
+// case '\'':
+// printer.print("\\'");
+// break;
+// case '\\':
+// printer.print(n.getValue());
+// break;
+// default:
+// if (c < ' ' || c > '~') {
+// String hex = Integer.toHexString(c);
+// switch (hex.length()) {
+// case 1:
+// printer.print("\\u000"+hex);
+// break;
+// case 2:
+// printer.print("\\u00"+hex);
+// break;
+// case 3:
+// printer.print("\\u0"+hex);
+// break;
+// case 4:
+// printer.print("\\u"+hex);
+// break;
+// }
+// } else {
+// printer.print(""+c);
+// }
+// break;
+// }
+// printer.print("'");
+ String str = n.getValue();
+ if (str.length() == 1) {
+ String hex = Integer.toHexString(str.charAt(0));
+ switch (hex.length()) {
+ case 1:
+ printer.print("0x0"+hex);
+ break;
+ case 2:
+ printer.print("0x"+hex);
+ break;
+ case 3:
+ printer.print("0x0"+hex);
+ break;
+ case 4:
+ printer.print("0x"+hex);
+ break;
+ }
+ } else if ("\\n".equals(str)) {
+ printer.print("0x0A");
+ } else if ("\\r".equals(str)) {
+ printer.print("0x0D");
+ } else if ("\\t".equals(str)) {
+ printer.print("0x09");
+ } else if ("\\\"".equals(str)) {
+ printer.print("0x22");
+ } else if ("\\'".equals(str)) {
+ printer.print("0x27");
+ } else {
+ throw new RuntimeException(str);
+ }
+ }
+
+ public void visit(DoubleLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(IntegerLiteralMinValueExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(LongLiteralMinValueExpr n, Object arg) {
+ printer.print(n.getValue());
+ }
+
+ public void visit(StringLiteralExpr n, Object arg) {
+ printer.print("\"");
+ printer.print(n.getValue());
+ printer.print("\"");
+ }
+
+ public void visit(BooleanLiteralExpr n, Object arg) {
+ printer.print(String.valueOf(n.getValue()));
+ }
+
+ public void visit(NullLiteralExpr n, Object arg) {
+ printer.print("null");
+ }
+
+ public void visit(ThisExpr n, Object arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("self");
+ }
+
+ public void visit(SuperExpr n, Object arg) {
+ if (n.getClassExpr() != null) {
+ n.getClassExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("super");
+ }
+
+ public void visit(MethodCallExpr n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print(n.getName());
+ printArguments(n.getArgs(), arg);
+ }
+
+ public void visit(ObjectCreationExpr n, Object arg) {
+ if (n.getScope() != null) {
+ n.getScope().accept(this, arg);
+ printer.print(".");
+ }
+
+ printer.print("new ");
+
+ n.getType().accept(this, arg);
+
+ printArguments(n.getArgs(), arg);
+
+ if (n.getAnonymousClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMethods(n.getAnonymousClassBody(), arg);
+ printer.unindent();
+ printer.print("}");
+ }
+ }
+
+ public void visit(UnaryExpr n, Object arg) {
+ Operator op = n.getOperator();
+ if (op == null) {
+ n.getExpr().accept(this, arg);
+ return;
+ }
+ switch (op) {
+ case positive:
+ printer.print("+");
+ n.getExpr().accept(this, arg);
+ break;
+ case negative:
+ printer.print("-");
+ n.getExpr().accept(this, arg);
+ break;
+ case inverse:
+ printer.print("i32::compl(");
+ n.getExpr().accept(this, arg);
+ printer.print(")");
+ break;
+ case not:
+ printer.print("!");
+ n.getExpr().accept(this, arg);
+ break;
+ case preIncrement:
+ case posIncrement:
+ n.getExpr().accept(this, arg);
+ printer.print(" = ");
+ n.getExpr().accept(this, arg);
+ printer.print(" + 1");
+ break;
+ case preDecrement:
+ case posDecrement:
+ n.getExpr().accept(this, arg);
+ printer.print(" = ");
+ n.getExpr().accept(this, arg);
+ printer.print(" - 1");
+ break;
+ }
+ }
+
+ public void visit(ConstructorDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ if (n.getTypeParameters() != null) {
+ printer.print(" ");
+ }
+ printer.print(n.getName());
+
+ printer.print("(");
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(")");
+
+ if (n.getThrows() != null) {
+ printer.print(" throws ");
+ for (Iterator<NameExpr> i = n.getThrows().iterator(); i.hasNext();) {
+ NameExpr name = i.next();
+ name.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ printer.print(" ");
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(MethodDeclaration n, Object arg) {
+
+ printJavadoc(n.getJavaDoc(), arg);
+// printMemberAnnotations(n.getAnnotations(), arg);
+// printModifiers(n.getModifiers());
+
+// printTypeParameters(n.getTypeParameters(), arg);
+// if (n.getTypeParameters() != null) {
+// printer.print(" ");
+// }
+
+ printer.print("fn ");
+ printer.print(n.getName());
+
+ printer.print("(");
+ inMethodSignature = true;
+ if (n.getParameters() != null) {
+ for (Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext();) {
+ Parameter p = i.next();
+ p.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ inMethodSignature = false;
+ printer.print(")");
+
+ Type type = n.getType();
+
+ if (!(type instanceof VoidType)) {
+ printer.print(" -> ");
+ type.accept(this, arg);
+ }
+
+// for (int i = 0; i < n.getArrayCount(); i++) {
+// printer.print("[]");
+// }
+
+// if (n.getThrows() != null) {
+// printer.print(" throws ");
+// for (Iterator<NameExpr> i = n.getThrows().iterator(); i.hasNext();) {
+// NameExpr name = i.next();
+// name.accept(this, arg);
+// if (i.hasNext()) {
+// printer.print(", ");
+// }
+// }
+// }
+ if (n.getBody() == null) {
+ printer.print(";");
+ } else {
+ printer.print(" ");
+ n.getBody().accept(this, arg);
+ }
+ }
+
+ public void visit(Parameter n, Object arg) {
+// printAnnotations(n.getAnnotations(), arg);
+// printModifiers(n.getModifiers());
+
+ VariableDeclaratorId id = n.getId();
+
+ printer.print(id.getName());
+// if (n.isVarArgs()) {
+// printer.print("...");
+// }
+ printer.print(": ");
+ n.getType().accept(this, arg);
+ }
+
+ public void visit(ExplicitConstructorInvocationStmt n, Object arg) {
+ if (n.isThis()) {
+ printer.print("this");
+ } else {
+ if (n.getExpr() != null) {
+ n.getExpr().accept(this, arg);
+ printer.print(".");
+ }
+ printer.print("super");
+ }
+ printArguments(n.getArgs(), arg);
+ printer.print(";");
+ }
+
+ public void visit(VariableDeclarationExpr n, Object arg) {
+// printAnnotations(n.getAnnotations(), arg);
+
+ printer.print("let ");
+
+ if (!ModifierSet.isFinal(n.getModifiers())) {
+ printer.print("mut ");
+ }
+
+// printModifiers(n.getModifiers());
+
+ List<VariableDeclarator> vars = n.getVars();
+
+ printVariableDeclarator(n.getType(), vars, arg, false);
+ }
+
+ public void visit(TypeDeclarationStmt n, Object arg) {
+ n.getTypeDeclaration().accept(this, arg);
+ }
+
+ public void visit(AssertStmt n, Object arg) {
+ Expression check = n.getCheck();
+ if (check instanceof BooleanLiteralExpr) {
+ BooleanLiteralExpr bool = (BooleanLiteralExpr) check;
+ if (!bool.getValue()) {
+ printer.print("fail;");
+ return;
+ }
+ }
+ printer.print("assert ");
+ check.accept(this, arg);
+ printer.print(";");
+ }
+
+ public void visit(BlockStmt n, Object arg) {
+ printer.printLn("{");
+ if (n.getStmts() != null) {
+ printer.indent();
+ for (Statement s : n.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+ }
+
+ public void visit(LabeledStmt n, Object arg) {
+ assert arg == null;
+ n.getStmt().accept(this, n.getLabel());
+ }
+
+ public void visit(EmptyStmt n, Object arg) {
+ printer.print(";");
+ }
+
+ public void visit(ExpressionStmt n, Object arg) {
+ Expression plusplus = null;
+ Expression ex = n.getExpression();
+
+ if (ex instanceof MethodCallExpr) {
+ MethodCallExpr meth = (MethodCallExpr) ex;
+ if (meth.getName().startsWith("fatal") || meth.getName().startsWith("err")
+ || meth.getName().startsWith("warn")
+ || meth.getName().startsWith("maybeErr")
+ || meth.getName().startsWith("maybeWarn")
+ || meth.getName().startsWith("note")
+ || "releaseArray".equals(meth.getName())
+ || "deleteArray".equals(meth.getName())
+ || "delete".equals(meth.getName())) {
+ return;
+ }
+ }
+
+ if (ex instanceof AssignExpr) {
+ AssignExpr ax = (AssignExpr) ex;
+ Expression left = ax.getTarget();
+ if (left instanceof ArrayAccessExpr) {
+ ArrayAccessExpr aae = (ArrayAccessExpr) left;
+ Expression index = aae.getIndex();
+ if (index instanceof UnaryExpr) {
+ UnaryExpr unex = (UnaryExpr) index;
+ if (unex.getOperator() == Operator.posIncrement) {
+ plusplus = unex.getExpr();
+ unex.setOperator(null);
+ }
+ }
+ }
+ }
+ n.getExpression().accept(this, arg);
+ printer.print(";");
+ if (plusplus != null) {
+ printer.printLn();
+ plusplus.accept(this, arg);
+ printer.print(" = ");
+ plusplus.accept(this, arg);
+ printer.print(" + 1;");
+ }
+ }
+
+ public void visit(SwitchStmt n, Object arg) {
+ printer.print("match ");
+ n.getSelector().accept(this, arg);
+ printer.printLn(" {");
+ if (n.getEntries() != null) {
+ printer.indent();
+ List<Expression> labels = new LinkedList<Expression>();
+ for (SwitchEntryStmt e : n.getEntries()) {
+ labels.add(e.getLabel());
+ List<Statement> stmts = e.getStmts();
+ if (stmts != null) {
+ if (stmts.get(stmts.size() - 1) instanceof BreakStmt) {
+ BreakStmt brk = (BreakStmt)stmts.get(stmts.size() - 1);
+ if (brk.getId() == null) {
+ stmts.remove(stmts.size() - 1);
+ }
+ }
+ if (!stmts.isEmpty()) {
+ boolean first = true;
+ for (Expression label : labels) {
+ if (!first) {
+ printer.print(" | ");
+ }
+ first = false;
+ if (label == null) {
+ printer.print("_");
+ } else {
+ label.accept(this, arg);
+ }
+ }
+ printer.printLn(" => {");
+ printer.indent();
+ for (Statement statement : stmts) {
+ statement.accept(this, arg);
+ printer.printLn();
+ }
+ printer.unindent();
+ printer.printLn("}");
+ }
+ labels.clear();
+ }
+ }
+ printer.unindent();
+ }
+ printer.print("}");
+
+ }
+
+ public void visit(SwitchEntryStmt n, Object arg) {
+ throw new RuntimeException("Not supposed to come here.");
+ }
+
+ public void visit(BreakStmt n, Object arg) {
+ printer.print("break");
+ if (n.getId() != null && !"charsetloop".equals(n.getId()) && !"charactersloop".equals(n.getId())) {
+ printer.print(" ");
+ printer.print(n.getId());
+ }
+ printer.print(";");
+ }
+
+ public void visit(ReturnStmt n, Object arg) {
+ printer.print("return");
+ if (n.getExpr() != null) {
+ printer.print(" ");
+ n.getExpr().accept(this, arg);
+ }
+ printer.print(";");
+ }
+
+ public void visit(EnumDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printModifiers(n.getModifiers());
+
+ printer.print("enum ");
+ printer.print(n.getName());
+
+ if (n.getImplements() != null) {
+ printer.print(" implements ");
+ for (Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext();) {
+ ClassOrInterfaceType c = i.next();
+ c.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+
+ printer.printLn(" {");
+ printer.indent();
+ if (n.getEntries() != null) {
+ printer.printLn();
+ for (Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext();) {
+ EnumConstantDeclaration e = i.next();
+ e.accept(this, arg);
+ if (i.hasNext()) {
+ printer.print(", ");
+ }
+ }
+ }
+ if (n.getMembers() != null) {
+ printer.printLn(";");
+ printMethods(n.getMembers(), arg);
+ } else {
+ if (n.getEntries() != null) {
+ printer.printLn();
+ }
+ }
+ printer.unindent();
+ printer.print("}");
+ throw new RuntimeException("Unsupported syntax.");
+ }
+
+ public void visit(EnumConstantDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printMemberAnnotations(n.getAnnotations(), arg);
+ printer.print(n.getName());
+
+ if (n.getArgs() != null) {
+ printArguments(n.getArgs(), arg);
+ }
+
+ if (n.getClassBody() != null) {
+ printer.printLn(" {");
+ printer.indent();
+ printMethods(n.getClassBody(), arg);
+ printer.unindent();
+ printer.printLn("}");
+ }
+ throw new RuntimeException("Unsupported syntax.");
+ }
+
+ public void visit(EmptyMemberDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ printer.print(";");
+ }
+
+ public void visit(InitializerDeclaration n, Object arg) {
+ printJavadoc(n.getJavaDoc(), arg);
+ if (n.isStatic()) {
+ printer.print("static ");
+ }
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(IfStmt n, Object arg) {
+ Expression cond = n.getCondition();
+ if (cond instanceof BinaryExpr) {
+ BinaryExpr binex = (BinaryExpr) cond;
+ Expression left = binex.getLeft();
+ if (left instanceof UnaryExpr) {
+ UnaryExpr unex = (UnaryExpr) left;
+ if (unex.getOperator() == Operator.preIncrement) {
+ unex.getExpr().accept(this, arg);
+ printer.print(" = ");
+ unex.getExpr().accept(this, arg);
+ printer.printLn(" + 1;");
+ unex.setOperator(null);
+ }
+ }
+ }
+
+ if (!TranslatorUtils.isErrorHandlerIf(n.getCondition(), false)) {
+ if (TranslatorUtils.isErrorOnlyBlock(n.getThenStmt(), false)) {
+ if (n.getElseStmt() != null
+ && !TranslatorUtils.isErrorOnlyBlock(n.getElseStmt(), false)) {
+ printer.print("if ");
+ if (n.getCondition() instanceof BinaryExpr) {
+ BinaryExpr binExpr = (BinaryExpr) n.getCondition();
+ switch (binExpr.getOperator()) {
+ case equals:
+ binExpr.getLeft().accept(this, arg);
+ printer.print(" != ");
+ binExpr.getRight().accept(this, arg);
+ break;
+ case notEquals:
+ binExpr.getLeft().accept(this, arg);
+ printer.print(" == ");
+ binExpr.getRight().accept(this, arg);
+ break;
+ default:
+ printer.print("!(");
+ n.getCondition().accept(this, arg);
+ printer.print(")");
+ break;
+ }
+ } else {
+ printer.print("!(");
+ n.getCondition().accept(this, arg);
+ printer.print(")");
+ }
+ printer.print(" ");
+ n.getElseStmt().accept(this, arg);
+ }
+ } else {
+ printer.print("if ");
+ n.getCondition().accept(this, arg);
+ printer.print(" ");
+ n.getThenStmt().accept(this, arg);
+ if (n.getElseStmt() != null
+ && !TranslatorUtils.isErrorOnlyBlock(n.getElseStmt(), false)) {
+ printer.print(" else ");
+ n.getElseStmt().accept(this, arg);
+ }
+ }
+ }
+
+ }
+
+ public void visit(WhileStmt n, Object arg) {
+ printer.print("while ");
+ n.getCondition().accept(this, arg);
+ printer.print(" ");
+ n.getBody().accept(this, arg);
+ }
+
+ public void visit(ContinueStmt n, Object arg) {
+ if (loopUpdate != null) {
+ loopUpdate.accept(this, arg);
+ printer.printLn(";");
+ }
+ printer.print("loop");
+ if (n.getId() != null) {
+ printer.print(" ");
+ printer.print(n.getId());
+ }
+ printer.print(";");
+ }
+
+ public void visit(DoStmt n, Object arg) {
+ printer.print("do ");
+ n.getBody().accept(this, arg);
+ printer.print(" while (");
+ n.getCondition().accept(this, arg);
+ printer.print(");");
+ throw new RuntimeException("Unsupported syntax.");
+ }
+
+ public void visit(ForeachStmt n, Object arg) {
+ printer.print("for (");
+ n.getVariable().accept(this, arg);
+ printer.print(" : ");
+ n.getIterable().accept(this, arg);
+ printer.print(") ");
+ n.getBody().accept(this, arg);
+ throw new RuntimeException("Unsupported syntax.");
+ }
+
+ public void visit(ForStmt n, Object arg) {
+ String label = null;
+ if (arg instanceof String) {
+ label = (String) arg;
+ arg = null;
+ }
+ if (n.getInit() == null && n.getCompare() == null && n.getUpdate() == null) {
+ printer.print("loop ");
+ if (label != null) {
+ printer.print(label);
+ printer.print(": ");
+ }
+ n.getBody().accept(this, arg);
+ return;
+ }
+
+ assert label == null || "charsetloop".equals(label) || "charactersloop".equals(label);
+
+ Expression oldLoopUpdate = loopUpdate;
+ loopUpdate = n.getUpdate().get(0);
+
+ if (n.getInit() != null) {
+ n.getInit().get(0).accept(this, arg);
+ printer.printLn(";");
+ }
+
+ if (n.getCompare() == null) {
+ printer.print("loop ");
+ } else {
+ printer.print("while ");
+ n.getCompare().accept(this, arg);
+ printer.print(" ");
+ }
+
+ Statement body = n.getBody();
+ if (body instanceof BlockStmt) {
+ BlockStmt blockStmt = (BlockStmt) body;
+ printer.printLn("{");
+ printer.indent();
+ if (blockStmt.getStmts() != null) {
+ for (Statement s : blockStmt.getStmts()) {
+ s.accept(this, arg);
+ printer.printLn();
+ }
+ }
+ if (loopUpdate != null) {
+ loopUpdate.accept(this, arg);
+ printer.printLn(";");
+ }
+ printer.unindent();
+ printer.print("}");
+ } else {
+ throw new RuntimeException();
+ }
+
+ loopUpdate = oldLoopUpdate;
+ }
+
+ public void visit(ThrowStmt n, Object arg) {
+ printer.print("throw ");
+ n.getExpr().accept(this, arg);
+ printer.print(";");
+ }
+
+ public void visit(SynchronizedStmt n, Object arg) {
+ printer.print("synchronized (");
+ n.getExpr().accept(this, arg);
+ printer.print(") ");
+ n.getBlock().accept(this, arg);
+ }
+
+ public void visit(TryStmt n, Object arg) {
+ printer.print("try ");
+ n.getTryBlock().accept(this, arg);
+ if (n.getCatchs() != null) {
+ for (CatchClause c : n.getCatchs()) {
+ c.accept(this, arg);
+ }
+ }
+ if (n.getFinallyBlock() != null) {
+ printer.print(" finally ");
+ n.getFinallyBlock().accept(this, arg);
+ }
+ }
+
+ public void visit(CatchClause n, Object arg) {
+ printer.print(" catch (");
+ n.getExcept().accept(this, arg);
+ printer.print(") ");
+ n.getCatchBlock().accept(this, arg);
+
+ }
+
+// public void visit(AnnotationDeclaration n, Object arg) {
+// printJavadoc(n.getJavaDoc(), arg);
+// printMemberAnnotations(n.getAnnotations(), arg);
+// printModifiers(n.getModifiers());
+//
+// printer.print("@interface ");
+// printer.print(n.getName());
+// printer.printLn(" {");
+// printer.indent();
+// if (n.getMembers() != null) {
+// printMembers(n.getMembers(), arg);
+// }
+// printer.unindent();
+// printer.print("}");
+// }
+//
+// public void visit(AnnotationMemberDeclaration n, Object arg) {
+// printJavadoc(n.getJavaDoc(), arg);
+// printMemberAnnotations(n.getAnnotations(), arg);
+// printModifiers(n.getModifiers());
+//
+// n.getType().accept(this, arg);
+// printer.print(" ");
+// printer.print(n.getName());
+// printer.print("()");
+// if (n.getDefaultValue() != null) {
+// printer.print(" default ");
+// n.getDefaultValue().accept(this, arg);
+// }
+// printer.print(";");
+// }
+//
+// public void visit(MarkerAnnotationExpr n, Object arg) {
+// printer.print("@");
+// n.getName().accept(this, arg);
+// }
+//
+// public void visit(SingleMemberAnnotationExpr n, Object arg) {
+// printer.print("@");
+// n.getName().accept(this, arg);
+// printer.print("(");
+// n.getMemberValue().accept(this, arg);
+// printer.print(")");
+// }
+//
+// public void visit(NormalAnnotationExpr n, Object arg) {
+// printer.print("@");
+// n.getName().accept(this, arg);
+// printer.print("(");
+// if (n.getPairs() != null) {
+// for (Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext();) {
+// MemberValuePair m = i.next();
+// m.accept(this, arg);
+// if (i.hasNext()) {
+// printer.print(", ");
+// }
+// }
+// }
+// printer.print(")");
+// }
+
+ public void visit(MemberValuePair n, Object arg) {
+ printer.print(n.getName());
+ printer.print(" = ");
+ n.getValue().accept(this, arg);
+ }
+
+ public void visit(LineComment n, Object arg) {
+ printer.print("//");
+ printer.printLn(n.getContent());
+ }
+
+ public void visit(BlockComment n, Object arg) {
+ printer.print("/*");
+ printer.print(n.getContent());
+ printer.printLn("*/");
+ }
+
+} \ No newline at end of file
diff --git a/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/SwitchBreakAnalyzerVisitor.java b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/SwitchBreakAnalyzerVisitor.java
new file mode 100644
index 000000000..766b349ce
--- /dev/null
+++ b/parser/html/java/htmlparser/translator-src/nu/validator/htmlparser/rusttranslate/SwitchBreakAnalyzerVisitor.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2008 Júlio Vilmar Gesser.
+ * Copyright (C) 2012 Mozilla Foundation
+ *
+ * This file is part of Java 1.5 parser and Abstract Syntax Tree.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Java 1.5 parser and Abstract Syntax Tree is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Java 1.5 parser and Abstract Syntax Tree. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ * Created on 09/06/2008
+ */
+package nu.validator.htmlparser.rusttranslate;
+
+import japa.parser.ast.stmt.AssertStmt;
+import japa.parser.ast.stmt.BlockStmt;
+import japa.parser.ast.stmt.BreakStmt;
+import japa.parser.ast.stmt.CatchClause;
+import japa.parser.ast.stmt.ContinueStmt;
+import japa.parser.ast.stmt.DoStmt;
+import japa.parser.ast.stmt.EmptyStmt;
+import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt;
+import japa.parser.ast.stmt.ExpressionStmt;
+import japa.parser.ast.stmt.ForStmt;
+import japa.parser.ast.stmt.ForeachStmt;
+import japa.parser.ast.stmt.IfStmt;
+import japa.parser.ast.stmt.LabeledStmt;
+import japa.parser.ast.stmt.ReturnStmt;
+import japa.parser.ast.stmt.Statement;
+import japa.parser.ast.stmt.SwitchEntryStmt;
+import japa.parser.ast.stmt.SwitchStmt;
+import japa.parser.ast.stmt.SynchronizedStmt;
+import japa.parser.ast.stmt.ThrowStmt;
+import japa.parser.ast.stmt.TryStmt;
+import japa.parser.ast.stmt.TypeDeclarationStmt;
+import japa.parser.ast.stmt.WhileStmt;
+import japa.parser.ast.type.WildcardType;
+import japa.parser.ast.visitor.GenericVisitorAdapter;
+
+import java.util.List;
+
+/**
+ * @author Julio Vilmar Gesser
+ * @author Henri Sivonen
+ */
+public class SwitchBreakAnalyzerVisitor extends GenericVisitorAdapter<Boolean, Boolean> {
+
+ private static final LoopBreakAnalyzerVisitor ANALYZER_VISITOR = new LoopBreakAnalyzerVisitor();
+
+ public Boolean visit(AssertStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(BlockStmt n, Boolean arg) {
+ // Bogus in the loop case
+ if (n.getStmts() != null) {
+ List<Statement> stms = n.getStmts();
+ return stms.get(stms.size() - 1).accept(this, arg);
+ }
+ return false;
+ }
+
+ public Boolean visit(BreakStmt n, Boolean arg) {
+ // Bogus in the general case
+ if (arg) {
+ return true;
+ }
+ return n.getId() != null;
+ }
+
+ public Boolean visit(CatchClause n, Boolean arg) {
+ return n.getCatchBlock().accept(this, arg);
+ }
+
+ public Boolean visit(ContinueStmt n, Boolean arg) {
+ // Bogus in the general case
+ if (arg) {
+ return true;
+ }
+ return n.getId() != null;
+ }
+
+ public Boolean visit(DoStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(EmptyStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ExplicitConstructorInvocationStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ExpressionStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(ForeachStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(ForStmt n, Boolean arg) {
+ return n.getBody().accept(ANALYZER_VISITOR, arg);
+ }
+
+ public Boolean visit(IfStmt n, Boolean arg) {
+ if (n.getElseStmt() != null) {
+ return n.getThenStmt().accept(this, arg) && n.getElseStmt().accept(this, arg);
+ }
+ return false;
+ }
+
+ public Boolean visit(LabeledStmt n, Boolean arg) {
+ return n.getStmt().accept(this, arg);
+ }
+
+ public Boolean visit(ReturnStmt n, Boolean arg) {
+ return true;
+ }
+
+ public Boolean visit(SwitchEntryStmt n, Boolean arg) {
+ if (n.getStmts() != null) {
+ List<Statement> stms = n.getStmts();
+ return stms.get(stms.size() - 1).accept(this, arg);
+ }
+ return false;
+ }
+
+ public Boolean visit(SwitchStmt n, Boolean arg) {
+ /*
+ List<SwitchEntryStmt> entries = n.getEntries();
+ for (int i = 0; i < array.length; i++) {
+ array_type array_element = array[i];
+
+ }
+ */
+ return true;
+ }
+
+ public Boolean visit(SynchronizedStmt n, Boolean arg) {
+ return n.getBlock().accept(this, arg);
+ }
+
+ public Boolean visit(ThrowStmt n, Boolean arg) {
+ return true;
+ }
+
+ public Boolean visit(TryStmt n, Boolean arg) {
+ if (n.getFinallyBlock() != null) {
+ return n.getFinallyBlock().accept(this, arg);
+ }
+ if (n.getCatchs() != null) {
+ for (CatchClause c : n.getCatchs()) {
+ boolean brk = c.accept(this, arg);
+ if (!brk) {
+ return false;
+ }
+ }
+ }
+ return n.getTryBlock().accept(this, arg);
+ }
+
+ public Boolean visit(TypeDeclarationStmt n, Boolean arg) {
+ return false;
+ }
+
+ public Boolean visit(WhileStmt n, Boolean arg) {
+ return n.getBody().accept(this, arg);
+ }
+
+ public Boolean visit(WildcardType n, Boolean arg) {
+ if (n.getExtends() != null) {
+ n.getExtends().accept(this, arg);
+ }
+ if (n.getSuper() != null) {
+ n.getSuper().accept(this, arg);
+ }
+ return null;
+ }
+} \ No newline at end of file