在 JISON 中解析单个产品
Parse individual productions in JISON
在 JISON 中,有没有办法为单个作品解析字符串?例如,这个原始解析器根据 ary
.
等几个产品定义了一个主 expressions
现在这个returns一个函数可以解析expressions
:
var parser = jison.Parser(bnf);
var str = "A(1-3,5)&B(1,2,3)"
var result = parser.parse(str) // this works
但我还想解析匹配 ary
、
等个别作品的字符串
var str = "1-3,5"
var result = parser.ary.parse(str) /// this does not work
下面是删除了一些 Javascript 的示例语法:
%start expressions
/* language grammar */
%%
expressions: e EOF {...}
;
assign: ID LPAR ary RPAR
;
predicate: COUNT LPAR elist constraint RPAR { ... }
;
e : TN { $$ = {}; }
| predicate { $$ = ; }
| e '&' e { $$ = _.merge({},,); }
| e '!' e { $$ = { "$or": [,]}; }
| '?' e { $$ = { "$not": }; }
| '{' e '}' { $$ = ; }
| assign { $$ = ; }
;
/* Seguir desde aca. Esta es la unica expr que sigue jodiendo... */
elist: elist SEMI e { ... }
| e { ... }
;
constraint: SEMI comparator val { ... }
| SEMI val {... }
;
ary: val { $$ = []; }
| ary "," val
;
val: NUMBER { $$ = +; }
| '-' NUMBER { $$ = - (+); }
| ID { $$ = ; }
| STRING { $$ = ; }
| NUMBER '-' NUMBER { $$ = _.range(+, ++1); }
| '(' ary ')' { $$ = ; }
;
comparator: '$eq'
| '$lte'
| '$gte'
| '$gt'
| '$lt' { $$ = ; }
;
将此功能添加到使用解析器生成器生成的解析器中真的很简单,而无需过多考虑解析器生成器的工作原理。您所需要的只是一些额外的(假)终端,一个用于开始解析的每个非终端,一个用于每个新终端。
如果您可以将词素注入到词法流中而不跳过箍,这对 jison 来说当然是可能的,因为它允许您插入自己的自定义词法分析器,它可以注入终端,然后通过调用传递给生成的词法分析器。 (如果您需要使用生成的词法分析器,那么如果您的词法分析器生成器允许启动条件,那么它仍然非常容易。您只需为每个注入的词法定义一个启动条件,它立即发出所需的终端,然后重置为标准启动条件以便解析实际输入。此策略有很多变体,具体取决于您可用的接口。)
基于以上内容,新语法将类似于:
start: old_start
| EXPR_TOKEN expr
| ARY_TOKEN ary
| ...
然后您只需注入正确的终端,解析器就会自动继续所需的 non-terminal。
对于像 Jison 这样的语法是数据的解析器生成器,这种转换可以很容易地自动完成,因此您甚至不需要真正决定 non-terminal 您对哪些感兴趣。
(注意:这让您可以 select 一个目标 non-terminal,而不是一个目标作品。如果您想要将一个 non-terminal 的一个作品作为目标,并且有多个作品,您需要将该产品复制到新的开始符号中。)
在 JISON 中,有没有办法为单个作品解析字符串?例如,这个原始解析器根据 ary
.
expressions
现在这个returns一个函数可以解析expressions
:
var parser = jison.Parser(bnf);
var str = "A(1-3,5)&B(1,2,3)"
var result = parser.parse(str) // this works
但我还想解析匹配 ary
、
var str = "1-3,5"
var result = parser.ary.parse(str) /// this does not work
下面是删除了一些 Javascript 的示例语法:
%start expressions
/* language grammar */
%%
expressions: e EOF {...}
;
assign: ID LPAR ary RPAR
;
predicate: COUNT LPAR elist constraint RPAR { ... }
;
e : TN { $$ = {}; }
| predicate { $$ = ; }
| e '&' e { $$ = _.merge({},,); }
| e '!' e { $$ = { "$or": [,]}; }
| '?' e { $$ = { "$not": }; }
| '{' e '}' { $$ = ; }
| assign { $$ = ; }
;
/* Seguir desde aca. Esta es la unica expr que sigue jodiendo... */
elist: elist SEMI e { ... }
| e { ... }
;
constraint: SEMI comparator val { ... }
| SEMI val {... }
;
ary: val { $$ = []; }
| ary "," val
;
val: NUMBER { $$ = +; }
| '-' NUMBER { $$ = - (+); }
| ID { $$ = ; }
| STRING { $$ = ; }
| NUMBER '-' NUMBER { $$ = _.range(+, ++1); }
| '(' ary ')' { $$ = ; }
;
comparator: '$eq'
| '$lte'
| '$gte'
| '$gt'
| '$lt' { $$ = ; }
;
将此功能添加到使用解析器生成器生成的解析器中真的很简单,而无需过多考虑解析器生成器的工作原理。您所需要的只是一些额外的(假)终端,一个用于开始解析的每个非终端,一个用于每个新终端。
如果您可以将词素注入到词法流中而不跳过箍,这对 jison 来说当然是可能的,因为它允许您插入自己的自定义词法分析器,它可以注入终端,然后通过调用传递给生成的词法分析器。 (如果您需要使用生成的词法分析器,那么如果您的词法分析器生成器允许启动条件,那么它仍然非常容易。您只需为每个注入的词法定义一个启动条件,它立即发出所需的终端,然后重置为标准启动条件以便解析实际输入。此策略有很多变体,具体取决于您可用的接口。)
基于以上内容,新语法将类似于:
start: old_start
| EXPR_TOKEN expr
| ARY_TOKEN ary
| ...
然后您只需注入正确的终端,解析器就会自动继续所需的 non-terminal。
对于像 Jison 这样的语法是数据的解析器生成器,这种转换可以很容易地自动完成,因此您甚至不需要真正决定 non-terminal 您对哪些感兴趣。
(注意:这让您可以 select 一个目标 non-terminal,而不是一个目标作品。如果您想要将一个 non-terminal 的一个作品作为目标,并且有多个作品,您需要将该产品复制到新的开始符号中。)