diff options
author | Matt A. Tobin <email@mattatobin.com> | 2020-01-15 14:56:04 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2020-01-15 14:56:04 -0500 |
commit | 6168dbe21f5f83b906e562ea0ab232d499b275a6 (patch) | |
tree | 658a4b27554c85ebcaad655fc83f2c2bb99e8e80 /parser/html/java/htmlparser/translator-src | |
parent | 09314667a692fedff8564fc347c8a3663474faa6 (diff) | |
download | UXP-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')
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 |