如何从JISON解析器中获取抽象语法树(AST)? [英] How to get Abstract Syntax Tree (AST) out of JISON parser?

查看:237
本文介绍了如何从JISON解析器中获取抽象语法树(AST)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我通过JISON生成了一个解析器:

So I have generated a parser via 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,否则返回true。

My question is, how do I retrieve the AST now? I can see that I can run the parser against input, but it just returns true if it works or fails if not.

对于记录,我使用的是JISON:< a href =http://zaach.github.com/jison/docs/ =noreferrer> http://zaach.github.com/jison/docs/

For the record, I am using JISON: http://zaach.github.com/jison/docs/

推荐答案

我对Jison的内部工作方式不太熟悉,所以我不知道会采用哪种方法。

I'm not too familiar with Jison's inner workings, so I don't know any method that would do it.

但是如果你对一点点暴力感兴趣来解决这个问题,试试这个:

But in case you're interested in a little bruteforce to solve this problem, try this:

首先,创建一个对象来保存AST

First, create an object to hold the 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添加一个小帮手函数

Add a little helper function for Jison's 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];
}

有了这个,请继续使用示例代码(稍作修改):

With this, continue to the example code (slight modification):

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']

小笔记:我必须添加一个开始规则,以便只有一个语句返回结果。它不干净(因为没有它,BNF工作正常)。将其设置为切入点以确保...

Small note: I had to add a "start" rule, in order to only have one statement that returns the result. It is not clean (since the BNF works fine without it). Set it as an entry point to be sure...

这篇关于如何从JISON解析器中获取抽象语法树(AST)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆