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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.api.tree;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.PrintWriter;
  31 import java.io.Reader;
  32 import java.net.URL;
  33 import java.nio.file.Path;
  34 import java.util.Map;
  35 import java.util.Objects;
  36 import jdk.nashorn.api.scripting.NashornException;
  37 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  38 import jdk.nashorn.internal.ir.FunctionNode;
  39 import jdk.nashorn.internal.runtime.Context;
  40 import jdk.nashorn.internal.runtime.ErrorManager;
  41 import jdk.nashorn.internal.runtime.JSType;
  42 import jdk.nashorn.internal.runtime.ParserException;
  43 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  44 import jdk.nashorn.internal.runtime.Source;
  45 import jdk.nashorn.internal.runtime.options.Options;
  46 
  47 final class ParserImpl implements Parser {
  48 
  49     private final ScriptEnvironment env;
  50     
  51     ParserImpl(final String... args) throws IllegalArgumentException {
  52        Objects.requireNonNull(args);
  53        Options options = new Options("nashorn");
  54        options.process(args);
  55        this.env = new ScriptEnvironment(options, 
  56                new PrintWriter(System.out), new PrintWriter(System.err));   
  57     }
  58     
  59     @Override
  60     public CompilationUnitTree parse(final File file, final DiagnosticListener listener) throws IOException, NashornException {
  61         Objects.requireNonNull(file);
  62         final Source src = Source.sourceFor(file.getName(), file);
  63         return translate(makeParser(src, listener).parse());
  64     }
  65 
  66     @Override
  67     public CompilationUnitTree parse(final Path path, final DiagnosticListener listener) throws IOException, NashornException {
  68         Objects.requireNonNull(path);
  69         final Source src = Source.sourceFor(path.toString(), path);
  70         return translate(makeParser(src, listener).parse());
  71     }
  72 
  73     @Override
  74     public CompilationUnitTree parse(final URL url, final DiagnosticListener listener) throws IOException, NashornException {
  75         final Source src = Source.sourceFor(url.toString(), url);
  76         return translate(makeParser(src, listener).parse());
  77     }
  78 
  79     @Override
  80     public CompilationUnitTree parse(final String name, final Reader reader, final DiagnosticListener listener) throws IOException, NashornException {
  81         Objects.requireNonNull(name);
  82         Objects.requireNonNull(reader);
  83         final Source src = Source.sourceFor(name, reader);
  84         return translate(makeParser(src, listener).parse());
  85     }
  86 
  87     @Override
  88     public CompilationUnitTree parse(final String name, final String code, final DiagnosticListener listener) throws NashornException {
  89         final Source src = Source.sourceFor(name, code);
  90         return translate(makeParser(src, listener).parse());
  91     }
  92     
  93     @Override
  94     public CompilationUnitTree parse(final ScriptObjectMirror scriptObj, final DiagnosticListener listener) throws NashornException {
  95         Objects.requireNonNull(scriptObj);
  96         final Map<?,?> map = scriptObj;
  97         if (map.containsKey("script") && map.containsKey("name")) {
  98             final String script = JSType.toString(map.get("script"));
  99             final String name   = JSType.toString(map.get("name"));
 100             final Source src = Source.sourceFor(name, script);
 101             return translate(makeParser(src, listener).parse());
 102         } else {
 103             throw new IllegalArgumentException("can't find 'script' and 'name' properties");
 104         }
 105     }
 106     
 107     private jdk.nashorn.internal.parser.Parser makeParser(final Source source, final DiagnosticListener listener) {
 108         final ErrorManager errMgr = listener != null? new ListenerErrorManager(listener) : new Context.ThrowErrorManager();
 109         return new jdk.nashorn.internal.parser.Parser(env, source, errMgr);
 110     }
 111     
 112     private static class ListenerErrorManager extends ErrorManager {
 113         private final DiagnosticListener listener;
 114         
 115         ListenerErrorManager(final DiagnosticListener listener) {
 116             // null check
 117             listener.getClass();
 118             this.listener = listener;
 119         }
 120         
 121         @Override
 122         public void error(final String msg) {
 123             error(new ParserException(msg));
 124         }
 125         
 126         @Override
 127         public void error(final ParserException e) {
 128             listener.report(new DiagnosticImpl(e, Diagnostic.Kind.ERROR));
 129         }
 130         
 131         @Override
 132         public void warning(final String msg) {
 133             warning(new ParserException(msg));
 134         }
 135         
 136         @Override
 137         public void warning(final ParserException e) {
 138             listener.report(new DiagnosticImpl(e, Diagnostic.Kind.WARNING));
 139         }
 140     }
 141     
 142     private CompilationUnitTree translate(final FunctionNode node) {
 143         return new IRTranslator().translate(node);
 144     }
 145 }