-
Notifications
You must be signed in to change notification settings - Fork 3
/
cue.bnf
263 lines (230 loc) · 11 KB
/
cue.bnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*
GrammarKit BNF grammar for CUE.
It tries to remain as close as possible to the original grammar.
Please not the following important differences:
- CUE has ":" to start a rule, GrammarKit has "::="
- in CUE's grammar {a} means 0 or more "a", but in GrammarKit {} it's just a grouping element.
GrammarKit's most-similar equivalent: {}*
- GrammarKit doesn't support left-recursive rules without adjustment to the type hierarchy
*/
{
generate=[java="11"]
consumeTokenMethod(".*")="consumeTokenFast"
parserClass="dev.monogon.cue.lang.parser.CueParser"
parserUtilClass="dev.monogon.cue.lang.parser.CueParserUtil"
tokenTypeClass="dev.monogon.cue.lang.CueTokenType"
elementTypeHolderClass="dev.monogon.cue.lang.CueTypes"
elementTypeClass="dev.monogon.cue.lang.psi.CueCompositeElementType"
implements="dev.monogon.cue.lang.psi.CueCompositeElement"
extends="dev.monogon.cue.lang.psi.CueCompositeElementImpl"
psiClassPrefix="Cue"
psiImplClassSuffix="Impl"
psiPackage="dev.monogon.cue.lang.psi"
psiImplPackage="dev.monogon.cue.lang.psi.impl"
psiImplUtilClass="dev.monogon.cue.lang.psi.impl.CuePsiImplUtil"
tokens=[
NEWLINE = '\n'
COMMA = ','
IDENTIFIER = 'IDENTIFIER'
IDENTIFIER_PREDECLARED = 'IDENTIFIER_PREDECLARED'
INT_LIT = 'INT_LIT'
FLOAT_LIT = 'FLOAT_LIT'
NULL_LIT = 'NULL_LIT'
BOOL_LIT = 'BOOL_LIT'
KEYWORD = "KEYWORD"
REL_OP = "REL_OP"
ADD_OP = "ADD_OP"
MUL_OP = "MUL_OP"
OP_DISJUNCTION = "|"
OP_UNIFICATION = "&"
OP_OR = "||"
OP_AND = "&&"
OP_EQ = "=="
QMARK = "?"
EXCL = "!"
DOT = "."
BOTTOM_LIT = "_|_"
// we're using _END tokens for string terminating tokens,
// because CueCommaInsertingLexer needs to know where string literals end
SINGLE_QUOTE = "SINGLE_QUOTE"
SINGLE_QUOTE_END = "'" // token text for end for better error reporting
DOUBLE_QUOTE = "DOUBLE_QUOTE"
DOUBLE_QUOTE_END = "\"" // token text for end for better error reporting
ESCAPED_CHAR = "ESCAPED_CHAR"
UNICODE_VALUE = "UNICODE_VALUE"
BYTE_VALUE = "BYTE_VALUE"
MULTILINE_STRING_START = "MULTILINE_STRING_START"
MULTILINE_STRING_END = "\"\"\"" // token text for end for better error reporting
MULTILINE_BYTES_START = "MULTILINE_BYTES_START"
MULTILINE_BYTES_END = "'''" // token text for end for better error reporting
INTERPOLATION_START = "INTERPOLATION_START"
INTERPOLATION_END = "INTERPOLATION_END"
LEFT_CURLY="{"
RIGHT_CURLY="}"
COLON=":"
ELLIPSIS_TOKEN="..."
EQ="="
QMARK="?"
LEFT_BRACKET="["
RIGHT_BRACKET="]"
AT="@"
LEFT_PAREN="("
RIGHT_PAREN=")"
ATTRIBUTE_VALUE="ATTRIBUTE_VALUE"
]
}
// https://cuelang.org/docs/references/spec/#source-file-organization
private file ::= { attribute comma }* [ PackageClause comma ] { ImportDecl comma }* { Declaration comma }*
PackageClause ::= "package" PackageName
private PackageName ::= identifier
ImportDecl ::= "import" ( ImportSpec | "(" { ImportSpec comma }* ")" ) {
pin=1
methods=[leftParen="LEFT_PAREN" rightParen="RIGHT_PAREN"]
}
ImportSpec ::= [ PackageName ] ImportPath
ImportLocation ::= { unicode_value }*
ImportPath ::= "\"" ImportLocation [ ":" identifier ] "\""
simple_string_lit ::= DOUBLE_QUOTE { unicode_value | interpolation }* DOUBLE_QUOTE_END {
pin=1
extends=Literal
implements=["dev.monogon.cue.lang.psi.CueStringLiteral" "com.intellij.psi.PsiLanguageInjectionHost"]
mixin="dev.monogon.cue.lang.psi.impl.CueSimpleStringLiteralMixin"
methods=[openingQuote="DOUBLE_QUOTE" closingQuote="DOUBLE_QUOTE_END"]
}
simple_bytes_lit ::= SINGLE_QUOTE { unicode_value | interpolation | BYTE_VALUE }* SINGLE_QUOTE_END {
pin=1
extends=Literal
implements=["dev.monogon.cue.lang.psi.CueStringLiteral" "com.intellij.psi.PsiLanguageInjectionHost"]
mixin="dev.monogon.cue.lang.psi.impl.CueSimpleByteLiteralMixin"
methods=[openingQuote="SINGLE_QUOTE" closingQuote="SINGLE_QUOTE_END"]
}
multiline_string_lit ::= MULTILINE_STRING_START NEWLINE { unicode_value | interpolation | NEWLINE }* NEWLINE* MULTILINE_STRING_END {
pin=1
extends=Literal
implements=["dev.monogon.cue.lang.psi.CueMultilineLiteral" "com.intellij.psi.PsiLanguageInjectionHost"]
mixin="dev.monogon.cue.lang.psi.impl.CueMultilineStringLiteralMixin"
methods=[openingQuote="MULTILINE_STRING_START" closingQuote="MULTILINE_STRING_END"]
}
multiline_bytes_lit ::= MULTILINE_BYTES_START NEWLINE { unicode_value | interpolation | BYTE_VALUE | NEWLINE }* NEWLINE* MULTILINE_BYTES_END {
pin=1
extends=Literal
implements=["dev.monogon.cue.lang.psi.CueMultilineLiteral" "com.intellij.psi.PsiLanguageInjectionHost"]
mixin="dev.monogon.cue.lang.psi.impl.CueMultilineBytesLiteralMixin"
methods=[openingQuote="MULTILINE_BYTES_START" closingQuote="MULTILINE_BYTES_END"]
}
interpolation ::= INTERPOLATION_START Expression INTERPOLATION_END { pin=1 }
private string_lit ::= simple_string_lit
| multiline_string_lit
| simple_bytes_lit
| multiline_bytes_lit
| "#" string_lit "#"
//private string_lit_recover ::= !(DOUBLE_QUOTE | DOUBLE_QUOTE_END | SINGLE_QUOTE | SINGLE_QUOTE_END | MULTILINE_STRING_START | MULTILINE_STRING_END | MULTILINE_BYTES_START | MULTILINE_BYTES_END)
// IntelliJ: extension to handle our known identifier tokens, identifier_PREDECLARED is mostly for highlighting
private identifier ::= IDENTIFIER | IDENTIFIER_PREDECLARED {
methods = [getReferences]
}
// https://cuelang.org/docs/references/spec/#structs
// fixme change of grammar rules
StructLit ::= "{" [ Declaration {comma Declaration}* comma? ] "}" {
pin=1 extends=Literal implements=["dev.monogon.cue.lang.psi.CueBlock"]
methods=[leftBrace="LEFT_CURLY" rightBrace="RIGHT_CURLY"]
}
Declaration ::= Field | Ellipsis | LetClause | Embedding | attribute // IntelliJ: moved LetClause before Embedding to fix parsing
Ellipsis ::= "..." [ Expression ] // use by both Declaration and ListLit
Embedding ::= Comprehension | AliasExpr {extends=Declaration}
Field ::= Label ":" { Label ":" }* AliasExpr attribute* {extends=Declaration methods=[getPresentation]}
Label ::= [ identifier "=" ] LabelExpr // fixme remap identifier here, i.e. accept keywords as identifier?
LabelExpr ::= LabelName ["?" | "!"]
| "[" AliasExpr "]" {
methods=[isOptionalFieldConstraint isRequiredFieldConstraint]
}
LabelName ::= <<struct_label>>
| simple_string_lit
| "(" AliasExpr ")" {
methods=[isOptionalFieldName isRequiredFieldName isDynamicFieldName]
}
// fixme remap identifier here, i.e. accept keywords as identifier?
attribute ::= "@" <<attribute_name>> "(" attr_tokens ")" {
pin=1
methods=[
leftParen="LEFT_PAREN"
rightParen="RIGHT_PAREN"
getAttributeNameElement
getAttributeName
]
}
attr_tokens ::= { <<attr_token>> // fixme remap token type of for attr_token tokens?
| "(" attr_tokens ")"
| "[" attr_tokens "]"
| "{" attr_tokens "}"
}*
// https://cuelang.org/docs/references/spec/#attributes
// fixme remap identifier here, i.e. accept keywords as identifier?
// IntelliJ: changed order, because the identifier prefix is also an Expression
AliasExpr ::= [ <<identifier_ref>> "=" ] Expression { extends=Expression }
// fixme added closing ] at the end, bug in grammar
ListLit ::= "[" [(ElementList [comma Ellipsis]) | Ellipsis] [comma] "]" {
pin=1
extends=Literal
methods=[leftBracket="LEFT_BRACKET" rightBracket="RIGHT_BRACKET"]
}
ElementList ::= Embedding { comma Embedding }*
// https://cuelang.org/docs/references/spec/#expressions
Operand ::= Literal | OperandName | "(" Expression ")" {extends=PrimaryExpr}
Literal ::= BasicLit | ListLit | StructLit {extends=Operand}
BasicLit ::= INT_LIT | FLOAT_LIT | string_lit | NULL_LIT | BOOL_LIT | BOTTOM_LIT {extends=Literal methods=[Literal=""]}
OperandName ::= <<identifier_ref>> | QualifiedIdent {extends=Operand}
QualifiedIdent ::= PackageName "." <<identifier_ref>> {extends=Operand}
// https://cuelang.org/docs/references/spec/#primary-expressions
//PrimaryExpr ::= Operand | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Slice | PrimaryExpr Arguments
// fixme this is a simple rewrite as non-left-recursive for now
// fixme: commented slice as it's not yet well defined in the grammar
PrimaryExpr ::= Operand {Selector | Index /*| Slice*/ | Arguments}* {extends=Expression}
Selector ::= "." (<<identifier_ref>> | simple_string_lit) {extends=PrimaryExpr}
Index ::= "[" Expression (":" Expression)? "]" {extends=PrimaryExpr pin=1} //fixme find out why example use ":" in Index
Argument ::= Expression {extends=PrimaryExpr}
Arguments ::= "(" [ ( Argument { comma Argument }* ) [ comma ] ] ")" {extends=PrimaryExpr pin=1}
// fixme Slice is missing
// https://cuelang.org/docs/references/spec/#operators
Expression ::= UnaryExpr | BinaryExpr | UnificationBinaryExpr // fixme extra root?
UnaryExpr ::= PrimaryExpr | unary_op UnaryExpr { extends=Expression }
BinaryExpr ::= Expression binary_op Expression {
extends=Expression
methods=[
left="/Expression[0]"
right="/Expression[1]"
]
}
UnificationBinaryExpr ::= Expression OP_UNIFICATION Expression {
extends=BinaryExpr
}
//"|" | "&" | "||" | "&&" | "==" | rel_op | add_op | mul_op
private binary_op ::= OP_DISJUNCTION | OP_OR | OP_AND | OP_EQ | rel_op | add_op | mul_op
//"!=" | "<" | "<=" | ">" | ">=" | "=~" | "!~"
private rel_op ::= REL_OP
//"+" | "-"
private add_op ::= ADD_OP
//"*" | "/" | "div" | "mod" | "quo" | "rem"
private mul_op ::= MUL_OP
// "+" | "-" | "!" | "*" | rel_op
private unary_op ::= ADD_OP | EXCL | "*" | rel_op
// https://cuelang.org/docs/references/spec/#comprehensions
Comprehension ::= Clauses StructLit
Clauses ::= StartClause { [ comma ] Clause }*
StartClause ::= ForClause | GuardClause
Clause ::= StartClause | LetClause
// fixme unclear if keywords are allowed here (i.e. remapped keywords)
ForClause ::= <<kw "for">> identifier [ comma identifier ] "in" Expression {
implements=["dev.monogon.cue.lang.psi.CueBlock"]
methods=["isValidBlock"]
}
GuardClause ::= <<kw "if">> Expression
// fixme unclear if keywords are allowed here (i.e. remapped keywords)
LetClause ::= <<kw "let">> identifier "=" Expression {
mixin="dev.monogon.cue.lang.psi.impl.CueLetClauseMixin"
implements=["dev.monogon.cue.lang.psi.CueBlock"]
methods=["isValidBlock"]
}
// IntelliJ: custom rules to support our extended token set
private unicode_value ::= UNICODE_VALUE | ESCAPED_CHAR
private comma ::= <<read_comma>>