少なくともCにはJavaScriptパーサーがあり、Java(Mozilla)、JavaScript(再びMozilla)およびRubyにあります。現在Pythonには何かありますか?
JavaScriptインタープリター自体は必要ありません。ECMA-262標準に準拠したパーサーだけが必要です。
簡単なグーグル検索ですぐに答えが見つからなかったので、SOコミュニティ。
[〜#〜] antlr [〜#〜] 、言語認識のためのもう1つのツールは、アクションを含む文法記述から認識エンジン、インタープリター、コンパイラー、およびトランスレーターを構築するためのフレームワークを提供する言語ツールです。さまざまなターゲット言語。
[〜#〜] antlr [〜#〜] サイトは、 JavaScript用の1つ を含む多くの文法を提供します。
たまたま Python API が利用可能です-文法から生成されたレクサー(認識機能)を直接Python(幸運)から呼び出すことができます。
現在、 slimit
と呼ばれる少なくとも1つの優れたツールがあります。
SlimItはPythonで書かれたJavaScriptミニファイアーです。 JavaScriptをよりコンパクトなコードにコンパイルして、ダウンロードと実行を高速化します。
SlimItは、JavaScriptパーサー、レクサー、プリティプリンター、ツリービジターを含むライブラリも提供します。
デモ:
次のjavascriptコードがあるとします。
$.ajax({
type: "POST",
url: 'http://www.example.com',
data: {
email: '[email protected]',
phone: '9999999999',
name: 'XYZ'
}
});
次に、email
オブジェクトからphone
、name
、およびdata
の値を取得する必要があります。
ここでのアイデアは、slimit
パーサーをインスタンス化し、すべてのノードにアクセスし、すべての割り当てをフィルター処理して、辞書に入れることです。
from slimit import ast
from slimit.parser import Parser
from slimit.visitors import nodevisitor
data = """
$.ajax({
type: "POST",
url: 'http://www.example.com',
data: {
email: '[email protected]',
phone: '9999999999',
name: 'XYZ'
}
});
"""
parser = Parser()
tree = parser.parse(data)
fields = {getattr(node.left, 'value', ''): getattr(node.right, 'value', '')
for node in nodevisitor.visit(tree)
if isinstance(node, ast.Assign)}
print fields
以下を印刷します。
{'name': "'XYZ'",
'url': "'http://www.example.com'",
'type': '"POST"',
'phone': "'9999999999'",
'data': '',
'email': "'[email protected]'"}
Pibが述べたように、 pynarcissus はPythonで書かれたJavascriptトークナイザーです。それはいくつかのラフなエッジを持っているようですが、これまでのところ私が達成したいもののためにうまく機能しています。
更新:pynarcissusで別の亀裂を取りました。以下は、システムのような訪問者パターンでPyNarcissusを使用するための作業方向です。残念ながら、現在のクライアントは私の実験の次のイテレーションを購入し、それを公開ソースにしないことに決めました。以下のコードのよりクリーンなバージョンはGistにあります here
from pynarcissus import jsparser
from collections import defaultdict
class Visitor(object):
CHILD_ATTRS = ['thenPart', 'elsePart', 'expression', 'body', 'initializer']
def __init__(self, filepath):
self.filepath = filepath
#List of functions by line # and set of names
self.functions = defaultdict(set)
with open(filepath) as myFile:
self.source = myFile.read()
self.root = jsparser.parse(self.source, self.filepath)
self.visit(self.root)
def look4Childen(self, node):
for attr in self.CHILD_ATTRS:
child = getattr(node, attr, None)
if child:
self.visit(child)
def visit_NOOP(self, node):
pass
def visit_FUNCTION(self, node):
# Named functions
if node.type == "FUNCTION" and getattr(node, "name", None):
print str(node.lineno) + " | function " + node.name + " | " + self.source[node.start:node.end]
def visit_IDENTIFIER(self, node):
# Anonymous functions declared with var name = function() {};
try:
if node.type == "IDENTIFIER" and hasattr(node, "initializer") and node.initializer.type == "FUNCTION":
print str(node.lineno) + " | function " + node.name + " | " + self.source[node.start:node.initializer.end]
except Exception as e:
pass
def visit_PROPERTY_INIT(self, node):
# Anonymous functions declared as a property of an object
try:
if node.type == "PROPERTY_INIT" and node[1].type == "FUNCTION":
print str(node.lineno) + " | function " + node[0].value + " | " + self.source[node.start:node[1].end]
except Exception as e:
pass
def visit(self, root):
call = lambda n: getattr(self, "visit_%s" % n.type, self.visit_NOOP)(n)
call(root)
self.look4Childen(root)
for node in root:
self.visit(node)
filepath = r"C:\Users\dward\Dropbox\juggernaut2\juggernaut\parser\test\data\jasmine.js"
outerspace = Visitor(filepath)
Esprima.jsをPythonに翻訳しました:
https://github.com/PiotrDabkowski/pyjsparser
これは手動翻訳なので、非常に高速で、angular.js
ファイルの解析に約1秒かかります(1秒あたり10万文字)。 ECMAScript 5.1全体とバージョン6の一部(たとえば、矢印関数、const
、let
など)をサポートしています。
あるいは、esprimaの新しいバージョンの 自動翻訳 を使用して、pythonが動作し、はJavaScript 6全体をサポートします!
あなたは試すことができます python-spidermonkey これは spidermonkey のラッパーです。これはMozillaのJavaScriptのC実装のコードネームです。