1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  * 
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  * 
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  * 
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  * 
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * Nashorn parser API usage.
  26  *
  27  * @test
  28  * @option -scripting
  29  * @run
  30  */
  31 
  32 function Parser() {
  33     // create nashorn parser
  34     this._parser = Parser.create();
  35 }
  36 
  37 // Java types used
  38 Parser.Diagnostic = Java.type("jdk.nashorn.api.tree.Diagnostic");
  39 Parser.SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
  40 Parser.Tree = Java.type("jdk.nashorn.api.tree.Tree");
  41 Parser.List = Java.type("java.util.List");
  42 Parser.Enum = Java.type("java.lang.Enum");
  43 
  44 // function to parse the script and return script friendly object
  45 Parser.prototype.parse = function(name, script, listener) {
  46     var tree = this._parser.parse(name, script, listener);
  47     tree.accept(new Parser.SimpleTreeVisitor(), null);
  48     return this.convert(tree);
  49 }
  50 
  51 Parser.create = function() {
  52     return Java.type("jdk.nashorn.api.tree.Parser").create();
  53 }
  54 
  55 // convert Nashorn parser Tree, Diagnostic as a script friendly object
  56 Parser.prototype.convert = function(tree) {
  57     if (!tree || typeof tree != 'object' || tree instanceof java.lang.Long) {
  58         return tree;
  59     }
  60 
  61     var obj = Object.bindProperties({}, tree);
  62     var result = {};
  63     for (var i in obj) {
  64         var val = obj[i];
  65         // skip these ES6 specific properties to reduce noise
  66         // in the output - unless there were set to true
  67         if (typeof(val) == 'boolean' && val == false) {
  68             switch (i) {
  69                 case "computed":
  70                 case "static":
  71                 case "restParameter":
  72                 case "this":
  73                 case "super":
  74                 case "star":
  75                 case "default":
  76                 case "starDefaultStar":
  77                 case "arrow":
  78                 case "generator":
  79                 case "let":
  80                 case "const":
  81                     continue;
  82              }
  83         }
  84 
  85         if (val instanceof Parser.Tree) {
  86             result[i] = this.convert(val);
  87         } else if (val instanceof Parser.List) {
  88             var arr = new Array(val.size());
  89             for (var j in val) {
  90                 arr[j] = this.convert(val[j]);
  91             }
  92 
  93             result[i] = arr;
  94         } else {
  95             switch (typeof val) {
  96                 case 'number':
  97                 case 'string':
  98                 case 'boolean':
  99                     result[i] = String(val);
 100                     break;
 101                 default:
 102                     if (val instanceof java.lang.Long || val instanceof Parser.Enum) {
 103                         result[i] = String(val);
 104                     }
 105             }
 106         }
 107     }
 108     return result;
 109 }
 110 
 111 function processFiles(subdir) {
 112     var File = Java.type("java.io.File");
 113     var files = new File(__DIR__ + subdir).listFiles();
 114     java.util.Arrays.sort(files);
 115     for each (var file in files) {
 116         if (file.name.endsWith(".js")) {
 117             var script = readFully(file);
 118             var parser = new Parser();
 119             var tree = parser.parse(subdir + "/" + file.name, script,
 120                 function(diagnostic) {
 121                     print(JSON.stringify(parser.convert(diagnostic), null, 2).replace(/\\r/g, ''));
 122                     print(",");
 123                 });
 124 
 125             if (tree != null) {
 126                 print(JSON.stringify(tree, null, 2));
 127                 print(",");
 128             }
 129         }
 130     }
 131 }
 132 
 133 // parse files in parsertests directory
 134 function main() {
 135     print("[");
 136 
 137     processFiles("parsertests");
 138     processFiles("parsernegativetests");
 139 
 140     // parse this file first!
 141     var script = readFully(__FILE__);
 142     var tree = new Parser().parse("parserapi.js", script, null);
 143     print(JSON.stringify(tree, null, 2));
 144     print("]");
 145 }
 146 
 147 main();