如何在吉森获得代币?

How to get tokens in Jison?

我在一个大学项目中使用 Jison,我需要为每个识别的标记制作一个 switch,这样我就可以向教授展示类似的内容:

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

关于如何在不手动重复使用正则表达式的情况下完成此操作的任何方法? (我的意思是,Jison 在内部使用正则表达式,但这不关我的事)

我尝试做的是:

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

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

提前致谢。

(警告:部分答案是通过检查jison生成的代码得出的。由于接口定义不明确,可能经不起时间的考验。)

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

严格来说,parser.lexer.lex() 被记录为 return 终端名称,但为了提高效率,jison 生成的词法分析器将 return 终端的内部数字代码如果 jison 能够找出词法规则 return 的终端。所以你有几个选择,如果你想追踪识别的终端的实际名称:

  1. 您可以通过避免使用 return <string> 形式来破坏此优化。例如,如果您更改词法规则:

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

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

    然后生成的词法分析器将return字符串'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 + '>')
}