package en;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONML;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* This class is responsible for reading the Javascript source
* and parses the content to JSONMLAst format as discussed in
* http://code.google.com/p/es-lab/wiki/JsonMLASTFormat#AST_Format
*
* Javascript parser is based on an OMeta-based parser for Ecmascript 5, written in Javascript,
* generating a JsonML-based AST
* http://code.google.com/p/es-lab/
*
* This class uses the javax.script API to integrate the script into the JAVA program.
*/
public class JS2AST {
private ScriptEngine engine;
public JS2AST() throws ScriptException {
// jav8 depends in google's V8 javascript engine
ScriptEngineManager factory = new ScriptEngineManager();
engine = factory.getEngineByName("jav8");
// we can use the standard engine or create our own scripting engine
//ScriptEngineManager factory = new ScriptEngineManager();
//engine = factory.getEngineByName("javascript");
// Java Script API does not support load function. This is a hack to include the definition of load into the script
this.engine.put("JS2AST", this);
this.engine.eval("function load(filename) { JS2AST.load(filename); }");
// prerequisite scripts including the full es5 Javascript parser
load("jslib/json2.js");
load("jslib/lib.js");
load("jslib/ometa-base.js");
load("jslib/es5parser.js");
load("jslib/unicode.js");
}
/**
* Using the es5 parser written in Javascript, invokes the
* parse2AST method of the wrapper (jslib/parse2AST.js) to parse the input file,
* and outputs JSONML array string storing the AST
*
* @param parser Reader for the Javascript parser
* @param jsfile String source of the Javascript file to be parsed
* @throws Exception
*/
public Document createAST(Reader parser, String jsfile) throws Exception{
String ast = null;
try {
engine.eval(parser);
Invocable invocableEngine = (Invocable)engine;
// Store the script in a String
String js = Utils.readFile2String(jsfile);
//String js = getURLContent(codeURL);
// (function name, script source, boolean for position details)
ast = (String)invocableEngine.invokeFunction("parse2AST", js, true);
//AST = invocableEngine.invokeFunction("parse2JSON", js, true);
} catch (Exception ex) {
ex.printStackTrace();
}
return convertToXML(ast);
}
/**
* Using the es5 parser written in Javascript, invokes the
* parse2AST method of the wrapper (jslib/parse2AST.js) to parse the input file,
* and outputs JSONML array string storing the AST
*
* @param parser Reader for the Javascript parser
* @param jslink URL of the Javascript d to be parsed
* @throws Exception
*/
public Document createAST(Reader parser, URL jslink) throws Exception{
String ast = null;
try {
engine.eval(parser);
Invocable invocableEngine = (Invocable)engine;
// Store the script in a String
String js = Utils.getURLContent(jslink);
// (function name, script source, boolean for position details)
ast = (String)invocableEngine.invokeFunction("parse2AST", js, true);
//AST = invocableEngine.invokeFunction("parse2JSON", js, true);
} catch (Exception ex) {
ex.printStackTrace();
}
return convertToXML(ast);
}
/**
* Load content of the file into the script
*
* @param filename Full path of the file
*/
public void load(String filename) throws ScriptException {
try {
this.engine.eval(new FileReader(filename));
}
catch(FileNotFoundException e) {
throw new RuntimeException("Error loading javascript file: " + filename, e);
}
}
/**
* Create an XML Document (org.w3c.dom.Document)
*
* @param ast String in JSONArray format
* @return XML Document
* @throws Exception
*/
public Document convertToXML(String ast) throws Exception{
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
String xmlASTString = null;
try {
JSONArray jsonAST = new JSONArray(ast.toString());
xmlASTString = JSONML.toString(jsonAST);
} catch (JSONException e) {
throw new JSParsingException("Malformed JSON parser output.", e);
}
Document doc = null;
try {
StringReader reader = new StringReader(xmlASTString);
InputSource inputSource = new InputSource(reader);
doc = docBuilder.parse(inputSource);
reader.close();
} catch (Exception e) {
throw new JSParsingException("Failed to interpret the XML AST", e);
}
return doc;
}
}