web-dev-qa-db-ja.com

JavaScriptパーサーPython

少なくともCにはJavaScriptパーサーがあり、Java(Mozilla)、JavaScript(再びMozilla)およびRubyにあります。現在Pythonには何かありますか?

JavaScriptインタープリター自体は必要ありません。ECMA-262標準に準拠したパーサーだけが必要です。

簡単なグーグル検索ですぐに答えが見つからなかったので、SOコミュニティ。

47
Claudiu

[〜#〜] antlr [〜#〜] 、言語認識のためのもう1つのツールは、アクションを含む文法記述から認識エンジン、インタープリター、コンパイラー、およびトランスレーターを構築するためのフレームワークを提供する言語ツールです。さまざまなターゲット言語。

[〜#〜] antlr [〜#〜] サイトは、 JavaScript用の1つ を含む多くの文法を提供します。

たまたま Python API が利用可能です-文法から生成されたレクサー(認識機能)を直接Python(幸運)から呼び出すことができます。

17
gimel

現在、 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オブジェクトからphonename、および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]'"}
37
alecxe

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)
11
David

Esprima.jsをPythonに翻訳しました:

https://github.com/PiotrDabkowski/pyjsparser

これは手動翻訳なので、非常に高速で、angular.jsファイルの解析に約1秒かかります(1秒あたり10万文字)。 ECMAScript 5.1全体とバージョン6の一部(たとえば、矢印関数、constletなど)をサポートしています。

あるいは、esprimaの新しいバージョンの 自動翻訳 を使用して、pythonが動作し、はJavaScript 6全体をサポートします!

9
Piotr Dabkowski

あなたは試すことができます python-spidermonkey これは spidermonkey のラッパーです。これはMozillaのJavaScriptのC実装のコードネームです。

3
swamy