我一直在尝试为grammarkit编写graphql语言语法,而我发现自己已经很长时间以来一直陷入歧义问题。 graphql中的关键字(例如:server.servlet.context-path=/auth
server.use-forward-headers=true
,type
,implements
)也可以是类型或字段的名称。 I.E。
scalar
首先,我在bnf中将这些关键字定义为type type implements type {}
,但这意味着上述情况无效。但是,如果我在描述规则时直接写这些关键字,则会在语法上产生歧义。
我在下面的语法基础上看到的一个问题示例是,如果您定义了这样的内容
tokens
PSI查看器告诉我,在directive @foo on Baz | Bar
scalar Foobar @cool
的位置上,期望的是@cool
,这是我在标量规则中甚至没有引用的规则。有谁熟悉grammarkit并遇到这样的事情?我真的很感谢一些见识。谢谢。
这是我上面提到的错误示例的语法摘录。
DirectiveAddtlLocation
答案 0 :(得分:0)
一旦您的语法看到directive @TOKEN on IDENTIFIER
,它就会消耗DirectiveAddtlLocation
的序列。其中的每一个都包含一个可选的PIPE
,后跟一个IDENTIFIER
。正如您在问题中指出的那样,GraphQL“关键字”实际上只是标识符的特殊情况。因此,这里可能发生的事情是,由于您允许任何令牌作为标识符,因此scalar
和Foobar
都以DirectiveAddtlLocation
的形式被使用,实际上并没有看到{{1} }。
ScalarTypeDef
您可以通过列出语法中的explicit set of allowed directive locations来解决此问题。 (您甚至可以只复制Appendix B of the GraphQL spec中的语法并更改其语法就可以走得很远。)
# Parses the same as:
directive @foo on Bar | Baz | scalar | Foobar
@cool # <-- ?????
现在,当您解析时:
DirectiveLocation ::= ExecutableDirectiveLocation | TypeSystemDirectiveLocation
ExecutableDirectiveLocation ::= 'QUERY' | 'MUTATION' | ...
TypeSystemDirectiveLocation ::= 'SCHEMA' | 'SCALAR' | ...
(对于“标识符”与“关键字”的区别有点奇怪,我很确定GraphQL语法实际上并不模棱两可;在允许使用自由格式标识符的每种情况下,标点符号再次出现“关键字”之前,在这种情况下,就会出现不重复的不重复关键字的明确列表。)