所以我通过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。

为了记录在案,我使用JISON: http://zaach.github.com/jison/docs/

===============>>#1 票数:12

我发现了一种比另一种答案更简单,更清洁的方法。

这篇文章分为两部分:

  • 一般方法:阅读如何实现我的方式。
  • 实际答案:特定于OP请求的先前描述方式的实现。

一般方式

  1. return语句添加到起始规则。

    例:

     start : xyz EOF {return $1;} ; 

    xyz是另一个生产规则。 $1访问相关生产规则的第一个符号(终端或非终端)的值。 在上面的代码中, $1包含xyz的结果。

  2. $$ = ...语句添加到所有其他规则。

    警告:使用$$ = ... ,不要return return将通过返回指定的值立即中止进一步的执行,如名称所示。

    例:

     multiplication : variable '*' variable {$$ = { type: 'multiplication', arguments: [ $1, $3 ] }; } ; 

    上面的生产规则会将对象$$传递给更高级别(即使用此规则的生产规则)。

    让我们补充乘法规则,以实现一个可运行的例子:

     /* lexical grammar */ %lex %% \\s+ /* skip whitespace */ [0-9]+("."[0-9]+)?\\b return 'NUMBER' [a-zA-Z]+ return 'CHARACTER' "*" return '*' <<EOF>> return 'EOF' . return 'INVALID' /lex %start start %% /* language grammar */ start : multiplication EOF {return $1;} ; multiplication : variable '*' variable {$$ = { type: 'multiplication', arguments: [ $1, $3 ] }; } ; variable : 'NUMBER' {$$ = { type: 'number', arguments: [$1] }; } | 'CHARACTER' {$$ = { type: 'character', arguments: [$1] }; } ; 

    您可以在线试用:http: //zaach.github.io/jison/try/ 在编辑时(12.02.2017),在线生成器遗憾地抛出错误 - 独立于您输入的Jison文件。有关如何在本地计算机上生成解析器的提示,请参阅步骤3之后的附录。

    如果您输入例如a*3 ,则会得到以下对象结构:

     { "type": "multiplication", "arguments": [ { "type": "character", "arguments": ["a"] }, { "type": "number", "arguments": ["3"] } ] } 
  3. 通过注入自定义对象来清理代码并生成AST

    使用Jison生成的解析器时,可以将任意对象注入语法文件中“代码块”的范围:

     const MyParser = require('./my-parser.js'); MyParser.parser.yy = { MultiplicationTerm /*, AdditionTerm, NegationTerm etc. */ }; let calculation = MyParser.parse("3*4"); // Using the modification below, calculation will now be an object of type MultiplicationTerm 

    如果MultiplicationTerm有一个构造函数接受这两个因子,乘法的新部分将如下所示:

     multiplication : variable '*' variable {$$ = new yy.MultiplicationTerm($1, $3);} ; 

关于如何创建Jison解析器的附录:

下载Jison NPM模块。 然后,您可以使用Jison的命令行创建Jison-parser,或者在构建文件中运行new jison.Generator(fileContents).generate() ,并将返回的字符串写入首选文件,例如my-parser.js

实际答案

应用上述规则会导致下面的Jison文件。
据我所知,Jison文件格式和JavaScript API(如问题中所述)可以互换。

另请注意,此Jison文件仅生成一个平面树(即列表),因为输入格式也只是一个列表(或者您将如何以逻辑方式嵌套连接的十六进制字符串?)。

/* lexical grammar */
%lex
%%

\s+                   /* skip whitespace */
[a-f0-9]+             return 'HEX'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

%start start
%% /* language grammar */

start
    :  hex_strings EOF
        {return $1;}
    ;

hex_strings
    : hex_strings HEX
        {$$ = $1.concat([$2]);}
    | HEX
        {$$ = [$1];}
    ;

===============>>#2 票数:12 已采纳

我对Jison的内部工作并不太熟悉,所以我不知道会有什么方法可以做到。

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

首先,创建一个对象来保存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']

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

  ask by Tower translate from so

未解决问题?本站智能推荐:

2回复

如何使用Jison生成一个处理语法歧义的解析器?

我试图通过Jison为ChucK语言生成一个JavaScript解析器,并且已经有了一个良好的开端,除了生成的解析器无法处理的语言含糊不清。 原始的ChucK编译器是由Bison生成的,并且必须能够以某种方式解决这些歧义。 出于这个问题的目的,我已经将问题简化为解释性语法,其仅呈现出一种
1回复

如何从野牛文件中使用JISON生成解析器

我正在尝试用JavaScript为音乐符号的Lilypond语言编写一个解析器。 我的第一本手册尝试了,但是只能处理一小部分语言。 由于Lilypond使用bison文件定义其语法[1],而JISON声称能够使用bison文件工作,因此我的想法也许是使用这些定义在JavaScript中生成解
1回复

递归布尔和/或数组jison解析器

我是jison的新手,并且设法拼凑了一个有用的查询解析器。 我现在正在尝试创建一个解析器,它可以解析像“a == 1和b == 1和c == 1”之类的字符串到类似的对象中 而像“a == 1或b == 1和c == 1”之类的字符串应该解析为像这样的对象 到目前为止,我的语法
1回复

吉森解析器在第一个规则后停止

我有一个简单的文件格式,我想用jison解析器生成器来解析。 该文件可以包含任意顺序和数量的多个表达式。 这是解析器的jison文件: 为简单起见,我将文件缩短为仅包含字符串和文件ID表达式。 我的问题是,如果第二个表达式仅包含一个像字符串这样的标记,则生成的解析器似乎只能识别
2回复

使用简单的jison语法解析错误

我正在尝试创建一种简单的脚本语言。 一开始我只是想要像 因此,我为jison创建了以下语法: 它生成语法分析器,而不会抱怨语法。 我的问题是当我这样做 我得到这个错误 这完全让我感到困惑://首先没有规则期望操作员。 唯一期望运算符的规则是AssignSta
1回复

如何在Jison中获取令牌?

我正在使用Jison进行大学项目,并且需要为每个已识别的标记进行switch ,因此我可以向教授介绍以下内容: <identifier, s> <operator, => <identifier, a> <operator, +> <ide
1回复

在Jison中调试

我正在使用Jison编写解析器。 这是我的语法: 当我运行它时,我收到以下错误消息: 我该怎么做这个调试消息? 你怎么用简单的英语解释这个消息? expression -> expression expression .中的句点是什么expression ->
1回复

如何识别jison中令牌的重复?

TL; TR 本练习的目的是检测某个令牌的重复,我正尝试使用正则表达式中的*符号来实现此目的,但是它不起作用。 问题描述 我正在做一个基本的编译器,它包括用已经定义的语法翻译某些语法。 在定义多个令牌的检测时,我仍然有一些缺点。 也就是说,例如,使用*指定正则表达式令牌的重
2回复

添加bison / jison计算器语言的功能

我正在尝试使用一些简单的函数来扩展Jison计算器示例 。 我对解析和野牛/ jison很新,但这是我到目前为止的一点点: 问题是函数只传递一个参数。 例如: 实际上,如果你在console.log中使用pow的参数,那么看起来b甚至都没有定义。 为什么在将它发送到函数之前
1回复

Jison:if-else和for ara组合时的语法冲突

我想用jison为JavaScript语言的子集创建解析器,但遇到一些问题。 最初,我对非终端stmt有了这个定义,它的工作原理是: 之后,我在stmt添加了以下规则: 该语法不明确,出现冲突。 因此,我遵循以下模式来解决悬而未决的歧义: 必须将其转换为:stmt