15

そこで、JISON を介してパーサーを生成しました。

// mygenerator.js
var Parser = require("jison").Parser;

// a grammar in JSON
var grammar = {
    "lex": {
        "rules": [
           ["\\s+", "/* skip whitespace */"],
           ["[a-f0-9]+", "return 'HEX';"]
        ]
    },

    "bnf": {
        "hex_strings" :[ "hex_strings HEX",
                         "HEX" ]
    }
};

// `grammar` can also be a string that uses jison's grammar format
var parser = new Parser(grammar);

// generate source, ready to be written to disk
var parserSource = parser.generate();

// you can also use the parser directly from memory

// returns true
parser.parse("adfe34bc e82a");

// throws lexical error
parser.parse("adfe34bc zxg");

私の質問は、今ASTを取得するにはどうすればよいですか? 入力に対してパーサーを実行できることがわかりますが、機能する場合は true を返し、機能しない場合は失敗します。

記録のために、私は JISON を使用しています: http://zaach.github.com/jison/docs/

4

2 に答える 2

13

私はジソンの内部の仕組みにあまり詳しくないので、それを行う方法を知りません.

しかし、この問題を解決するためのちょっとした総当たり攻撃に興味がある場合は、これを試してください:

まず、AST を保持するオブジェクトを作成します。

function jisonAST(name, x) { this.name = name; this.x = x; }

// return the indented AST
jisonAST.prototype.get = function(indent){
  // create an indentation for level l
  function indentString(l) { var r=""; for(var i=0;i<l;i++){r+="  "}; return r }

  var r = indentString(indent) + "["+this.name+": ";
  var rem = this.x;
  if( rem.length == 1 && !(rem[0] instanceof jisonAST) ) r += "'"+rem[0]+"'"; 
  else for( i in rem ){ 
      if( rem[i] instanceof jisonAST ) r += "\n" + rem[i].get(indent+1);
      else { r += "\n" + indentString(indent+1); r += "'"+rem[i]+"'"; }
    }
  return r + "]";
}

Jison の BNF に小さなヘルパー関数を追加

function o( s ){
    r = "$$ = new yy.jisonAST('"+s+"',[";
    for( i = 1; i <= s.split(" ").length; i++ ){ r += "$"+i+"," }
    r = r.slice(0,-1) + "]);";
    return [s,r];
}

これで、コード例に進みます (わずかな変更):

var Parser = require("jison").Parser;

// a grammar in JSON
var grammar = {
    "lex": {
        "rules": [
           ["\\s+", "/* skip whitespace */"],
           ["[a-f0-9]+", "return 'HEX';"]
        ]
    },
    "bnf": {
        // had to add a start/end, see below
        "start" : [ [ "hex_strings", "return $1" ] ],
        "hex_strings" :[ 
            o("hex_strings HEX"), 
            o("HEX") 
        ]
    }
};

var parser = new Parser(grammar);
// expose the AST object to Jison
parser.yy.jisonAST = jisonAST

これで、解析を試すことができます:

console.log( parser.parse("adfe34bc e82a 43af").get(0) );

これにより、次のことが得られます。

[hex_strings HEX: 
  [hex_strings HEX: 
    [HEX: 'adfe34bc']  
    'e82a']  
  '43af']

小さなメモ: 結果を返すステートメントを 1 つだけにするために、「開始」ルールを追加する必要がありました。これはクリーンではありません (BNF はこれがなくても正常に動作するため)。確実にエントリーポイントとして設定してください...

于 2012-02-07T23:17:25.380 に答える