解析GraphQL模式意外失败

时间:2020-10-09 23:24:30

标签: antlr4

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

https://github.com/walmartlabs/lacinia/blob/master/resources/com/walmartlabs/lacinia/schema.g4

直到最近(可能是吃我们自己的狗粮)之后,才有效地破解了以下有效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 ':'"})

因此,尽管语法中的规则将truefalse匹配为BooleanValue,将null匹配为NullValue,解析器仍然失败。

我已经在语法中进行了一些重击...重新排序规则,以确保在其他操作之前检查BooleanValue,但是我仍然遇到相同的错误。我不确定如何在这里找到根本问题。

这里显然有什么不对吗?

1 个答案:

答案 0 :(得分:0)

问题在于词法分析器将永远不会产生BooleanValue令牌:

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

BooleanValue
    : K_TRUE
    | K_FALSE
    ;

因为K_TRUEK_FALSEBooleanValue之前定义。 ANTLR的词法分析器是这样工作的:

  • 为词法分析器规则匹配尽可能多的字符
  • 每当有2个或更多匹配相同字符的词法分析器规则时,让该规则首先定义“赢”

解决方案是将BooleanValue提升为解析器:

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

booleanValue
    : K_TRUE
    | K_FALSE
    ;

...

value
    : IntValue
    | FloatValue
    | StringValue
    | BlockStringValue
    | booleanValue
    | NullValue
    | enumValue
    | arrayValue
    | objectValue
    ;

,您的输入将被正确解析:

enter image description here

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

相关问题