【问题标题】:ANTLR language - Tree not created (EOF - syntax error)ANTLR 语言 - 未创建树(EOF - 语法错误)
【发布时间】:2013-04-02 19:53:01
【问题描述】:

我在以下语言定义中显然有一个错误:

grammar Hello;


object  :
ALL* NAME ALL* '{' 
    (ALL* | (ALL* NAME ALL* NAME)* | (ALL* object)*)*
'}' ALL*;

ALL     :
(~('{' | '}' | '"'))+ -> skip;      // All but braces and double quotes

NAME    :
'"' ALL* '"';


当我尝试读取文件或直接添加内容(使用run.bat Hello object -gui)时,解析器会给我一个语法错误mismatched input '<EOF>' expecting NAME。 而且我只有一个带有单个节点的树:'object'。


这是Java源代码:

public static void main(String[] args) throws Exception {
    HelloLexer lexer = new HelloLexer(new ANTLRFileStream("gamemodes.txt"));
    TokenStream tokenStream = new CommonTokenStream(lexer);
    HelloParser parser = new HelloParser(tokenStream);

    System.out.println(lexer.getAllTokens().size());

    parser.setBuildParseTree(true);

    // Tree Creation
    RuleContext tree = parser.object();
    tree.inspect(parser);
}


最后,文件结构(在任何地方都有一些空格/字符(没有大括号和双引号)):

...
"objName"
{
    ...
    "innerObjName1"
    {
        "firstProperty"  "firstResult"
        ...
        "secondProp"     ""
    }

    "innerObjName2"
    {
        "firstProperty"  "firstResult"
        "secondProp"     ""
    }
}
...


注意:我在 Windows 上。

谢谢!

【问题讨论】:

  • 我认为您正在尝试使用正则表达式创建解析器规则(以小写字母开头的规则,例如 object 规则)。我认为antlr无法处理。解析器规则拥有更简单的机制。
  • 我在official website 中看到了一些使用正则表达式的示例,例如语法 (*, +, ?)...顺便说一句,如果你有解决我问题的想法,我在听你的:)
  • 哇,这好像叫EBNF,我什至不知道它存在。很高兴知道这一点。不过很遗憾,我无法帮助您解决问题。

标签: java tree antlr token grammar


【解决方案1】:

reportAttemptingFullContext 不是错误。它只是让您知道 ANTLR 4 正在使用其内部实现的部分,该部分使用完整的解析上下文来确保准确性。包含该消息是因为完整上下文算法比它首先尝试的 SLL 算法慢一些。

编辑:如果您使用的是非标准发行版,您可能需要指定以下选项以确保构建解析树。该选项在官方发行版中默认为真。

parser.setBuildParseTree(true);

编辑 2: 涵盖语法问题。

这是原始语法中的object 规则,仅更改了格式。

object // intermediate form 1
    :   ALL* NAME ALL* '{' 
        (   ALL*
        |   (ALL* NAME ALL* NAME)*
        |   (ALL* object)*
        )*
        '}' ALL*
    ;

这条规则非常模糊。作为一个简单的示例,请注意以下修改后的语法实际上将匹配相同的输入。

object // intermediate form 2
    :   ALL* NAME ALL* '{' 
        (   ALL
        |   ALL* NAME ALL* NAME
        |   ALL* object
        )*
        '}' ALL*
    ;

另一个简化从 2 个 alt 中删除了不必要的 ALL* 前缀。

object // final form
    :   ALL* NAME ALL* '{' 
        (   ALL
        |   NAME ALL* NAME
        |   object
        )*
        '}' ALL*
    ;

作为最后的更改,我将创建一个以明确的EOF 结尾的entry 规则:

entry : object EOF;

要解析您的输入,请调用 entry() 而不是 object() 以确保解析您的所有输入。如果您需要ObjectContext 对象,可以通过调用EntryContext.object() 获得。

【讨论】:

  • 感谢您的快速答复!很高兴知道这不是错误,但现在似乎没有生成树(之前,我有一个不同的语法来生成它)..你有什么想法吗?
  • 我增强了主题/内容以更好地解释我的评论。
  • 请也阅读我的编辑(我现在有一个错误)。我还添加了 parser.setBuildParseTree(true) 但它给了我相同的结果
  • 非常感谢,现在可以使用了!!我会在可能的时候给你赏金(1小时):)
【解决方案2】:

当你skip 一个词法分析器规则时,你不能在你的解析器规则中使用它。

试试这样的:

grammar Hello;

parse
 : object EOF
 ;

object
 : NAME (OBRACE object+ CBRACE | NAME)
 ;

NAME   : '"' ~["{}]* '"';
OBRACE : '{';
CBRACE : '}';
OTHER  : ~["{}]+ -> skip;

【讨论】:

  • 感谢巴特的回答。我不知道skip。顺便说一句,错误仍然存​​在,在字符 0 的最后一行:mismatched input '<EOF>' expecting NAME..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多