如何在杰森获得代币



我正在为一个大学项目使用Jison,我需要为每个可识别的令牌制作一个switch,这样我就可以向教授呈现如下内容:

<identifier, s>
<operator, =>
<identifier, a>
<operator, +>
<identifier, b>

如何在不手动循环正则表达式的情况下完成这项工作?(我的意思是,Jison内部使用regexp,但这不是我的事)

我试着做的是:

var lex = parser.lexer,
    token;
lex.setInput('The code to parse');
while (!lex.done) {
    token = lex.next();
}

但是我在token中保存的唯一东西是一个数字,当语法中没有定义符号时,它返回逐字符标记。

(警告:这个答案的一部分是通过检查jison生成的代码得来的。由于接口没有很好地定义,它可能经不起时间的考验。

parser.lexer.next()不是文档中的词法分析器接口的一部分,尽管jison生成的词法分析器似乎实现了它。注意,如果消耗的输入对应于不产生标记的词法规则,则它不会产生标记。(例如,忽略空白的规则。)最好使用文档化的接口parser.lexer.lex(),它总是生成一个令牌。

严格地说,parser.lexer.lex()被记录为返回终端的名称,但是为了效率,如果jison能够计算出词法规则将返回哪个终端,jison生成的词法分析器将返回终端的内部数字代码。因此,如果您想要跟踪所识别的终端的实际名称,那么您有两个替代方法:

  1. 您可以通过避免使用表单return <string>来挫败这种优化。例如,如果更改词法规则:

    [A-Za-z][A-Za-z0-9]    { return 'IDENTIFIER`; }
    

    [A-Za-z][A-Za-z0-9]    { return '' + 'IDENTIFIER`; }
    

    则生成的词法分析器将返回字符串'IDENTIFIER',而不是一些数字代码。

  2. 或者,您可以使用parser.terminals_,根据生成的解析器顶部的注释,它具有terminals_: {associative list: number ==> name}的形式,用于查找给定令牌编号的终端名称。

使用parser.lexer.yytext获取与词位相关联的源字符串。

下面是使用第二个选项的解决方案:

/* To reduce confusion, I change 'lex' to 'lexer' */
var lexer = parser.lexer,
    token;
lexer.setInput('The code to parse');
while (!lexer.done) {
    token = lexer.lex();
    /* Look up the token name if necessary */
    if (token in parser.terminals_) {
       token = parser.terminals_[token];
    }
    console.log('<' + token + ', ' + lexer.yytext + '>')
}

相关内容

  • 没有找到相关文章

最新更新