Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol
diffdown.com
1@dialects { jsx, ts }
2
3@precedence {
4 typeargs,
5 typeMember,
6 typePrefix,
7 intersectionPrefixed @left,
8 intersection @left,
9 unionPrefixed @left,
10 union @left,
11 typeExtends @right,
12 else @right,
13 member,
14 readonly,
15 newArgs,
16 call,
17 instantiate,
18 taggedTemplate,
19 prefix,
20 postfix,
21 typeof,
22 exp @left,
23 times @left,
24 plus @left,
25 shift @left,
26 loop,
27 rel @left,
28 satisfies,
29 equal @left,
30 bitAnd @left,
31 bitXor @left,
32 bitOr @left,
33 and @left,
34 or @left,
35 ternary @right,
36 assign @right,
37 comma @left,
38 statement @cut,
39 predicate
40}
41
42@top Script { Hashbang? statement* }
43
44@top SingleExpression { expression }
45
46@top SingleClassItem { classItem }
47
48statement[@isGroup=Statement] {
49 ExportDeclaration |
50 ImportDeclaration |
51 ForStatement { kw<"for"> ckw<"await">? (ForSpec | ForInSpec | ForOfSpec) statement } |
52 WhileStatement { kw<"while"> ParenthesizedExpression statement } |
53 WithStatement { kw<"with"> ParenthesizedExpression statement } |
54 DoStatement { kw<"do"> statement kw<"while"> ParenthesizedExpression semi } |
55 IfStatement { kw<"if"> ParenthesizedExpression statement (!else kw<"else"> statement)? } |
56 SwitchStatement { kw<"switch"> ParenthesizedExpression SwitchBody { "{" switchItem* "}" } } |
57 TryStatement {
58 kw<"try"> Block
59 CatchClause { kw<"catch"> ("(" pattern ")")? Block }?
60 FinallyClause { kw<"finally"> Block }?
61 } |
62 ReturnStatement { kw<"return"> (noSemi expression)? semi } |
63 ThrowStatement { kw<"throw"> expression semi } |
64 BreakStatement { kw<"break"> (noSemi Label)? semi } |
65 ContinueStatement { kw<"continue"> (noSemi Label)? semi } |
66 DebuggerStatement { kw<"debugger"> semi } |
67 Block |
68 LabeledStatement { Label ":" statement } |
69 declaration |
70 ExpressionStatement { expression semi } |
71 ";"
72}
73
74ExportDeclaration {
75 kw<"export"> Star (ckw<"as"> (VariableName | String))? ckw<"from"> String semi |
76 kw<"export"> kw<"default"> (FunctionDeclaration | ClassDeclaration | expression semi) |
77 kw<"export"> tskw<"type">? declaration |
78 kw<"export"> tskw<"type">? ExportGroup (ckw<"from"> String)? semi |
79 kw<"export"> "=" expression semi
80}
81
82ExportGroup {
83 "{" commaSep<(VariableName | String | kw<"default">) (ckw<"as"> (VariableName { word } | String))?> "}"
84}
85
86ImportDeclaration {
87 kw<"import"> ckw<"defer">? tskw<"type">? (Star ckw<"as"> VariableDefinition | commaSep<VariableDefinition | ImportGroup>)
88 ckw<"from"> String semi |
89 kw<"import"> ckw<"defer">? String semi
90}
91
92ImportGroup {
93 "{" commaSep<tskw<"type">? (VariableDefinition | (VariableName | String | kw<"default">) ckw<"as"> VariableDefinition)> "}"
94}
95
96ForSpec {
97 "("
98 (VariableDeclaration | expression ";" | ";") expression? ";" expression?
99 ")"
100}
101
102forXSpec<op> {
103 "("
104 (variableDeclarationKeyword pattern | VariableName | MemberExpression | ArrayPattern | ObjectPattern)
105 !loop op expression
106 ")"
107}
108
109ForInSpec { forXSpec<kw<"in">> }
110ForOfSpec { forXSpec<ckw<"of">> }
111
112declaration {
113 FunctionDeclaration |
114 ClassDeclaration |
115 VariableDeclaration |
116 TypeAliasDeclaration |
117 InterfaceDeclaration |
118 EnumDeclaration |
119 NamespaceDeclaration |
120 AmbientDeclaration
121}
122
123FunctionDeclaration {
124 async? !statement kw<"function"> Star? VariableDefinition? functionSignature (Block | semi)
125}
126
127ClassDeclaration {
128 !statement Decorator* tskw<"abstract">? kw<"class"> VariableDefinition TypeParamList?
129 (kw<"extends"> ((VariableName | MemberExpression) !typeargs TypeArgList | expression))?
130 (tskw<"implements"> commaSep1<type>)?
131 ClassBody
132}
133
134classItem { MethodDeclaration | PropertyDeclaration | StaticBlock | ";" }
135
136ClassBody { "{" classItem* "}" }
137
138privacy {
139 @extend[@name=Privacy,@dialect=ts]<word, "public" | "private" | "protected">
140}
141
142privacyArg {
143 @extend[@name=Privacy,@dialect=ts]<identifier, "public" | "private" | "protected">
144}
145
146propModifier {
147 Decorator |
148 tsPkwMod<"declare"> |
149 privacy |
150 pkwMod<"static"> |
151 tsPkwMod<"abstract"> |
152 tsPkwMod<"override">
153}
154
155classPropName { propName | PrivatePropertyDefinition }
156
157MethodDeclaration[group=ClassItem] {
158 propModifier*
159 pkwMod<"async">?
160 (pkwMod<"get"> | pkwMod<"set"> | Star)?
161 classPropName
162 functionSignature
163 (Block | semi)
164}
165
166StaticBlock[group=ClassItem] {
167 pkwMod<"static"> Block
168}
169
170PropertyDeclaration[group=ClassItem] {
171 propModifier*
172 (tsPkwMod<"readonly"> | pkwMod<"accessor">)?
173 classPropName
174 (Optional | LogicOp<"!">)?
175 TypeAnnotation?
176 ("=" expressionNoComma)?
177 semi
178}
179
180variableDeclarationKeyword {
181 kw<"let"> | kw<"var"> | kw<"const"> | ckw<"await">? ckw<"using">
182}
183
184VariableDeclaration {
185 variableDeclarationKeyword commaSep1<patternAssignTyped> semi
186}
187
188TypeAliasDeclaration {
189 tskw<"type"> TypeDefinition TypeParamList? "=" type semi
190}
191
192InterfaceDeclaration {
193 tskw<"interface"> TypeDefinition TypeParamList? (kw<"extends"> commaSep1<type>)? ObjectType
194}
195
196EnumDeclaration {
197 kw<"const">? tskw<"enum"> TypeDefinition EnumBody { "{" commaSep<PropertyName ("=" expressionNoComma)?> "}" }
198}
199
200NamespaceDeclaration {
201 (tskw<"namespace"> | tskw<"module">) VariableDefinition ("." PropertyDefinition)* Block
202}
203
204AmbientDeclaration {
205 tskw<"declare"> (
206 VariableDeclaration |
207 TypeAliasDeclaration |
208 EnumDeclaration |
209 InterfaceDeclaration |
210 NamespaceDeclaration |
211 GlobalDeclaration { tskw<"global"> Block } |
212 ClassDeclaration {
213 tskw<"abstract">? kw<"class"> VariableDefinition TypeParamList?
214 (kw<"extends"> expression)?
215 (tskw<"implements"> commaSep1<type>)?
216 ClassBody { "{" (
217 MethodDeclaration |
218 PropertyDeclaration |
219 IndexSignature semi
220 )* "}" }
221 } |
222 AmbientFunctionDeclaration {
223 async? kw<"function"> Star? VariableDefinition? TypeParamList? ParamList (TypeAnnotation | TypePredicate) semi
224 }
225 )
226}
227
228decoratorExpression {
229 VariableName |
230 MemberExpression { decoratorExpression !member ("." | questionDot) (PropertyName | PrivatePropertyName) } |
231 CallExpression { decoratorExpression !call TypeArgList? questionDot? ArgList } |
232 ParenthesizedExpression
233}
234
235Decorator { "@" decoratorExpression }
236
237pattern { VariableDefinition | ArrayPattern | ObjectPattern }
238
239ArrayPattern { "[" commaSep<("..."? patternAssign)?> ~destructure "]" }
240
241ObjectPattern { "{" commaSep<PatternProperty> ~destructure "}" }
242
243patternAssign {
244 pattern ("=" expressionNoComma)?
245}
246
247TypeAnnotation { ":" type }
248
249TypePredicate {
250 ":" (
251 tskw<"asserts"> (VariableName | kw<"this">) !predicate (tskw<"is"> type)? |
252 (VariableName | kw<"this">) !predicate tskw<"is"> type
253 )
254}
255
256patternAssignTyped {
257 pattern Optional? TypeAnnotation? ("=" expressionNoComma)?
258}
259
260ParamList {
261 "(" commaSep<"..." patternAssignTyped | Decorator* privacyArg? tskw<"readonly">? patternAssignTyped | kw<"this"> TypeAnnotation> ")"
262}
263
264Block {
265 !statement "{" statement* "}"
266}
267
268switchItem {
269 CaseLabel { kw<"case"> expression ":" } |
270 DefaultLabel { kw<"default"> ":" } |
271 statement
272}
273
274expression[@isGroup=Expression] {
275 expressionNoComma | SequenceExpression
276}
277
278SequenceExpression {
279 expressionNoComma !comma ("," expressionNoComma)+
280}
281
282expressionNoComma {
283 Number |
284 String |
285 TemplateString |
286 VariableName |
287 boolean |
288 kw<"this"> |
289 kw<"null"> |
290 kw<"super"> |
291 RegExp |
292 ArrayExpression |
293 ObjectExpression { "{" commaSep<Property> ~destructure "}" } |
294 NewTarget { kw<"new"> "." PropertyName } |
295 NewExpression { kw<"new"> expressionNoComma (!newArgs ArgList)? } |
296 UnaryExpression |
297 YieldExpression |
298 AwaitExpression |
299 ParenthesizedExpression |
300 ClassExpression |
301 FunctionExpression |
302 ArrowFunction |
303 MemberExpression |
304 BinaryExpression |
305 ConditionalExpression { expressionNoComma !ternary questionOp expressionNoComma LogicOp<":"> expressionNoComma } |
306 AssignmentExpression |
307 PostfixExpression { expressionNoComma !postfix (incdec | LogicOp<"!">) } |
308 CallExpression { expressionNoComma !call questionDot? ArgList } |
309 InstantiationExpression { (VariableName | MemberExpression) !instantiate TypeArgList } |
310 TaggedTemplateExpression { expressionNoComma !taggedTemplate TemplateString } |
311 DynamicImport { kw<"import"> "(" expressionNoComma ")" } |
312 ImportMeta { kw<"import"> "." PropertyName } |
313 JSXElement |
314 PrefixCast { tsAngleOpen (type | kw<"const">) ~tsAngle ">" expressionNoComma } |
315 ArrowFunction[@dynamicPrecedence=1] {
316 TypeParamList { tsAngleOpen commaSep<typeParam> ">" } ParamList TypeAnnotation? "=>" (Block | expressionNoComma)
317 }
318}
319
320ParenthesizedExpression { "(" expression ")" }
321
322ArrayExpression {
323 "[" commaSep1<"..."? expressionNoComma | ""> ~destructure "]"
324}
325
326propName { PropertyDefinition | "[" expression "]" ~destructure | Number ~destructure | String ~destructure }
327
328Property {
329 pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? propName functionSignature Block |
330 propName ~destructure (":" expressionNoComma)? |
331 "..." expressionNoComma
332}
333
334PatternProperty {
335 "..." patternAssign |
336 ((PropertyName | Number | String) ~destructure (":" pattern)? |
337 ("[" expression "]" ~destructure ":" pattern)) ("=" expressionNoComma)?
338}
339
340ClassExpression {
341 kw<"class"> VariableDefinition? (kw<"extends"> expression)? ClassBody
342}
343
344functionSignature { TypeParamList? ParamList (TypeAnnotation | TypePredicate)? }
345
346FunctionExpression {
347 async? kw<"function"> Star? VariableDefinition? functionSignature Block
348}
349
350YieldExpression[@dynamicPrecedence=1] {
351 !prefix ckw<"yield"> Star? expressionNoComma
352}
353
354AwaitExpression[@dynamicPrecedence=1] {
355 !prefix ckw<"await"> expressionNoComma
356}
357
358UnaryExpression {
359 !prefix (kw<"void"> | kw<"typeof"> | kw<"delete"> |
360 LogicOp<"!"> | BitOp<"~"> | incdec | incdecPrefix | plusMin)
361 expressionNoComma
362}
363
364BinaryExpression {
365 expressionNoComma !exp ArithOp<"**"> expressionNoComma |
366 expressionNoComma !times (divide | ArithOp<"%"> | ArithOp<"*">) expressionNoComma |
367 expressionNoComma !plus plusMin expressionNoComma |
368 expressionNoComma !shift BitOp<">>" ">"? | "<<"> expressionNoComma |
369 expressionNoComma !rel (LessThan | CompareOp<"<=" | ">" "="?> | kw<"instanceof">) expressionNoComma |
370 expressionNoComma !satisfies tskw<"satisfies"> type |
371 (expressionNoComma | PrivatePropertyName) !rel ~tsIn kw<"in"> expressionNoComma |
372 expressionNoComma !rel ckw<"as"> (kw<"const"> | type) |
373 expressionNoComma !rel tskw<"satisfies"> type |
374 expressionNoComma !equal CompareOp<"==" "="? | "!=" "="?> expressionNoComma |
375 expressionNoComma !bitOr BitOp { "|" } expressionNoComma |
376 expressionNoComma !bitXor BitOp<"^"> expressionNoComma |
377 expressionNoComma !bitAnd BitOp { "&" } expressionNoComma |
378 expressionNoComma !and LogicOp<"&&"> expressionNoComma |
379 expressionNoComma !or LogicOp<"||" | "??"> expressionNoComma
380}
381
382AssignmentExpression {
383 (VariableName | MemberExpression) !assign UpdateOp<($[+\-/%^] | "*" "*"? | "|" "|"? | "&" "&"? | "<<" | ">>" ">"? | "??") "=">
384 expressionNoComma |
385 (VariableName | MemberExpression | ArrayPattern | ObjectPattern) !assign "=" expressionNoComma
386}
387
388MemberExpression {
389 expressionNoComma !member (("." | questionDot) (PropertyName | PrivatePropertyName) | questionDot? "[" expression "]")
390}
391
392ArgList {
393 "(" commaSep<"..."? expressionNoComma> ")"
394}
395
396ArrowFunction {
397 async? (ParamList { VariableDefinition } | ParamList TypeAnnotation?) "=>" (Block | expressionNoComma)
398}
399
400TypeArgList[@dynamicPrecedence=1] {
401 @extend[@dialect=ts,@name="<"]<LessThan, "<"> commaSep<type> ">"
402}
403
404TypeParamList {
405 "<" commaSep<typeParam> ">"
406}
407
408typeParam { (kw<"in"> | tskw<"out"> | kw<"const">)? TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? }
409
410typeofExpression {
411 MemberExpression { typeofExpression !member (("." | questionDot) PropertyName | "[" expression "]") } |
412 InstantiationExpression { typeofExpression !instantiate TypeArgList } |
413 VariableName
414}
415
416type[@isGroup=Type] {
417 ThisType { kw<"this"> } |
418 LiteralType {
419 plusMin? Number |
420 boolean |
421 String
422 } |
423 TemplateType |
424 NullType { kw<"null"> } |
425 VoidType { kw<"void"> } |
426 TypeofType { kw<"typeof"> typeofExpression } |
427 KeyofType { !typePrefix tskw<"keyof"> type } |
428 UniqueType { !typePrefix tskw<"unique"> type } |
429 ImportType { kw<"import"> "(" String ")" } |
430 InferredType { tskw<"infer"> TypeName } |
431 ParenthesizedType { "(" type ")" } |
432 FunctionSignature { TypeParamList? ParamTypeList "=>" type } |
433 NewSignature { kw<"new"> ParamTypeList "=>" type } |
434 IndexedType |
435 TupleType { "[" commaSep<(Label ":")? type | "..." type> ~destructure "]" } |
436 ArrayType { type noSemiType "[" "]" } |
437 ReadonlyType { tskw<"readonly"> !readonly type } |
438 ObjectType |
439 UnionType {
440 type (!union unionOp type)+ |
441 unionOp type (!unionPrefixed unionOp type)*
442 } |
443 IntersectionType {
444 type (!intersection intersectionOp type)+ |
445 intersectionOp type (!intersectionPrefixed intersectionOp type)*
446 } |
447 ConditionalType { type !typeExtends kw<"extends"> type questionOp ~arrow type LogicOp<":"> type } |
448 ParameterizedType { (TypeName | IndexedType) !typeargs TypeArgList } |
449 TypeName
450}
451
452IndexedType {
453 type !typeMember ("." TypeName | noSemiType "[" type "]")+
454}
455
456ObjectType {
457 "{" (
458 (MethodType |
459 PropertyType |
460 IndexSignature |
461 CallSignature { ParamTypeList (TypeAnnotation | TypePredicate) } |
462 NewSignature[@dynamicPrecedence=1] { @extend[@name=new]<word, "new"> ParamTypeList TypeAnnotation })
463 ("," | semi)
464 )* ~destructure "}"
465}
466
467IndexSignature {
468 (plusMin? tsPkwMod<"readonly">)?
469 "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type (ckw<"as"> type)?) "]"
470 (plusMin? Optional)?
471 TypeAnnotation
472}
473
474MethodType {
475 pkwMod<"async">?
476 (pkwMod<"get"> | pkwMod<"set"> | Star)?
477 propName
478 (plusMin? Optional)?
479 functionSignature
480}
481
482PropertyType {
483 (plusMin? tsPkwMod<"readonly">)?
484 propName
485 (plusMin? Optional)?
486 TypeAnnotation
487}
488
489ParamTypeList[@name=ParamList] {
490 "(" commaSep<"..."? pattern ~arrow Optional? ~arrow TypeAnnotation? | kw<"this"> TypeAnnotation> ")"
491}
492
493@skip {} {
494 TemplateString[isolate] {
495 templateStart (templateEscape | templateContent | templateExpr)* templateEnd
496 }
497
498 TemplateType[isolate] {
499 templateStart (templateContent | templateType)* templateEnd
500 }
501
502 String[isolate] {
503 '"' (stringContentDouble | Escape)* ('"' | "\n") |
504 "'" (stringContentSingle | Escape)* ("'" | "\n")
505 }
506
507 BlockComment[isolate] { "/*" (blockCommentContent | blockCommentNewline)* blockCommentEnd }
508}
509
510templateExpr[@name=Interpolation,isolate] { InterpolationStart expression? InterpolationEnd }
511
512templateType[@name=Interpolation,isolate] { InterpolationStart type? InterpolationEnd }
513
514@skip {} {
515 JSXElement {
516 JSXSelfClosingTag |
517 (JSXOpenTag | JSXFragmentTag) (JSXText | JSXElement | JSXEscape)* JSXCloseTag
518 }
519}
520
521JSXSelfClosingTag { JSXStartTag jsxElementName jsxAttribute* JSXSelfCloseEndTag }
522
523JSXOpenTag { JSXStartTag jsxElementName jsxAttribute* JSXEndTag }
524
525JSXFragmentTag { JSXStartTag JSXEndTag }
526
527JSXCloseTag { JSXStartCloseTag jsxElementName? JSXEndTag }
528
529jsxElementName {
530 JSXIdentifier |
531 JSXBuiltin { JSXLowerIdentifier } |
532 JSXNamespacedName |
533 JSXMemberExpression
534}
535
536JSXMemberExpression { (JSXMemberExpression | JSXIdentifier | JSXLowerIdentifier) "." (JSXIdentifier | JSXLowerIdentifier) }
537
538JSXNamespacedName { (JSXIdentifier | JSXNamespacedName | JSXLowerIdentifier) ":" (JSXIdentifier | JSXLowerIdentifier) }
539
540jsxAttribute {
541 JSXSpreadAttribute { "{" "..." expression "}" } |
542 JSXAttribute { (JSXIdentifier | JSXNamespacedName | JSXLowerIdentifier) ("=" jsxAttributeValue)? }
543}
544
545jsxAttributeValue {
546 JSXAttributeValue |
547 JSXEscape { "{" expression "}" } |
548 JSXElement
549}
550
551JSXEscape { "{" "..."? expression "}" }
552
553commaSep<content> {
554 "" | content ("," content?)*
555}
556
557commaSep1<content> {
558 content ("," content)*
559}
560
561// Keywords
562
563kw<term> { @specialize[@name={term}]<identifier, term> }
564
565// Contextual keywords
566
567ckw<term> { @extend[@name={term}]<identifier, term> }
568
569tskw<term> { @extend[@name={term},@dialect=ts]<identifier, term> }
570
571async { @extend[@name=async]<identifier, "async"> }
572
573// Contextual keyword in property context
574
575pkwMod<term> { @extend[@name={term}]<word, term> }
576
577tsPkwMod<term> { @extend[@name={term},@dialect=ts]<word, term> }
578
579semi { ";" | insertSemi }
580
581boolean { @specialize[@name=BooleanLiteral]<identifier, "true" | "false"> }
582
583Star { "*" }
584
585VariableName { identifier ~arrow }
586
587VariableDefinition { identifier ~arrow }
588
589TypeDefinition { identifier }
590
591TypeName { identifier ~arrow }
592
593Label { identifier }
594
595PropertyName { word ~propName }
596
597PropertyDefinition { word ~propName }
598
599PrivatePropertyName { privateIdentifier }
600
601PrivatePropertyDefinition { privateIdentifier }
602
603Optional { "?" }
604
605questionOp[@name=LogicOp] { "?" }
606
607unionOp[@name=LogicOp] { "|" }
608
609plusMin { ArithOp<"+" | "-"> }
610
611intersectionOp[@name=LogicOp] { "&" }
612
613@skip { spaces | newline | LineComment | BlockComment }
614
615@context trackNewline from "./tokens.js"
616
617@external tokens noSemicolon from "./tokens" { noSemi }
618
619@external tokens noSemicolonType from "./tokens" { noSemiType }
620
621@external tokens operatorToken from "./tokens" {
622 incdec[@name=ArithOp],
623 incdecPrefix[@name=ArithOp]
624 questionDot[@name="?."]
625}
626
627@external tokens jsx from "./tokens" { JSXStartTag }
628
629@local tokens {
630 InterpolationStart[closedBy=InterpolationEnd] { "${" }
631 templateEnd { "`" }
632 templateEscape[@name=Escape] { Escape }
633 @else templateContent
634}
635
636@local tokens {
637 blockCommentEnd { "*/" }
638 blockCommentNewline { "\n" }
639 @else blockCommentContent
640}
641
642@tokens {
643 spaces[@export] { $[\u0009 \u000b\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]+ }
644 newline[@export] { $[\r\n\u2028\u2029] }
645
646 LineComment[isolate] { "//" ![\n]* }
647
648 Hashbang { "#!" ![\n]* }
649
650 divide[@name=ArithOp] { "/" }
651
652 @precedence { "/*", LineComment, divide }
653
654 @precedence { "/*", LineComment, RegExp }
655
656 identifierChar { @asciiLetter | $[_$\u{a1}-\u{10ffff}] }
657
658 word { identifierChar (identifierChar | @digit)* }
659
660 identifier { word }
661
662 privateIdentifier { "#" word }
663
664 @precedence { spaces, newline, identifier }
665
666 @precedence { spaces, newline, JSXIdentifier, JSXLowerIdentifier }
667
668 @precedence { spaces, newline, word }
669
670 hex { @digit | $[a-fA-F] }
671
672 Number {
673 (@digit ("_" | @digit)* ("." ("_" | @digit)*)? | "." @digit ("_" | @digit)*)
674 (("e" | "E") ("+" | "-")? ("_" | @digit)+)? |
675 @digit ("_" | @digit)* "n" |
676 "0x" (hex | "_")+ "n"? |
677 "0b" $[01_]+ "n"? |
678 "0o" $[0-7_]+ "n"?
679 }
680
681 @precedence { Number "." }
682
683 Escape {
684 "\\" ("x" hex hex | "u" ("{" hex+ "}" | hex hex hex hex) | ![xu])
685 }
686
687 stringContentSingle { ![\\\n']+ }
688
689 stringContentDouble { ![\\\n"]+ }
690
691 templateStart { "`" }
692
693 InterpolationEnd[openedBy=InterpolationStart] { "}" }
694
695 ArithOp<expr> { expr }
696 LogicOp<expr> { expr }
697 BitOp<expr> { expr }
698 CompareOp<expr> { expr }
699 UpdateOp<expr> { expr }
700
701 @precedence { "*", ArithOp }
702
703 RegExp[isolate] { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[dgimsuvy]*)? }
704
705 LessThan[@name=CompareOp] { "<" }
706
707 "="[@name=Equals]
708 "..."[@name=Spread]
709 "=>"[@name=Arrow]
710
711 "(" ")" "[" "]" "{" "}" "<" ">"
712
713 "." "," ";" ":" "@"
714
715 JSXIdentifier { $[A-Z_$\u{a1}-\u{10ffff}] (identifierChar | @digit | "-")* }
716 JSXLowerIdentifier[@name=JSXIdentifier] { $[a-z] (identifierChar | @digit | "-")* }
717
718 JSXAttributeValue { '"' !["]* '"' | "'" ![']* "'" }
719
720 JSXStartCloseTag { "</" }
721
722 JSXEndTag { ">" }
723
724 JSXSelfCloseEndTag { "/>" }
725
726 JSXText { ![<{]+ }
727
728 tsAngleOpen[@dialect=ts,@name="<"] { "<" }
729}
730
731@external tokens insertSemicolon from "./tokens" { insertSemi }
732
733@external propSource jsHighlight from "./highlight"
734
735@detectDelim