aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/ir/debug/JSONWriter.java')
-rw-r--r--src/jdk/nashorn/internal/ir/debug/JSONWriter.java1076
1 files changed, 0 insertions, 1076 deletions
diff --git a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
deleted file mode 100644
index b72d8996..00000000
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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 General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.ir.debug;
-
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
-import java.util.ArrayList;
-import java.util.List;
-import jdk.nashorn.internal.ir.AccessNode;
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.BlockStatement;
-import jdk.nashorn.internal.ir.BreakNode;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.CaseNode;
-import jdk.nashorn.internal.ir.CatchNode;
-import jdk.nashorn.internal.ir.ContinueNode;
-import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ExpressionStatement;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.IfNode;
-import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.JoinPredecessorExpression;
-import jdk.nashorn.internal.ir.LabelNode;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.SplitNode;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.SwitchNode;
-import jdk.nashorn.internal.ir.TernaryNode;
-import jdk.nashorn.internal.ir.ThrowNode;
-import jdk.nashorn.internal.ir.TryNode;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.WhileNode;
-import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
-import jdk.nashorn.internal.parser.JSONParser;
-import jdk.nashorn.internal.parser.Lexer.RegexToken;
-import jdk.nashorn.internal.parser.Parser;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.ParserException;
-import jdk.nashorn.internal.runtime.Source;
-
-/**
- * This IR writer produces a JSON string that represents AST as a JSON string.
- */
-public final class JSONWriter extends SimpleNodeVisitor {
-
- /**
- * Returns AST as JSON compatible string.
- *
- * @param context context
- * @param code code to be parsed
- * @param name name of the code source (used for location)
- * @param includeLoc tells whether to include location information for nodes or not
- * @return JSON string representation of AST of the supplied code
- */
- public static String parse(final Context context, final String code, final String name, final boolean includeLoc) {
- final Parser parser = new Parser(context.getEnv(), sourceFor(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class));
- final JSONWriter jsonWriter = new JSONWriter(includeLoc);
- try {
- final FunctionNode functionNode = parser.parse(); //symbol name is ":program", default
- functionNode.accept(jsonWriter);
- return jsonWriter.getString();
- } catch (final ParserException e) {
- e.throwAsEcmaException();
- return null;
- }
- }
-
- @Override
- public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinPredecessorExpression) {
- final Expression expr = joinPredecessorExpression.getExpression();
- if(expr != null) {
- expr.accept(this);
- } else {
- nullValue();
- }
- return false;
- }
-
- @Override
- protected boolean enterDefault(final Node node) {
- objectStart();
- location(node);
-
- return true;
- }
-
- private boolean leave() {
- objectEnd();
- return false;
- }
-
- @Override
- protected Node leaveDefault(final Node node) {
- objectEnd();
- return null;
- }
-
- @Override
- public boolean enterAccessNode(final AccessNode accessNode) {
- enterDefault(accessNode);
-
- type("MemberExpression");
- comma();
-
- property("object");
- accessNode.getBase().accept(this);
- comma();
-
- property("property", accessNode.getProperty());
- comma();
-
- property("computed", false);
-
- return leave();
- }
-
- @Override
- public boolean enterBlock(final Block block) {
- enterDefault(block);
-
- type("BlockStatement");
- comma();
-
- array("body", block.getStatements());
-
- return leave();
- }
-
- @Override
- public boolean enterBinaryNode(final BinaryNode binaryNode) {
- enterDefault(binaryNode);
-
- final String name;
- if (binaryNode.isAssignment()) {
- name = "AssignmentExpression";
- } else if (binaryNode.isLogical()) {
- name = "LogicalExpression";
- } else {
- name = "BinaryExpression";
- }
-
- type(name);
- comma();
-
- property("operator", binaryNode.tokenType().getName());
- comma();
-
- property("left");
- binaryNode.lhs().accept(this);
- comma();
-
- property("right");
- binaryNode.rhs().accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterBreakNode(final BreakNode breakNode) {
- enterDefault(breakNode);
-
- type("BreakStatement");
- comma();
-
- final String label = breakNode.getLabelName();
- if(label != null) {
- property("label", label);
- } else {
- property("label");
- nullValue();
- }
-
- return leave();
- }
-
- @Override
- public boolean enterCallNode(final CallNode callNode) {
- enterDefault(callNode);
-
- type("CallExpression");
- comma();
-
- property("callee");
- callNode.getFunction().accept(this);
- comma();
-
- array("arguments", callNode.getArgs());
-
- return leave();
- }
-
- @Override
- public boolean enterCaseNode(final CaseNode caseNode) {
- enterDefault(caseNode);
-
- type("SwitchCase");
- comma();
-
- final Node test = caseNode.getTest();
- property("test");
- if (test != null) {
- test.accept(this);
- } else {
- nullValue();
- }
- comma();
-
- array("consequent", caseNode.getBody().getStatements());
-
- return leave();
- }
-
- @Override
- public boolean enterCatchNode(final CatchNode catchNode) {
- enterDefault(catchNode);
-
- type("CatchClause");
- comma();
-
- property("param");
- catchNode.getException().accept(this);
- comma();
-
- final Node guard = catchNode.getExceptionCondition();
- if (guard != null) {
- property("guard");
- guard.accept(this);
- comma();
- }
-
- property("body");
- catchNode.getBody().accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterContinueNode(final ContinueNode continueNode) {
- enterDefault(continueNode);
-
- type("ContinueStatement");
- comma();
-
- final String label = continueNode.getLabelName();
- if(label != null) {
- property("label", label);
- } else {
- property("label");
- nullValue();
- }
-
- return leave();
- }
-
- @Override
- public boolean enterEmptyNode(final EmptyNode emptyNode) {
- enterDefault(emptyNode);
-
- type("EmptyStatement");
-
- return leave();
- }
-
- @Override
- public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
- // handle debugger statement
- final Node expression = expressionStatement.getExpression();
- if (expression instanceof RuntimeNode) {
- expression.accept(this);
- return false;
- }
-
- enterDefault(expressionStatement);
-
- type("ExpressionStatement");
- comma();
-
- property("expression");
- expression.accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterBlockStatement(final BlockStatement blockStatement) {
- enterDefault(blockStatement);
-
- type("BlockStatement");
- comma();
-
- property("block");
- blockStatement.getBlock().accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterForNode(final ForNode forNode) {
- enterDefault(forNode);
-
- if (forNode.isForIn() || (forNode.isForEach() && forNode.getInit() != null)) {
- type("ForInStatement");
- comma();
-
- final Node init = forNode.getInit();
- assert init != null;
- property("left");
- init.accept(this);
- comma();
-
- final Node modify = forNode.getModify();
- assert modify != null;
- property("right");
- modify.accept(this);
- comma();
-
- property("body");
- forNode.getBody().accept(this);
- comma();
-
- property("each", forNode.isForEach());
- } else {
- type("ForStatement");
- comma();
-
- final Node init = forNode.getInit();
- property("init");
- if (init != null) {
- init.accept(this);
- } else {
- nullValue();
- }
- comma();
-
- final Node test = forNode.getTest();
- property("test");
- if (test != null) {
- test.accept(this);
- } else {
- nullValue();
- }
- comma();
-
- final Node update = forNode.getModify();
- property("update");
- if (update != null) {
- update.accept(this);
- } else {
- nullValue();
- }
- comma();
-
- property("body");
- forNode.getBody().accept(this);
- }
-
- return leave();
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- final boolean program = functionNode.isProgram();
- if (program) {
- return emitProgram(functionNode);
- }
-
- enterDefault(functionNode);
- final String name;
- if (functionNode.isDeclared()) {
- name = "FunctionDeclaration";
- } else {
- name = "FunctionExpression";
- }
- type(name);
- comma();
-
- property("id");
- final FunctionNode.Kind kind = functionNode.getKind();
- if (functionNode.isAnonymous() || kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
- nullValue();
- } else {
- functionNode.getIdent().accept(this);
- }
- comma();
-
- array("params", functionNode.getParameters());
- comma();
-
- arrayStart("defaults");
- arrayEnd();
- comma();
-
- property("rest");
- nullValue();
- comma();
-
- property("body");
- functionNode.getBody().accept(this);
- comma();
-
- property("generator", false);
- comma();
-
- property("expression", false);
-
- return leave();
- }
-
- private boolean emitProgram(final FunctionNode functionNode) {
- enterDefault(functionNode);
- type("Program");
- comma();
-
- // body consists of nested functions and statements
- final List<Statement> stats = functionNode.getBody().getStatements();
- final int size = stats.size();
- int idx = 0;
- arrayStart("body");
-
- for (final Node stat : stats) {
- stat.accept(this);
- if (idx != (size - 1)) {
- comma();
- }
- idx++;
- }
- arrayEnd();
-
- return leave();
- }
-
- @Override
- public boolean enterIdentNode(final IdentNode identNode) {
- enterDefault(identNode);
-
- final String name = identNode.getName();
- if ("this".equals(name)) {
- type("ThisExpression");
- } else {
- type("Identifier");
- comma();
- property("name", identNode.getName());
- }
-
- return leave();
- }
-
- @Override
- public boolean enterIfNode(final IfNode ifNode) {
- enterDefault(ifNode);
-
- type("IfStatement");
- comma();
-
- property("test");
- ifNode.getTest().accept(this);
- comma();
-
- property("consequent");
- ifNode.getPass().accept(this);
- final Node elsePart = ifNode.getFail();
- comma();
-
- property("alternate");
- if (elsePart != null) {
- elsePart.accept(this);
- } else {
- nullValue();
- }
-
- return leave();
- }
-
- @Override
- public boolean enterIndexNode(final IndexNode indexNode) {
- enterDefault(indexNode);
-
- type("MemberExpression");
- comma();
-
- property("object");
- indexNode.getBase().accept(this);
- comma();
-
- property("property");
- indexNode.getIndex().accept(this);
- comma();
-
- property("computed", true);
-
- return leave();
- }
-
- @Override
- public boolean enterLabelNode(final LabelNode labelNode) {
- enterDefault(labelNode);
-
- type("LabeledStatement");
- comma();
-
- property("label", labelNode.getLabelName());
- comma();
-
- property("body");
- labelNode.getBody().accept(this);
-
- return leave();
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public boolean enterLiteralNode(final LiteralNode literalNode) {
- enterDefault(literalNode);
-
- if (literalNode instanceof LiteralNode.ArrayLiteralNode) {
- type("ArrayExpression");
- comma();
-
- array("elements", ((LiteralNode.ArrayLiteralNode)literalNode).getElementExpressions());
- } else {
- type("Literal");
- comma();
-
- property("value");
- final Object value = literalNode.getValue();
- if (value instanceof RegexToken) {
- // encode RegExp literals as Strings of the form /.../<flags>
- final RegexToken regex = (RegexToken)value;
- final StringBuilder regexBuf = new StringBuilder();
- regexBuf.append('/');
- regexBuf.append(regex.getExpression());
- regexBuf.append('/');
- regexBuf.append(regex.getOptions());
- buf.append(quote(regexBuf.toString()));
- } else {
- final String str = literalNode.getString();
- // encode every String literal with prefix '$' so that script
- // can differentiate b/w RegExps as Strings and Strings.
- buf.append(literalNode.isString()? quote("$" + str) : str);
- }
- }
-
- return leave();
- }
-
- @Override
- public boolean enterObjectNode(final ObjectNode objectNode) {
- enterDefault(objectNode);
-
- type("ObjectExpression");
- comma();
-
- array("properties", objectNode.getElements());
-
- return leave();
- }
-
- @Override
- public boolean enterPropertyNode(final PropertyNode propertyNode) {
- final Node key = propertyNode.getKey();
-
- final Node value = propertyNode.getValue();
- if (value != null) {
- objectStart();
- location(propertyNode);
-
- property("key");
- key.accept(this);
- comma();
-
- property("value");
- value.accept(this);
- comma();
-
- property("kind", "init");
-
- objectEnd();
- } else {
- // getter
- final Node getter = propertyNode.getGetter();
- if (getter != null) {
- objectStart();
- location(propertyNode);
-
- property("key");
- key.accept(this);
- comma();
-
- property("value");
- getter.accept(this);
- comma();
-
- property("kind", "get");
-
- objectEnd();
- }
-
- // setter
- final Node setter = propertyNode.getSetter();
- if (setter != null) {
- if (getter != null) {
- comma();
- }
- objectStart();
- location(propertyNode);
-
- property("key");
- key.accept(this);
- comma();
-
- property("value");
- setter.accept(this);
- comma();
-
- property("kind", "set");
-
- objectEnd();
- }
- }
-
- return false;
- }
-
- @Override
- public boolean enterReturnNode(final ReturnNode returnNode) {
- enterDefault(returnNode);
-
- type("ReturnStatement");
- comma();
-
- final Node arg = returnNode.getExpression();
- property("argument");
- if (arg != null) {
- arg.accept(this);
- } else {
- nullValue();
- }
-
- return leave();
- }
-
- @Override
- public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
- final RuntimeNode.Request req = runtimeNode.getRequest();
-
- if (req == RuntimeNode.Request.DEBUGGER) {
- enterDefault(runtimeNode);
- type("DebuggerStatement");
- return leave();
- }
-
- return false;
- }
-
- @Override
- public boolean enterSplitNode(final SplitNode splitNode) {
- return false;
- }
-
- @Override
- public boolean enterSwitchNode(final SwitchNode switchNode) {
- enterDefault(switchNode);
-
- type("SwitchStatement");
- comma();
-
- property("discriminant");
- switchNode.getExpression().accept(this);
- comma();
-
- array("cases", switchNode.getCases());
-
- return leave();
- }
-
- @Override
- public boolean enterTernaryNode(final TernaryNode ternaryNode) {
- enterDefault(ternaryNode);
-
- type("ConditionalExpression");
- comma();
-
- property("test");
- ternaryNode.getTest().accept(this);
- comma();
-
- property("consequent");
- ternaryNode.getTrueExpression().accept(this);
- comma();
-
- property("alternate");
- ternaryNode.getFalseExpression().accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterThrowNode(final ThrowNode throwNode) {
- enterDefault(throwNode);
-
- type("ThrowStatement");
- comma();
-
- property("argument");
- throwNode.getExpression().accept(this);
-
- return leave();
- }
-
- @Override
- public boolean enterTryNode(final TryNode tryNode) {
- enterDefault(tryNode);
-
- type("TryStatement");
- comma();
-
- property("block");
- tryNode.getBody().accept(this);
- comma();
-
-
- final List<? extends Node> catches = tryNode.getCatches();
- final List<CatchNode> guarded = new ArrayList<>();
- CatchNode unguarded = null;
- if (catches != null) {
- for (final Node n : catches) {
- final CatchNode cn = (CatchNode)n;
- if (cn.getExceptionCondition() != null) {
- guarded.add(cn);
- } else {
- assert unguarded == null: "too many unguarded?";
- unguarded = cn;
- }
- }
- }
-
- array("guardedHandlers", guarded);
- comma();
-
- property("handler");
- if (unguarded != null) {
- unguarded.accept(this);
- } else {
- nullValue();
- }
- comma();
-
- property("finalizer");
- final Node finallyNode = tryNode.getFinallyBody();
- if (finallyNode != null) {
- finallyNode.accept(this);
- } else {
- nullValue();
- }
-
- return leave();
- }
-
- @Override
- public boolean enterUnaryNode(final UnaryNode unaryNode) {
- enterDefault(unaryNode);
-
- final TokenType tokenType = unaryNode.tokenType();
- if (tokenType == TokenType.NEW) {
- type("NewExpression");
- comma();
-
- final CallNode callNode = (CallNode)unaryNode.getExpression();
- property("callee");
- callNode.getFunction().accept(this);
- comma();
-
- array("arguments", callNode.getArgs());
- } else {
- final String operator;
- final boolean prefix;
- switch (tokenType) {
- case INCPOSTFIX:
- prefix = false;
- operator = "++";
- break;
- case DECPOSTFIX:
- prefix = false;
- operator = "--";
- break;
- case INCPREFIX:
- operator = "++";
- prefix = true;
- break;
- case DECPREFIX:
- operator = "--";
- prefix = true;
- break;
- default:
- prefix = true;
- operator = tokenType.getName();
- break;
- }
-
- type(unaryNode.isAssignment()? "UpdateExpression" : "UnaryExpression");
- comma();
-
- property("operator", operator);
- comma();
-
- property("prefix", prefix);
- comma();
-
- property("argument");
- unaryNode.getExpression().accept(this);
- }
-
- return leave();
- }
-
- @Override
- public boolean enterVarNode(final VarNode varNode) {
- final Node init = varNode.getInit();
- if (init instanceof FunctionNode && ((FunctionNode)init).isDeclared()) {
- // function declaration - don't emit VariableDeclaration instead
- // just emit FunctionDeclaration using 'init' Node.
- init.accept(this);
- return false;
- }
-
- enterDefault(varNode);
-
- type("VariableDeclaration");
- comma();
-
- arrayStart("declarations");
-
- // VariableDeclarator
- objectStart();
- location(varNode.getName());
-
- type("VariableDeclarator");
- comma();
-
- property("id");
- varNode.getName().accept(this);
- comma();
-
- property("init");
- if (init != null) {
- init.accept(this);
- } else {
- nullValue();
- }
-
- // VariableDeclarator
- objectEnd();
-
- // declarations
- arrayEnd();
-
- return leave();
- }
-
- @Override
- public boolean enterWhileNode(final WhileNode whileNode) {
- enterDefault(whileNode);
-
- type(whileNode.isDoWhile() ? "DoWhileStatement" : "WhileStatement");
- comma();
-
- if (whileNode.isDoWhile()) {
- property("body");
- whileNode.getBody().accept(this);
- comma();
-
- property("test");
- whileNode.getTest().accept(this);
- } else {
- property("test");
- whileNode.getTest().accept(this);
- comma();
-
- property("body");
- whileNode.getBody().accept(this);
- }
-
- return leave();
- }
-
- @Override
- public boolean enterWithNode(final WithNode withNode) {
- enterDefault(withNode);
-
- type("WithStatement");
- comma();
-
- property("object");
- withNode.getExpression().accept(this);
- comma();
-
- property("body");
- withNode.getBody().accept(this);
-
- return leave();
- }
-
- // Internals below
-
- private JSONWriter(final boolean includeLocation) {
- this.buf = new StringBuilder();
- this.includeLocation = includeLocation;
- }
-
- private final StringBuilder buf;
- private final boolean includeLocation;
-
- private String getString() {
- return buf.toString();
- }
-
- private void property(final String key, final String value, final boolean escape) {
- buf.append('"');
- buf.append(key);
- buf.append("\":");
- if (value != null) {
- if (escape) {
- buf.append('"');
- }
- buf.append(value);
- if (escape) {
- buf.append('"');
- }
- }
- }
-
- private void property(final String key, final String value) {
- property(key, value, true);
- }
-
- private void property(final String key, final boolean value) {
- property(key, Boolean.toString(value), false);
- }
-
- private void property(final String key, final int value) {
- property(key, Integer.toString(value), false);
- }
-
- private void property(final String key) {
- property(key, null);
- }
-
- private void type(final String value) {
- property("type", value);
- }
-
- private void objectStart(final String name) {
- buf.append('"');
- buf.append(name);
- buf.append("\":{");
- }
-
- private void objectStart() {
- buf.append('{');
- }
-
- private void objectEnd() {
- buf.append('}');
- }
-
- private void array(final String name, final List<? extends Node> nodes) {
- // The size, idx comparison is just to avoid trailing comma..
- final int size = nodes.size();
- int idx = 0;
- arrayStart(name);
- for (final Node node : nodes) {
- if (node != null) {
- node.accept(this);
- } else {
- nullValue();
- }
- if (idx != (size - 1)) {
- comma();
- }
- idx++;
- }
- arrayEnd();
- }
-
- private void arrayStart(final String name) {
- buf.append('"');
- buf.append(name);
- buf.append('"');
- buf.append(':');
- buf.append('[');
- }
-
- private void arrayEnd() {
- buf.append(']');
- }
-
- private void comma() {
- buf.append(',');
- }
-
- private void nullValue() {
- buf.append("null");
- }
-
- private void location(final Node node) {
- if (includeLocation) {
- objectStart("loc");
-
- // source name
- final Source src = lc.getCurrentFunction().getSource();
- property("source", src.getName());
- comma();
-
- // start position
- objectStart("start");
- final int start = node.getStart();
- property("line", src.getLine(start));
- comma();
- property("column", src.getColumn(start));
- objectEnd();
- comma();
-
- // end position
- objectStart("end");
- final int end = node.getFinish();
- property("line", src.getLine(end));
- comma();
- property("column", src.getColumn(end));
- objectEnd();
-
- // end 'loc'
- objectEnd();
-
- comma();
- }
- }
-
- private static String quote(final String str) {
- return JSONParser.quote(str);
- }
-}