package.src.javascript.grammar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javascript Show documentation
Show all versions of javascript Show documentation
lezer-based JavaScript grammar
@dialects { jsx, ts }
@precedence {
typeargs,
typeMember,
typePrefix,
intersection @left,
union @left,
typeExtends @right,
else @right,
member,
readonly,
newArgs,
call,
taggedTemplate,
prefix,
postfix,
typeof,
exp @left,
times @left,
plus @left,
shift @left,
loop,
rel @left,
satisfies,
equal @left,
bitOr @left,
bitXor @left,
bitAnd @left,
and @left,
or @left,
ternary @right,
assign @right,
comma @left,
statement @cut,
predicate
}
@top Script { Hashbang? statement+ }
@top SingleExpression { expression }
@top SingleClassItem { classItem }
statement[@isGroup=Statement] {
ExportDeclaration |
ImportDeclaration |
ForStatement { kw<"for"> ckw<"await">? (ForSpec | ForInSpec | ForOfSpec) statement } |
WhileStatement { kw<"while"> ParenthesizedExpression statement } |
WithStatement { kw<"with"> ParenthesizedExpression statement } |
DoStatement { kw<"do"> statement kw<"while"> ParenthesizedExpression semi } |
IfStatement { kw<"if"> ParenthesizedExpression statement (!else kw<"else"> statement)? } |
SwitchStatement { kw<"switch"> ParenthesizedExpression SwitchBody { "{" switchItem* "}" } } |
TryStatement {
kw<"try"> Block
CatchClause { kw<"catch"> ("(" pattern ")")? Block }?
FinallyClause { kw<"finally"> Block }?
} |
ReturnStatement { kw<"return"> (noSemi expression)? semi } |
ThrowStatement { kw<"throw"> expression semi } |
BreakStatement { kw<"break"> (noSemi Label)? semi } |
ContinueStatement { kw<"continue"> (noSemi Label)? semi } |
DebuggerStatement { kw<"debugger"> semi } |
Block |
LabeledStatement { Label ":" statement } |
declaration |
ExpressionStatement { expression semi } |
";"
}
ExportDeclaration {
kw<"export"> Star (ckw<"as"> (VariableName | String))? ckw<"from"> String semi |
kw<"export"> kw<"default"> (FunctionDeclaration | ClassDeclaration | expression semi) |
kw<"export"> tskw<"type">? declaration |
kw<"export"> tskw<"type">? ExportGroup (ckw<"from"> String)? semi |
kw<"export"> "=" expression semi
}
ExportGroup {
"{" commaSep (VariableName { word } | String))?> "}"
}
ImportDeclaration {
kw<"import"> tskw<"type">? (Star ckw<"as"> VariableDefinition | commaSep)
ckw<"from"> String semi |
kw<"import"> String semi
}
ImportGroup {
"{" commaSep? (VariableDefinition | (VariableName | String) ckw<"as"> VariableDefinition)> "}"
}
ForSpec {
"("
(VariableDeclaration | expression ";" | ";") expression? ";" expression?
")"
}
forXSpec {
"("
(variableDeclarationKeyword pattern | VariableName | MemberExpression | ArrayPattern | ObjectPattern)
!loop op expression
")"
}
ForInSpec { forXSpec> }
ForOfSpec { forXSpec> }
declaration {
FunctionDeclaration |
ClassDeclaration |
VariableDeclaration |
TypeAliasDeclaration |
InterfaceDeclaration |
EnumDeclaration |
NamespaceDeclaration |
AmbientDeclaration
}
FunctionDeclaration {
async? !statement kw<"function"> Star? VariableDefinition? functionSignature (Block | semi)
}
ClassDeclaration {
!statement Decorator* tskw<"abstract">? kw<"class"> VariableDefinition TypeParamList?
(kw<"extends"> ((VariableName | MemberExpression) !typeargs TypeArgList | expression))?
(tskw<"implements"> commaSep1)?
ClassBody
}
classItem { MethodDeclaration | PropertyDeclaration | StaticBlock | ";" }
ClassBody { "{" classItem* "}" }
privacy {
@extend[@name=Privacy,@dialect=ts]
}
privacyArg {
@extend[@name=Privacy,@dialect=ts]
}
propModifier {
Decorator |
tsPkwMod<"declare"> |
privacy |
pkwMod<"static"> |
tsPkwMod<"abstract"> |
tsPkwMod<"override">
}
MethodDeclaration[group=ClassItem] {
propModifier*
pkwMod<"async">?
(pkwMod<"get"> | pkwMod<"set"> | Star)?
(propName | PrivatePropertyDefinition)
functionSignature
(Block | semi)
}
StaticBlock[group=ClassItem] {
pkwMod<"static"> Block
}
PropertyDeclaration[group=ClassItem] {
propModifier*
(tsPkwMod<"readonly"> | pkwMod<"accessor">)?
(propName | PrivatePropertyDefinition)
(Optional | LogicOp<"!">)?
TypeAnnotation?
("=" expressionNoComma)?
semi
}
variableDeclarationKeyword {
kw<"let"> | kw<"var"> | kw<"const"> | ckw<"await">? ckw<"using">
}
VariableDeclaration {
variableDeclarationKeyword commaSep1 semi
}
TypeAliasDeclaration {
tskw<"type"> TypeDefinition TypeParamList? "=" type semi
}
InterfaceDeclaration {
tskw<"interface"> TypeDefinition TypeParamList? (kw<"extends"> type)? ObjectType
}
EnumDeclaration {
kw<"const">? tskw<"enum"> TypeDefinition EnumBody { "{" commaSep "}" }
}
NamespaceDeclaration {
(tskw<"namespace"> | tskw<"module">) VariableDefinition ("." PropertyDefinition)* Block
}
AmbientDeclaration {
tskw<"declare"> (
VariableDeclaration |
TypeAliasDeclaration |
EnumDeclaration |
InterfaceDeclaration |
NamespaceDeclaration |
GlobalDeclaration { tskw<"global"> Block } |
ClassDeclaration {
tskw<"abstract">? kw<"class"> VariableDefinition TypeParamList?
(kw<"extends"> expression)?
(tskw<"implements"> commaSep1)?
ClassBody { "{" (
MethodDeclaration |
PropertyDeclaration |
IndexSignature semi
)* "}" }
} |
AmbientFunctionDeclaration {
async? kw<"function"> Star? VariableDefinition? TypeParamList? ParamList (TypeAnnotation | TypePredicate) semi
}
)
}
decoratorExpression {
VariableName |
MemberExpression { decoratorExpression !member ("." | "?.") (PropertyName | PrivatePropertyName) } |
CallExpression { decoratorExpression !call TypeArgList? "?."? ArgList } |
ParenthesizedExpression
}
Decorator { "@" decoratorExpression }
pattern { VariableDefinition | ArrayPattern | ObjectPattern }
ArrayPattern { "[" commaSep<("..."? patternAssign)?> ~destructure "]" }
ObjectPattern { "{" commaSep ~destructure "}" }
patternAssign {
pattern ("=" expressionNoComma)?
}
TypeAnnotation { ":" type }
TypePredicate { ":" (VariableName | kw<"this">) !predicate tskw<"is"> type }
patternAssignTyped {
pattern Optional? TypeAnnotation? ("=" expressionNoComma)?
}
ParamList {
"(" commaSep<"..." patternAssignTyped | Decorator* privacyArg? tskw<"readonly">? patternAssignTyped | kw<"this"> TypeAnnotation> ")"
}
Block {
!statement "{" statement* "}"
}
switchItem {
CaseLabel { kw<"case"> expression ":" } |
DefaultLabel { kw<"default"> ":" } |
statement
}
expression[@isGroup=Expression] {
expressionNoComma | SequenceExpression
}
SequenceExpression {
expressionNoComma !comma ("," expressionNoComma)+
}
expressionNoComma {
Number |
String |
TemplateString |
VariableName |
boolean |
kw<"this"> |
kw<"null"> |
kw<"super"> |
RegExp |
ArrayExpression |
ObjectExpression { "{" commaSep ~destructure "}" } |
NewExpression { kw<"new"> expressionNoComma (!newArgs TypeArgList? ArgList)? } |
UnaryExpression |
YieldExpression |
AwaitExpression |
ParenthesizedExpression |
ClassExpression |
FunctionExpression |
ArrowFunction |
MemberExpression |
BinaryExpression |
ConditionalExpression { expressionNoComma !ternary questionOp expressionNoComma LogicOp<":"> expressionNoComma } |
AssignmentExpression |
PostfixExpression { expressionNoComma !postfix (incdec | LogicOp<"!">) } |
CallExpression { expressionNoComma !call TypeArgList? "?."? ArgList } |
TaggedTemplateExpression { expressionNoComma !taggedTemplate TemplateString } |
DynamicImport { kw<"import"> "(" expressionNoComma ")" } |
ImportMeta { kw<"import"> "." PropertyName } |
JSXElement |
PrefixCast { tsAngleOpen type ~tsAngle ">" expressionNoComma } |
ArrowFunction[@dynamicPrecedence=1] {
TypeParamList { tsAngleOpen commaSep ">" } ParamList TypeAnnotation? "=>" (Block | expressionNoComma)
}
}
ParenthesizedExpression { "(" expression ")" }
ArrayExpression {
"[" commaSep1<"..."? expressionNoComma | ""> ~destructure "]"
}
propName { PropertyDefinition | "[" expression "]" | Number | String }
Property {
pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? propName functionSignature Block |
propName ~destructure (":" expressionNoComma)? |
"..." expressionNoComma
}
PatternProperty {
"..." patternAssign |
((PropertyName | Number | String) ~destructure (":" pattern)? |
("[" expression "]" ~destructure ":" pattern)) ("=" expressionNoComma)?
}
ClassExpression {
kw<"class"> VariableDefinition? (kw<"extends"> expression)? ClassBody
}
functionSignature { TypeParamList? ParamList (TypeAnnotation | TypePredicate)? }
FunctionExpression {
async? kw<"function"> Star? VariableDefinition? functionSignature Block
}
YieldExpression[@dynamicPrecedence=1] {
!prefix ckw<"yield"> Star? expressionNoComma
}
AwaitExpression[@dynamicPrecedence=1] {
!prefix ckw<"await"> expressionNoComma
}
UnaryExpression {
!prefix (kw<"void"> | kw<"typeof"> | kw<"delete"> |
LogicOp<"!"> | BitOp<"~"> | incdec | incdecPrefix | ArithOp<"+" | "-">)
expressionNoComma
}
BinaryExpression {
expressionNoComma !exp ArithOp<"**"> expressionNoComma |
expressionNoComma !times (divide | ArithOp<"%"> | ArithOp<"*">) expressionNoComma |
expressionNoComma !plus ArithOp<"+" | "-"> expressionNoComma |
expressionNoComma !shift BitOp<">>" ">"? | "<<"> expressionNoComma |
expressionNoComma !rel (LessThan | CompareOp<"<=" | ">" "="?> | kw<"instanceof">) expressionNoComma |
expressionNoComma !satisfies tskw<"satisfies"> type |
(expressionNoComma | PrivatePropertyName) !rel ~tsIn kw<"in"> expressionNoComma |
expressionNoComma !rel ckw<"as"> (kw<"const"> | type) |
expressionNoComma !equal CompareOp<"==" "="? | "!=" "="?> expressionNoComma |
expressionNoComma !bitOr BitOp { "|" } expressionNoComma |
expressionNoComma !bitXor BitOp<"^"> expressionNoComma |
expressionNoComma !bitAnd BitOp { "&" } expressionNoComma |
expressionNoComma !and LogicOp<"&&"> expressionNoComma |
expressionNoComma !or LogicOp<"||" | "??"> expressionNoComma
}
AssignmentExpression {
(VariableName | MemberExpression) !assign UpdateOp<($[+\-/%^] | "*" "*"? | "|" "|"? | "&" "&"? | "<<" | ">>" ">"? | "??") "=">
expressionNoComma |
(VariableName | MemberExpression | ArrayPattern | ObjectPattern) !assign "=" expressionNoComma
}
MemberExpression {
expressionNoComma !member (("." | "?.") (PropertyName | PrivatePropertyName) | "?."? "[" expression "]")
}
ArgList {
"(" commaSep<"..."? expressionNoComma> ")"
}
ArrowFunction {
async? (ParamList { VariableDefinition } | ParamList TypeAnnotation?) "=>" (Block | expressionNoComma)
}
TypeArgList[@dynamicPrecedence=1] {
@extend[@dialect=ts,@name="<"] commaSep ">"
}
TypeParamList {
"<" commaSep ">"
}
typeParam { TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? }
typeofMemberExpression[@name=MemberExpression] {
VariableName !member (("." | "?.") PropertyName | "[" expression "]")
}
type[@isGroup=Type] {
ThisType { kw<"this"> } |
LiteralType {
ArithOp<"+" | "-">? Number |
boolean |
String
} |
TemplateType |
NullType { kw<"null"> } |
VoidType { kw<"void"> } |
TypeofType { kw<"typeof"> (VariableName | typeofMemberExpression) } |
KeyofType { !typePrefix tskw<"keyof"> type } |
UniqueType { !typePrefix tskw<"unique"> type } |
ImportType { kw<"import"> "(" String ")" } |
InferredType { tskw<"infer"> TypeName } |
ParenthesizedType { "(" type ")" } |
FunctionSignature { TypeParamList? ParamTypeList "=>" type } |
NewSignature { kw<"new"> ParamTypeList "=>" type } |
IndexedType |
TupleType { "[" commaSep<(Label ":")? type | "..." type> "]" } |
ArrayType { type "[" "]" | type "[" "]" } |
ReadonlyType { tskw<"readonly"> !readonly type } |
ObjectType |
UnionType { type !union LogicOp { "|" } type } |
IntersectionType { type !intersection LogicOp { "&" } type } |
ConditionalType { type !typeExtends kw<"extends"> type questionOp ~arrow type LogicOp<":"> type } |
ParameterizedType { (TypeName | IndexedType) !typeargs TypeArgList } |
TypeName
}
IndexedType {
type !typeMember ("." TypeName | "[" type "]")+
}
ObjectType {
"{" (
(MethodType |
PropertyType |
IndexSignature |
CallSignature { ParamTypeList (TypeAnnotation | TypePredicate) } |
NewSignature[@dynamicPrecedence=1] { @extend[@name=new] ParamTypeList TypeAnnotation })
("," | semi)
)* "}"
}
IndexSignature {
tsPkwMod<"readonly">? "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type) "]" TypeAnnotation
}
MethodType {
pkwMod<"async">?
(pkwMod<"get"> | pkwMod<"set"> | Star)?
PropertyDefinition
functionSignature
}
PropertyType {
(ArithOp<"+" | "-">? tsPkwMod<"readonly">)?
PropertyDefinition
(ArithOp<"+" | "-">? Optional)?
TypeAnnotation
}
ParamTypeList[@name=ParamList] {
"(" commaSep<"..."? VariableDefinition ~arrow Optional? ~arrow TypeAnnotation?> ")"
}
@skip {} {
TemplateString {
templateStart (templateEscape | templateContent | templateExpr)* templateEnd
}
TemplateType {
templateStart (templateContent | templateType)* templateEnd
}
String {
'"' (stringContentDouble | Escape)* ('"' | "\n") |
"'" (stringContentSingle | Escape)* ("'" | "\n")
}
BlockComment { "/*" (blockCommentContent | blockCommentNewline)* blockCommentEnd }
}
templateExpr[@name=Interpolation] { InterpolationStart expression InterpolationEnd }
templateType[@name=Interpolation] { InterpolationStart type InterpolationEnd }
@skip {} {
JSXElement {
JSXSelfClosingTag |
(JSXOpenTag | JSXFragmentTag) (JSXText | JSXElement | JSXEscape)* JSXCloseTag
}
}
JSXSelfClosingTag { JSXStartTag jsxElementName jsxAttribute* JSXSelfCloseEndTag }
JSXOpenTag { JSXStartTag jsxElementName jsxAttribute* JSXEndTag }
JSXFragmentTag { JSXStartTag JSXEndTag }
JSXCloseTag { JSXStartCloseTag jsxElementName? JSXEndTag }
jsxElementName {
JSXIdentifier |
JSXBuiltin { JSXLowerIdentifier } |
JSXNamespacedName |
JSXMemberExpression
}
JSXMemberExpression { (JSXMemberExpression | JSXIdentifier | JSXLowerIdentifier) "." (JSXIdentifier | JSXLowerIdentifier) }
JSXNamespacedName { (JSXIdentifier | JSXNamespacedName | JSXLowerIdentifier) ":" (JSXIdentifier | JSXLowerIdentifier) }
jsxAttribute {
JSXSpreadAttribute { "{" "..." expression "}" } |
JSXAttribute { (JSXIdentifier | JSXNamespacedName | JSXLowerIdentifier) ("=" jsxAttributeValue)? }
}
jsxAttributeValue {
JSXAttributeValue |
JSXEscape { "{" expression "}" } |
JSXElement
}
JSXEscape { "{" "..."? expression "}" }
commaSep {
"" | content ("," content?)*
}
commaSep1 {
content ("," content)*
}
// Keywords
kw { @specialize[@name={term}] }
// Contextual keywords
ckw { @extend[@name={term}] }
tskw { @extend[@name={term},@dialect=ts] }
async { @extend[@name=async] }
// Contextual keyword in property context
pkwMod { @extend[@name={term}] }
tsPkwMod { @extend[@name={term},@dialect=ts] }
semi { ";" | insertSemi }
boolean { @specialize[@name=BooleanLiteral] }
Star { "*" }
VariableName { identifier ~arrow }
VariableDefinition { identifier ~arrow }
TypeDefinition { identifier }
TypeName { identifier ~arrow }
Label { identifier }
PropertyName { word }
PropertyDefinition { word }
PrivatePropertyName { privateIdentifier }
PrivatePropertyDefinition { privateIdentifier }
Optional { "?" }
questionOp[@name=LogicOp] { "?" }
@skip { spaces | newline | LineComment | BlockComment }
@context trackNewline from "./tokens.js"
@external tokens noSemicolon from "./tokens" { noSemi }
@external tokens incdecToken from "./tokens" {
incdec[@name=ArithOp],
incdecPrefix[@name=ArithOp]
}
@local tokens {
InterpolationStart[closedBy=InterpolationEnd] { "${" }
templateEnd { "`" }
templateEscape[@name=Escape] { Escape }
@else templateContent
}
@local tokens {
blockCommentEnd { "*/" }
blockCommentNewline { "\n" }
@else blockCommentContent
}
@tokens {
spaces[@export] { $[\u0009 \u000b\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]+ }
newline[@export] { $[\r\n\u2028\u2029] }
LineComment { "//" ![\n]* }
Hashbang { "#!" ![\n]* }
divide[@name=ArithOp] { "/" }
@precedence { "/*", LineComment, divide }
@precedence { "/*", LineComment, RegExp }
identifierChar { @asciiLetter | $[_$\u{a1}-\u{10ffff}] }
word { identifierChar (identifierChar | @digit)* }
identifier { word }
privateIdentifier { "#" word }
@precedence { spaces, newline, identifier }
@precedence { spaces, newline, JSXIdentifier, JSXLowerIdentifier }
@precedence { spaces, newline, word }
hex { @digit | $[a-fA-F] }
Number {
(@digit ("_" | @digit)* ("." ("_" | @digit)*)? | "." @digit ("_" | @digit)*)
(("e" | "E") ("+" | "-")? ("_" | @digit)+)? |
@digit ("_" | @digit)* "n" |
"0x" (hex | "_")+ "n"? |
"0b" $[01_]+ "n"? |
"0o" $[0-7_]+ "n"?
}
@precedence { Number "." }
Escape {
"\\" ("x" hex hex | "u" ("{" hex+ "}" | hex hex hex hex) | ![xu])
}
stringContentSingle { ![\\\n']+ }
stringContentDouble { ![\\\n"]+ }
templateStart { "`" }
InterpolationEnd[openedBy=InterpolationStart] { "}" }
ArithOp { expr }
LogicOp { expr }
BitOp { expr }
CompareOp { expr }
UpdateOp { expr }
@precedence { "*", ArithOp }
RegExp { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[gimsuy]*)? }
LessThan[@name=CompareOp] { "<" }
"="[@name=Equals]
"..."[@name=Spread]
"=>"[@name=Arrow]
"(" ")" "[" "]" "{" "}" ">"
"?." "." "," ";" ":" "@"
JSXIdentifier { $[A-Z_$\u{a1}-\u{10ffff}] (identifierChar | @digit | "-")* }
JSXLowerIdentifier[@name=JSXIdentifier] { $[a-z] (identifierChar | @digit | "-")* }
JSXAttributeValue { '"' !["]* '"' | "'" ![']* "'" }
JSXStartTag[@dialect=jsx] { "<" }
JSXStartCloseTag { "" }
JSXEndTag { ">" }
JSXSelfCloseEndTag { "/>" }
JSXText { ![<{]+ }
tsAngleOpen[@dialect=ts] { "<" }
@precedence { JSXStartTag, tsAngleOpen }
}
@external tokens insertSemicolon from "./tokens" { insertSemi }
@external propSource jsHighlight from "./highlight"
@detectDelim
© 2015 - 2025 Weber Informatics LLC | Privacy Policy