首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何向acorn或esprima解析器添加关键字

如何向acorn或esprima解析器添加关键字
EN

Stack Overflow用户
提问于 2020-01-19 04:38:16
回答 1查看 287关注 0票数 0

我正在研究一种可以转换为javascript的语言,并且具有类似的语法。但是,我想包含一些新类型的块语句。出于语法目的,它们与IfStatement相同。怎样才能让esprima或acorn解析这个程序的MyStatement {a=1;}而不抛出错误呢?如果它叫它IfStatement也没问题。我不想分叉esprima。

EN

回答 1

Stack Overflow用户

发布于 2020-01-22 02:06:16

事实证明,acorn的插件功能并没有真正的文档记录。看起来分叉橡子是最简单的路线。在本例中,只需搜索_if的出现情况并遵循类似的_MyStatement模式即可。

然而,可以编写一个插件来完成我想要做的事情。这看起来有点不切实际,但这是代码。基本步骤如下:

  1. 要扩展Parse并将其添加到将被第一次传递识别的关键字列表中
  2. 为新关键字创建一个TokenType并将其添加到Parser.acorn.keywordTypes,扩展parseStatement以便它处理新TokenType的处理程序,该处理程序将根据关键字功能的要求将信息添加到抽象语法树,并使用诸如this.expect(tt.parenR)之类的命令使用令牌来使用'(‘或this.parseExpression()来处理整个表达式。<代码>H213<代码>G214

代码如下:

代码语言:javascript
复制
var program = 
`
  MyStatement {
    MyStatement(true) {
      MyStatement() {
        var a = 1;
      }
    }
    if (1) {
      var c = 0;
    }
  }
`;

const acorn = require("acorn");

const Parser = acorn.Parser;
const tt = acorn.tokTypes; //used to access standard token types like "("
const TokenType = acorn.TokenType; //used to create new types of Tokens.

//add a new keyword to Acorn.
Parser.acorn.keywordTypes["MyStatement"] = new TokenType("MyStatement",{keyword: "MyStatement"});

//const isIdentifierStart = acorn.isIdentifierStart;

function wordsRegexp(words) {
  return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}

var bruceware = function(Parser) {
  return class extends Parser {
    parse(program) {
      console.log("hooking parse.");

      //it appears it is necessary to add keywords here also.
      var newKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this const class extends export import super";
      newKeywords += " MyStatement";
      this.keywords = wordsRegexp(newKeywords);

      return(super.parse(program));
    }

    parseStatement(context, topLevel, exports) {
      var starttype = this.type;
      console.log("!!!hooking parseStatement", starttype);

      if (starttype == Parser.acorn.keywordTypes["MyStatement"]) {
        console.log("Parse MyStatement");
        var node = this.startNode();
        return this.parseMyStatement(node);
      }
      else {
        return(super.parseStatement(context, topLevel, exports));
      }
    }

    parseMyStatement(node) {
      console.log("parse MyStatement");
      this.next();

      //In my language, MyStatement doesn't have to have a parameter. It could be called as `MyStatement { ... }`
      if (this.type == tt.parenL) {
        node.test = this.parseOptionalParenExpression();
      }
      else {
        node.test = 0; //If there is no test, just make it 0 for now (note that this may break code generation later).
      }

      node.isMyStatement = true; //set a flag so we know that this if a "MyStatement" instead of an if statement.

      //process the body of the block just like a normal if statement for now.

      // allow function declarations in branches, but only in non-strict mode
      node.consequent = this.parseStatement("if");
      //node.alternate = this.eat(acornTypes["else"]) ? this.parseStatement("if") : null;
      return this.finishNode(node, "IfStatement")
    };

    //In my language, MyStatement, optionally has a parameter. It can also by called as MyStatement() { ... }
    parseOptionalParenExpression() {
      this.expect(tt.parenL);

      //see what type it is
      console.log("Type: ", this.type);

      //allow it to be blank.
      var val = 0; //for now just make the condition 0. Note that this may break code generation later.
      if (this.type == tt.parenR) {
        this.expect(tt.parenR);
      }
      else { 
        val = this.parseExpression();
        this.expect(tt.parenR);
      }

      return val
    };

  }
}

process.stdout.write('\033c'); //cls

var result2 = Parser.extend(bruceware).parse(program); //attempt to parse

console.log(JSON.stringify(result2,null,' ')); //show the results.
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59804600

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档