如何在杰森获得令牌?

时间:2015-07-19 22:41:00

标签: javascript parsing token lexer jison

我将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中保存的唯一内容是一个数字,当一个符号没有在语法中定义时,它会返回逐个字符的标记。

提前致谢。

1 个答案:

答案 0 :(得分:0)

(警告:这个答案的一部分是通过检查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}形式,在给定令牌编号的情况下查找终端名称。< / p>

  3. 要获取与词汇相关联的源字符串,请使用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 + '>')
    }