【问题标题】:ANTLR4. Comments not being swallowed by the lexerANTLR4。词法分析器没有吞下注释
【发布时间】:2014-10-25 01:52:12
【问题描述】:

我有以下 Antlr4 语法:

grammar Smarty;

/*
 * Parser Rules
 */

parse: smartyBody
     ;

smartyBody: include
          | bodyText?
          ;

include: INCLUDE fileName CB
          ;

bodyText: BODY_TEXT
         ;

fileName: FILENAME
        ; 
/*
 * Lexer Rules
 */
COMMENT: '{*' .*? '*}'      -> skip;

INCLUDE: '{include' SPACE+ 'file='?;

BODY_TEXT: ANY_CHAR+;

CB: SPACE? '}';

FILENAME: '\'' FILE_NAME '\''
     |    '"' FILE_NAME '"';

SPACE: [ \t];
NEW_LINE:   [\r\n]+         -> skip;

fragment FILE_NAME: PATH_CHARACTERS+;
fragment PATH_CHARACTERS: ~[\u0000-\u001f"*:<>?\\/|\u007f-\uffff];
fragment ANY_CHAR: [ -~];

现在如果我尝试使用 cmets,它们会被传回而不是被吞掉。

传递给解析器的文本:{* {include file='xxxxx'} *} zzzzzzzz

如果我覆盖 EnterBodyText 并将文本字符串传递给解析器,则侦听器中的 Text 变量将获取包括 cmets 在内的原始文本。

internal partial class BaseListener : SmartyBaseListener
{
    public override void EnterBodyText( SmartyParser.BodyTextContext context )
    {
       var Text = context.BODY_TEXT().GetText();
       // Text gets: {* {include file='xxxxx'} *} zzzzzzzz
       // not just zzzzzzzz
    }
}

任何帮助表示赞赏。

【问题讨论】:

    标签: comments antlr4 lexer


    【解决方案1】:

    ANTLR 的词法分析器会尽可能地匹配。所以输入{* {include file='xxxxx'} *} zzzzzzzz完全匹配BODY_TEXT

    解决此问题的一种方法是将 BODY_TEXT 改为解析器规则:

    body_text: ANY_CHAR+;
    
    ...
    
    COMMENT: '{*' .*? '*}' -> skip;
    
    ...
    
    // No fragment anymore. And keep this as the last lexer rule!
    ANY_CHAR: [ -~];
    

    【讨论】:

    • 非常感谢您的帮助。即使我认为 COMMENT 在 BODY_TEXT 之前声明,它也会优先于 BODY_TEXT。
    • @Terry151151, COMMENT 仅在两者匹配相同数量的字符时优先于 BODY_TEXT。只要其中一条规则匹配得更多,它就会“获胜”。
    • 请注意,它确实使处理效率低下。如果我有一个没有标签的 2k 文档,我最终会得到 2k 个节点,每个节点都包含一个字符。然后我必须为每个单个字符循环执行 GetText() 而不是只从词法分析器接收单个字符串。
    猜你喜欢
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 2015-03-22
    相关资源
    最近更新 更多