在 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 的一个作品作为目标,并且有多个作品,您需要将该产品复制到新的开始符号中。)