【问题标题】:How to get tokens in Jison?如何在吉森中获得代币?
【发布时间】:2015-07-19 22:41:00
【问题描述】:

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

提前致谢。

【问题讨论】:

    标签: javascript parsing token lexer jison


    【解决方案1】:

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

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

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

    1. 您可以通过避免使用return &lt;string&gt; 形式来破坏这种优化。例如,如果您更改词法规则:

      [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 ==&gt; 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 + '>')
    }
    

    【讨论】:

    • 感谢您的回答。我还必须查看生成的解析器源代码才能弄清楚,Jison 文档仍然有点不足。顺便说一句,我使用了您制作的表格:)
    猜你喜欢
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多