Antlr4 分析GraphQL架构意外失败

Antlr4 分析GraphQL架构意外失败,antlr4,Antlr4,作为Clojure GraphQL库的一部分,我们使用以下语法解析GraphQL模式定义: 直到最近(您好,吃我们自己的狗粮)才出现的问题是以下有效SDL无法解析: directive @auth ( logFailure: Boolean = true ) on FIELD_DEFINITION 以下是分析错误: clojure.lang.ExceptionInfo: Failed to parse GraphQL schema.

作为Clojure GraphQL库的一部分,我们使用以下语法解析GraphQL模式定义:

直到最近(您好,吃我们自己的狗粮)才出现的问题是以下有效SDL无法解析:

directive @auth (
              logFailure: Boolean = true
            ) on FIELD_DEFINITION
以下是分析错误:

clojure.lang.ExceptionInfo: Failed to parse GraphQL schema.
    errors: ({:locations [{:line 2, :column nil}],
              :message
              "mismatched input 'true' expecting {'{', '[', EXECUTABLE_DIRECTIVE_LOCATION, TYPE_SYSTEM_DIRECTIVE_LOCATION, 'type', 'implements', 'interface', 'schema', 'enum', 'union', 'input', 'directive', 'extend', 'scalar', 'on', 'fragment', 'query', 'mutation', 'subscription', 'value', BooleanValue, Name, NullValue, IntValue, FloatValue, StringValue, BlockStringValue}"}
             {:locations [{:line 3, :column nil}],
              :message "mismatched input ')' expecting ':'"})

因此,尽管语法中有规则将
true
false
匹配为布尔值,将
null
匹配为null值,解析器还是失败了

我已经做了一些痛击。。。重新排列语法中的规则,以确保在检查其他内容之前先检查BooleanValue,但我仍然会遇到相同的错误。我不确定如何确定这里的根本问题


这里有什么明显的错误吗?

问题是lexer永远不会生成
布尔值
标记:

K_TRUE         : 'true'         ;
K_FALSE        : 'false'        ;
...

BooleanValue
    : K_TRUE
    | K_FALSE
    ;
因为
K_TRUE
K_FALSE
是在
BooleanValue
之前定义的。这就是ANTLR的lexer的工作原理:

  • 为lexer规则匹配尽可能多的字符
  • 每当有两个或多个lexer规则匹配相同的字符时,让首先定义的规则“win”
解决方案是将
BooleanValue
提升到解析器:

K_TRUE         : 'true'         ;
K_FALSE        : 'false'        ;
...

booleanValue
    : K_TRUE
    | K_FALSE
    ;

...

value
    : IntValue
    | FloatValue
    | StringValue
    | BlockStringValue
    | booleanValue
    | NullValue
    | enumValue
    | arrayValue
    | objectValue
    ;
您的输入将被正确解析:


顺便说一句,
NullValue
:它永远不会被创建为令牌,因为
K_NULL
是在它之前定义的。最简单的方法是将其作为lexer规则删除,并直接在解析器规则中使用
K_NULL

问题是lexer永远不会生成
布尔值
标记:

K_TRUE         : 'true'         ;
K_FALSE        : 'false'        ;
...

BooleanValue
    : K_TRUE
    | K_FALSE
    ;
因为
K_TRUE
K_FALSE
是在
BooleanValue
之前定义的。这就是ANTLR的lexer的工作原理:

  • 为lexer规则匹配尽可能多的字符
  • 每当有两个或多个lexer规则匹配相同的字符时,让首先定义的规则“win”
解决方案是将
BooleanValue
提升到解析器:

K_TRUE         : 'true'         ;
K_FALSE        : 'false'        ;
...

booleanValue
    : K_TRUE
    | K_FALSE
    ;

...

value
    : IntValue
    | FloatValue
    | StringValue
    | BlockStringValue
    | booleanValue
    | NullValue
    | enumValue
    | arrayValue
    | objectValue
    ;
您的输入将被正确解析:


顺便说一句,
NullValue
:它永远不会被创建为令牌,因为
K_NULL
是在它之前定义的。最简单的方法是将其作为lexer规则删除,并直接在解析器规则中使用
K_NULL

谢谢!我以前试过,但没用,我一定是做错了。我将重新尝试,并返回结果。救生员!没问题@HowardM.LewisShip,如果这为您解决了问题,请告诉我。确认:是的,这一改变带来了所有的不同。再次感谢你的帮助!谢谢我以前试过,但没用,我一定是做错了。我将重新尝试,并返回结果。救生员!没问题@HowardM.LewisShip,如果这为您解决了问题,请告诉我。确认:是的,这一改变带来了所有的不同。再次感谢你的帮助!