我发现了一种比其他答案中提到的更简单、更清晰的方法。
这篇文章分为两个部分:
- 通用方法:阅读如何实现我的方法。
- 实际答案:一个特定于OP请求的之前描述的方式的实现。
通用方法
在您的起始规则中添加一个return语句。
例如:
start
: xyz EOF
{return $1;}
;
xyz
是另一条产生式规则。 $1
访问关联产生式规则的第一个符号(终结符或非终结符)的值。在上面的代码中,$1
包含来自xyz
的结果。
将$$ = ...
语句添加到所有其他规则中。
警告:使用$$ = ...
,不要使用return
!return
会立即通过返回指定的值来终止进一步执行,正如其名称所示。
例子:
multiplication
: variable '*' variable
{$$ = {
type: 'multiplication',
arguments: [
$1,
$3
]
};
}
;
以上生产规则将对象 $$
传递给更高层级(即使用此规则的生产规则)。
为了实现可运行的示例,让我们补充乘法规则:
%lex
%%
\s+
[0-9]+("."[0-9]+)?\b return 'NUMBER'
[a-zA-Z]+ return 'CHARACTER'
"*" return '*'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
%start start
%%
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"]
}
]
}
通过注入自定义对象来清理代码和生成AST
使用Jison生成的解析器时,您可以将任意对象注入到语法文件中的“代码块”作用域中:
const MyParser = require('./my-parser.js');
MyParser.parser.yy = {
MultiplicationTerm
};
let calculation = MyParser.parse("3*4");
如果
MultiplicationTerm
有一个接受两个因子的构造函数,那么乘法运算的新部分将如下所示:
如果MultiplicationTerm
有一个接受两个因子的构造函数,那么乘法的新部分将如下所示:
multiplication
: variable '*' variable
{$$ = new yy.MultiplicationTerm($1, $3);}
;
关于如何创建Jison解析器的补充说明:
下载Jison NPM模块。然后,您可以通过使用Jison的命令行或在构建文件中运行new jison.Generator(fileContents).generate()
来创建Jison解析器,并将返回的字符串写入您首选的文件,例如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];}
;