首页 文章

ANTLR解析 - 忽略最后一行输入的注释

提问于
浏览
1

我正在使用Antlr 3.2而我在编写语法时无法忽略注释行 . 具体来说,如果注释行是输入的最后一行,后面没有换行符,我会收到错误 .

我的输入是有效的汇编语言,其中注释从行开头的任何地方用分号开始,然后转到行尾 . 其他所有内容都被解析为命令 .

我的语法的缩减版本展示了这个问题:

grammar Test;

options {
    language = Java;
    output = AST;
    ASTLabelType = CommonTree;
}

@header {
    package test;
}

@lexer::header {
    package test;
}

rule
    :   instruction+ EOF!
    ;

instruction
    :   'SET' NEWLINE!*
    ;

COMMENT
    :   ';' .* NEWLINE+ { $channel=HIDDEN; }
    ;

NEWLINE
    :  '\r'? '\n'
    ;

WS
    :   (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; }
    ;

如果我使用如下输入:

; comment line 1 with blank line after it

SET ; comment after command
; comment line again

解析这个说 line 4:11 required (...)+ loop did not match anything at character '<EOF>' 时出错 .

如果我在输入的最后一行添加换行符,它可以正常工作,因为换行符与换行符相匹配,并且规则结束时EOF匹配 .

我怎样才能更好地写这个,所以它忽略了最后一行的注释,但没有给出错误?我不想在原始输入中添加任何内容来破解它,是否有更简洁的方式来阅读注释行?我已经尝试了NEWLINE | EOF的各种组合,但没有任何东西摆脱错误 .

1 回答

  • 2

    这样的事情应该这样做:

    COMMENT
        :   ';' ~('\r' | '\n')* { $channel=HIDDEN; }
        ;
    

    如果你想让 COMMENT 在最后有一个换行符,请执行以下操作:

    COMMENT
        :   ';' ~('\r' | '\n')* NEWLINE? { $channel=HIDDEN; }
        ;
    

    但是,两个规则 NEWLINEWS

    NEWLINE
        :  '\r'? '\n'
        ;
    
    WS
        :   (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; }
        ;
    

    是危险的:ANTLR的工作方式如下:它尽可能地匹配,因此匹配最多“胜利”的规则 . 如果两个(或更多)规则匹配相同数量的字符,则首先定义的规则为“wins” .

    换句话说,如果词法分析器看到像 "\n" 这样的输入,则会创建 NEWLINE . 但是如果词法分析器看到 " \n" (后跟 "\n" 的空格),则会创建一个 WS 标记(并放在 HIDDEN 通道上) .

    我不确定换行符是否真的对你的语言很重要(它们不是任何汇编语言,AFAIK),所以只需删除 NEWLINE 规则 . 如果有意义,请从 WS 规则中删除字符 \r\n .

相关问题