0

AngularJS Web アプリケーションがあります。

アプリケーションで peg.js を使用したいと考えています。私はちょうど peg.js 文法を書きました: CriteriaValue.pegjs とコマンドラインでパーサーを生成しました: CriteriaValue.js を生成しました pegjs CriteriaValue.pegjs

誰かがパーサーの使い方を説明してくれませんか?

var result = parser.parse('my string'); 動作しません。

プランカーを作成しました: http://plnkr.co/edit/Ae05SeZAjKOQ75B3lvLc?p=preview

4

1 に答える 1

4

簡潔な答え

  • CriteriaValue.jsmodule.exportsで、最初の行を次のように変更します。parser
  • index.html で、<script>CriteriaValue.js が最初になるようにタグを入れ替えます。
  • (オプション) script.js で、実際の値を確認するために、解析の結果を書式設定された JSON 文字列として出力します。

これがプランカーです: http://plnkr.co/edit/kiBp2Na9s4PXpenCzQjx?p=preview

長い答え

元の plunker を実行し、コンソール ログを確認します。2 つのエラーに気付くでしょう:

  • ReferenceError: Can't find variable: parser (script.js:3)
  • ReferenceError: Can't find variable: error (CriteriaValue.js:1)

最初のエラーはparser、script.js または CriteriaValue.js によってグローバル スコープでオブジェクトが作成されていないことが原因です。

CriteriaValue.js を見ると、実際には、生成されたパーサー オブジェクトが存在しない に割り当てられていることがわかりますmodules.export。node.js でパーサーを使用することを想定しているため、これが PEG.js のデフォルトの動作です。エラーが表示される理由は、オブジェクトがないためです。そのためmodule、この存在しないオブジェクトのexportプロパティに割り当てることができません。割り当てを に変更するparserと (PEG.js はstrict モードを使用しないため)、割り当てが可能になり、このエラーが回避parserされ、script.js で使用できるようになります。

最後に、script.js で使用する前にパーサーを作成する必要があります。<script>それがスワップの理由です。

今後 CriteriaValue.js を作成するには、次のようにします。

pegjs --export-var parser CriteriaValue.pegjs

これにより、オブジェクトが のparser代わりに変数に割り当てられるようにファイルが生成されますmodule.exports

AngularJS の出番

@dirkk がコメントで述べたように、パーサーをグローバル変数として定義することは悪い習慣であり、パーサーをサービスとして実装する AngularJS の方法ではありません。

これを行うための最も迅速な (ただし必ずしも最適とは限りません) 方法は、既に生成されている CriteriaValue.js コードを取得し、それをサービスでラップすることです。例えば:

angular.module('yourApp.services', [])
.factory('Parser', function() {
  // The generated code, except replace "parser = " with "return "
});

別のオプションは、.pegjs ファイルを取得し、以下を使用してクライアントでパーサーを生成することですPEG.buildParser()

angular.module('yourApp.services', [])
.factory('Parser', ['$http', '$q', function($http, $q) {
  var deferred = $q.defer();
  $http.get('path/to/CriteriaValue.pegjs')
  .success(function(grammar) {
    try {
      deferred.resolve(PEG.buildParser(grammar));
    } catch (e) {
      deferred.reject(e);
    }
  })
  .error(function(message) {
    deferred.reject('Unable to load grammar: ' + message);
  });

  return deferred.promise;
}]);

これにより、毎回サービスを書き直す必要がなくなるため、文法の更新が容易になりますが、アプリの読み込みが遅くなります。これが実現可能かどうかは、文法がどれほど複雑で、実際に変更する必要があるかによって異なります。

パーサーの作成方法に関係なく、生成されたパーサー オブジェクトを Angular アプリの残りの部分に直接公開する必要は必ずしもありません。代わりに、このパーサーを使用してアプリが実際に行うことについて、より高レベルの API を実装できます (例: validate(input)getAST(input)など)。このようにすると、将来別のパーサー (Jison など) に切り替えることにした場合でも、変更するコードが大幅に少なくなります。

于 2015-06-12T08:00:27.273 に答える