【问题标题】:Antlr whitespace token errorAntlr 空白令牌错误
【发布时间】:2012-06-12 21:59:19
【问题描述】:

我有以下语法,我想匹配字符串“{name1, name2}”。我只想要包含至少一个元素的名称/整数列表。但是我得到了错误:
第 1:6 行在字符 ' ' 处没有可行的替代方案
第 1:11 行在字符 '}' 处没有可行的替代方案
第 1:7 行不匹配的输入“名称”需要 SIMPLE_VAR_TYPE

我希望空格等会被忽略...另外有趣的是输入“{name1,name2}”不会发生错误(“,”后没有空格)。 这是我的语法

grammar NusmvInput;
options {
  language = Java;
}
@header {
  package secltlmc.grammar;
}
@lexer::header {
  package secltlmc.grammar;
}
specification : 
     SIMPLE_VAR_TYPE EOF
     ;     
INTEGER 
    : ('0'..'9')+
    ;
SIMPLE_VAR_TYPE 
    : ('{' (NAME | INTEGER) (',' (NAME | INTEGER))* '}'  )
    ;
NAME 
    : ('A'..'Z' | 'a'..'z') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' | '#' | '-')*
    ;
WS 
    : (' ' | '\t' | '\n' | '\r')+ {$channel = HIDDEN;} 
    ;

这是我的测试代码

package secltlmc;
public class Main {
    public static void main(String[] args) throws 
            IOException, RecognitionException {
        CharStream stream = new ANTLRStringStream("{name1, name2}");
        NusmvInputLexer lexer = new NusmvInputLexer(stream);
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        NusmvInputParser parser = new NusmvInputParser(tokenStream);
        parser.specification();
    }
}

感谢您的帮助。

【问题讨论】:

    标签: parsing antlr grammar


    【解决方案1】:

    问题是你试图用词法分析器解析SIMPLE_VAR_TYPE,即你试图使它成为一个单一的标记。实际上,您似乎想要一个多令牌生产,因为您希望通过WS 将空白重新定向到隐藏通道。

    您应该将SIMPLE_VAR_TYPE 从词法分析器规则更改为解析器规则,方法是将其首字母(或者更好的是,整个名称)更改为小写。

    specification : 
         simple_var_type EOF
         ;    
    
    simple_var_type 
        : ('{' (NAME | INTEGER) (',' (NAME | INTEGER))* '}'  )
        ;
    

    【讨论】:

    • @HeinrichOdy 我的理解是词法分析器规则只能显式地使用其他词法分析器规则。解析器规则隐式使用所有词法分析器规则,因为解析器规则是更高级别的。解析器为下一个标记调用词法分析器,词法分析器将WS 传递到隐藏通道,然后继续处理下一个标记。您可以在词法分析器规则中明确使用WS,这也是正确的。
    • 对不起,删除我自己的评论...选择了您的答案,原因是为了向我明确表示在令牌内空白清除不适用于隐藏令牌,谢谢。
    【解决方案2】:

    SIMPLE_VAR_TYPE 的定义指定如下表达式:

    • 打开{
    • 后跟NAMEINTEGER 之一
    • 后跟零个或多个:
      • 逗号 (,) 后跟 NAMEINTEGER 之一
    • 随后关闭}

    它不允许在输入中使用空格(NAMEINTEGER 都不允许),所以当你提供一个空格时会出现错误

    试试:

    SIMPLE_VAR_TYPE 
    : ('{' (NAME | INTEGER) (WS* ',' WS* (NAME | INTEGER))* '}'  )
    ;
    

    【讨论】:

    • 也许我也应该将 WS 添加到 '{'WS* ... WS*'}',但我知道你的目标是什么,谢谢 :)
    猜你喜欢
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 2011-08-16
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2012-04-10
    相关资源
    最近更新 更多