当前位置: 首页 > 知识库问答 >
问题:

为什么我的antlr语法似乎正确地解析了这个输入?

贺浩漫
2023-03-14
grammar ParserLang;

options {
    language=Python;
}

@header {
import sys
import antlr3

from ParserLangLexer import ParserLangLexer
}

@main { 
def main(argv, otherArg=None):
    char_stream = antlr3.ANTLRInputStream(open(sys.argv[1],'r'))
    lexer = ParserLangLexer(char_stream)

    tokens = CommonTokenStream(lexer)
    parser = ParserLangParser(tokens);

    rule   = parser.entry_rule()
}

program     : idList EOF
            | integerList EOF
            ;

idList      : ID whitespace idList 
            | ID
            ;

integerList : INTEGER whitespace integerList 
            | INTEGER
            ;

whitespace  : (WHITESPACE | COMMENT) +;

ID            : LETTER (DIGIT | LETTER)*;
INTEGER       : (NONZERO_DIGIT DIGIT*) | ZERO ;
WHITESPACE    : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+    { $channel = HIDDEN; } ;
COMMENT       : ('/*' .* '*/') | ('//' .* '\n') { $channel = HIDDEN; } ;

fragment ZERO            : '0' ;
fragment DIGIT         : '0' .. '9';
fragment NONZERO_DIGIT : '1' .. '9';
fragment LETTER        : 'a' .. 'z' | 'A' .. 'Z';

编辑:当我使用ANTLRWorks以相同的语法输入时,会抛出一个NoViableAltException。我如何通过代码得到错误?

共有1个答案

席宜修
2023-03-14

我无法复制它。当我在修复语法错误(rule=parser.entry_rule()应该是:rule=parser.program())之后从输入生成lexer和parser,并解析输入“12月12日1965”(作为文件输入或作为纯字符串)时,我会得到以下错误:

line 1:0 no viable alternative at input u'December'

这可能看起来很奇怪,因为这可能是IDList的开始。事实是,你的语法还有一个错误,还有一个可以改进的小地方:

  • 空白注释放置在隐藏通道上,因此在解析器规则中不可用(至少不更改解析器读取其标记的通道...);
  • 输入末尾的注释,即末尾没有\n,将无法正确标记。最好定义这样的一行注释:'//'~('\r''\n')*。尾部的换行符终究会被空白规则捕获。

由于空白规则,解析器无法匹配IDList(或IntegerList),因此会产生指向第一个令牌的错误('decce')。

下面是一个有效的语法(如预期的那样):

grammar ParserLang;

options {
    language=Python;
}

@header {
import sys
import antlr3

from ParserLangLexer import ParserLangLexer
}

@main { 
def main(argv, otherArg=None):
    lexer = ParserLangLexer(antlr3.ANTLRStringStream('December 12 1965'))
    parser = ParserLangParser(CommonTokenStream(lexer))
    parser.program()
}

program     : idList EOF
            | integerList EOF
            ;

idList      : ID+
            ;

integerList : INTEGER+
            ;

ID          : LETTER (DIGIT | LETTER)*;
INTEGER     : (NONZERO_DIGIT DIGIT*) | ZERO ;
WHITESPACE  : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
COMMENT     : ('/*' .* '*/' | '//' ~('\r' | '\n')*)   { $channel = HIDDEN; } ;

fragment ZERO          : '0' ;
fragment DIGIT         : '0' .. '9';
fragment NONZERO_DIGIT : '1' .. '9';
fragment LETTER        : 'a' .. 'z' | 'A' .. 'Z';

运行从上面的语法生成的解析器也会产生错误:

line 1:9 missing EOF at u'12'
 类似资料:
  • 然而,Antlr似乎不喜欢我在两个不同的地方使用“函数”。据我所知,语法甚至没有歧义。 在下面的语法中,如果我删除第1行,生成的解析器解析示例输入没有问题。另外,如果我更改第2行或第3行中的令牌字符串,使它们不相等,解析器就会工作。 我得到的语法错误是: 测试生成的解析器的程序:

  • 我正在用grun测试一些语法,我没有看到我的令牌被识别为令牌。我最初认为我可能已经基于这个StackOverflow链接创建了“隐式”令牌。 此外,在回顾grun-tokens的输出时,我发现了这些链接:1)最近对-tokens输出的更改。2)可能已经过时的testrig.md我已经发现并正在深入研究它。 下面是我的简单hellotc.g4,在这里我探索了以下内容: 我用以下方法进行测试: 我的代

  • 其中是我自己的班级。 此方法的返回类型是什么?为什么它似乎有两种返回类型?

  • 问题内容: 我的活动课在这里: 和相机预览类在这里: 但是,当我测试该类时,似乎首先调用onResume(),然后在1或2秒后再次调用。因此,相机必须再次刷新。如果我根本没有onResume(),则摄像头预览稳定,但是如果我从主屏幕或其他某个应用再次切换到该应用,则会崩溃。我发现onPause()不会影响任何一个。我的代码正确吗?我应该添加/删除哪些内容以使其不会再次刷新并且在应用切换后仍然不会崩

  • 问题内容: 我刚刚安装并重新安装了IntelliJ。每个Java文件都将变成红色。我检查了JDK;它是1.6。##。在构建工作就好了。 我遇到了通常突出显示的错误。在每个声明上: 无法解析符号SomeEntityBean / Bean 并在每种方法上: 无法解析方法SomeFunction() 如何解决这些错误错误? 问题答案: 即使没有Korgen所描述的外部更改,有时IntelliJ也会自己感

  • 我有字符串格式的日期,我想解析成使用日期。 我将其解析为: 但奇怪的是,如果我通过"03-08-201309hjhkjhk"或"03-88-2013"或43-88-201378",它不会抛出错误,它会解析它。 现在,我必须编写正则表达式模式来检查日期的输入是否正确。但为什么会这样呢?? 代码: