grammars/jsoniq.cson
name: "JSONiq"
scopeName: "source.jsoniq"
fileTypes: [
"jq"
]
firstLineMatch: "^\\bjsoniq\\s+version\\b.*"
foldingStartMarker: "^\\s*(<[^!?%/](?!.+?(/>|</.+?>))|<[!%]--(?!.+?--%?>)|<%[!]?(?!.+?%>))|(declare|.*\\{\\s*(//.*)?$)"
foldingStopMarker: "^\\s*(</[^>]+>|[/%]>|-->)\\s*$|(.*\\}\\s*;?\\s*|.*;)"
patterns: [include: "#main"]
repository:
# Grammar's entry-point
main:
patterns: [
{include: "#EmbeddedXQuery"}
{include: "#Pragma"}
{include: "#XMLComment"}
{include: "#CDATA"}
{include: "#PredefinedEntityRef"}
{include: "#CharRef"}
{include: "#Comments"}
{include: "#String"}
{include: "#Annotation"}
{include: "#AbbrevForwardStep"}
{include: "#Variable"}
{include: "#Numbers"}
{include: "#Keywords"}
{include: "#EQName"}
{include: "#Symbols"}
{include: "#OpenTag"}
{include: "#CloseTag"}
]
AbbrevForwardStep:
name: "support.type.jsoniq"
match: "(@)(?:\\*\\s|(?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-._a-zA-Z0-9]*)"
captures:
1: name: "punctuation.definition.type.jsoniq"
Annotation:
name: "meta.declaration.annotation.jsoniq"
match: "(%+)((?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-._a-zA-Z0-9]*)"
captures:
1: name: "punctuation.definition.annotation.jsoniq"
2: name: "entity.name.annotation.jsoniq"
CDATA:
name: "string.unquoted.cdata.jsoniq"
begin: "<!\\[CDATA\\["
end: "\\]\\]>"
beginCaptures: 0: name: "punctuation.definition.string.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.string.end.jsoniq"
CharRef:
name: "constant.character.entity.jsoniq"
match: "(&#)([0-9]+|x[0-9A-Fa-f]+)(;)"
captures:
1: name: "punctuation.definition.entity.begin.jsoniq"
2: name: "entity.name.entity.other.jsoniq"
3: name: "punctuation.definition.entity.end.jsoniq"
CloseTag:
name: "meta.tag.closetag.jsoniq"
match: "(<\\/)((?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-_a-zA-Z0-9]*)\\s*(>)"
captures:
1: name: "punctuation.definition.tag.begin.jsoniq"
2: name: "entity.name.tag.localname.jsoniq"
3: name: "punctuation.definition.tag.end.jsoniq"
Comments:
patterns: [{
name: "comment.block.doc.jsoniq"
begin: "\\(:~"
end: ":\\)"
beginCaptures: 0: name: "punctuation.definition.comment.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.comment.end.jsoniq"
patterns: [{
name: "constant.language.jsoniq"
match: "(@)[a-zA-Z0-9_\\.\\-]+"
captures:
1: name: "punctuation.definition.jsoniq"
}]
},{
# <? … ?>
name: "comment.block.jsoniq"
begin: "<\\?"
end: "\\?>"
beginCaptures: 0: name: "punctuation.definition.comment.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.comment.end.jsoniq"
},{
# (: … :)
name: "comment.block.jsoniq"
begin: "\\(:"
end: ":\\)"
beginCaptures: 0: name: "punctuation.definition.comment.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.comment.end.jsoniq"
}]
EmbeddedXQuery:
begin: "^(?=xquery\\s+version\\s+)"
end: "\\z"
contentName: "source.embedded.xq"
patterns: [include: "source.xq"]
EQName:
name: "support.function.eqname.jsoniq"
match: "(?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-_a-zA-Z0-9]*(?=\\s*\\()"
Keywords:
patterns: [{
name: "constant.language.${1:/downcase}.jsoniq"
match: "\\b(NaN|null)\\b"
},{
name: "constant.language.boolean.logical.$1.jsoniq"
match: "\\b(true|false)\\b"
},{
name: "storage.type.$1.jsoniq"
match: "\\b(function|let)\\b"
},{
# FIXME: Both this list and the one below are probably incorrectly categorised
# as "operators" or "control flow". I'll leave their categorisation to somebody
# familiar with JSONiq ⸻ @Alhadis
name: "keyword.control.flow.$1.jsoniq"
match: """(?x) \\b
( break
| case
| catch
| continue
| end
| exit
| for
| from
| if
| import
| in
| loop
| return
| switch
| then
| try
| when
| where
| while
| with
) \\b
"""
},{
name: "keyword.operator.$1.jsoniq"
match: """(?x) \\b
( after
| allowing
| ancestor-or-self
| ancestor
| and
| append
| array
| ascending
| as
| attribute
| at
| base-uri
| before
| boundary-space
| by
| castable
| cast
| child
| collation
| comment
| constraint
| construction
| contains
| context
| copy-namespaces
| copy
| count
| decimal-format
| decimal-separator
| declare
| default
| delete
| descendant-or-self
| descendant
| descending
| digit
| div
| document-node
| document
| element
| else
| empty-sequence
| empty
| encoding
| eq
| every
| except
| external
| first
| following-sibling
| following
| ft-option
| ge
| greatest
| grouping-separator
| group
| gt
| idiv
| index
| infinity
| insert
| instance
| integrity
| intersect
| into
| is
| item
| json-item
| jsoniq
| json
| last
| lax
| least
| le
| lt
| minus-sign
| modify
| module
| mod
| namespace-node
| namespace
| next
| ne
| nodes
| node
| not
| object
| of
| only
| option
| ordered
| ordering
| order
| or
| paragraphs
| parent
| pattern-separator
| per-mille
| percent
| preceding-sibling
| preceding
| previous
| processing-instruction
| rename
| replace
| returning
| revalidation
| satisfies
| schema-attribute
| schema-element
| schema
| score
| select
| self
| sentences
| sliding
| some
| stable
| start
| strict
| text
| times
| to
| treat
| tumbling
| typeswitch
| type
| union
| unordered
| updating
| validate
| value
| variable
| version
| window
| words
| xquery
| zero-digit
) (?!:|-)\\b
"""
}]
EnclosedExpr:
name: "meta.enclosed.expression.jsoniq"
begin: "{"
end: "}"
beginCaptures: 0: name: "punctuation.section.scope.begin.jsoniq"
endCaptures: 0: name: "punctuation.section.scope.end.jsoniq"
patterns: [include: "#main"]
Numbers:
patterns: [{
name: "constant.numeric.exponential.jsoniq"
match: "(?:\\.[0-9]+|\\b[0-9]+(?:\\.[0-9]*)?)[Ee][+#x002D]?[0-9]+\\b"
},{
name: "constant.numeric.float.jsoniq"
match: "(?:\\.[0-9]+|\\b[0-9]+\\.[0-9]*)\\b"
},{
name: "constant.numeric.integer.jsoniq"
match: "\\b[0-9]+\\b"
}]
OpenTag:
name: "meta.tag.opentag.jsoniq"
begin: "(<)((?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-_a-zA-Z0-9]*)"
end: "/?>"
beginCaptures:
1: name: "punctuation.definition.tag.begin.jsoniq"
2: name: "entity.name.tag.localname.jsoniq"
endCaptures:
0: name: "punctuation.definition.tag.end.jsoniq"
patterns: [{
name: "entity.other.attribute-name.jsoniq"
match: "([-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?([-_a-zA-Z0-9][-_a-zA-Z0-9]*)"
},{
name: "keyword.operator.assignment.jsoniq"
match: "="
},{
name: "string.quoted.single.jsoniq"
begin: "'"
end: "'(?!')"
patterns: [
{match: "''", name: "constant.character.escape.quote.jsoniq"}
{include: "#PredefinedEntityRef"}
{include: "#CharRef"}
{match: "({{|}})", name: "constant.jsoniq"}
{include: "#EnclosedExpr"}
]
},{
name: "string.quoted.double.jsoniq"
begin: '"'
end: '"(?!")'
patterns: [
{match: '""', name: "constant.character.escape.quote.jsoniq"}
{include: "#PredefinedEntityRef"}
{include: "#CharRef"}
{match: "({{|}})", name: "string.jsoniq"}
{include: "#EnclosedExpr"}
]
}]
# (# … #)
Pragma:
name: "meta.pragma.jsoniq"
begin: "\\(#"
end: "#\\)"
beginCaptures: 0: name: "punctuation.definition.pragma.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.pragma.end.jsoniq"
contentName: "constant.other.pragma.jsoniq"
PredefinedEntityRef:
name: "constant.language.entity.predefined.jsoniq"
match: "(&)(lt|gt|amp|quot|apos)(;)"
captures:
1: name: "punctuation.definition.entity.begin.jsoniq"
2: name: "entity.name.entity.other.jsoniq"
3: name: "punctuation.definition.entity.end.jsoniq"
# "Double-quoted string"
String:
name: "string.quoted.double.jsoniq"
begin: '"'
end: '"'
patterns: [{
name: "constant.character.escape.jsoniq"
match: '\\\\(?:["\\\\/bfnrt]|u[0-9a-fA-F]{4})'
},{
name: "invalid.illegal.unrecognized-string-escape.jsoniq"
match: "\\\\."
}]
# Punctuation and stuff
Symbols:
patterns: [
{match: ":=?", name: "keyword.operator.assignment.definition.jsoniq"}
{match: ",", name: "punctuation.separator.delimiter.comma.jsoniq"}
{match: "\\.", name: "punctuation.separator.delimiter.dot.jsoniq"}
{match: "\\[", name: "punctuation.definition.bracket.square.begin.jsoniq"}
{match: "\\]", name: "punctuation.definition.bracket.square.end.jsoniq"}
{match: "\\{", name: "punctuation.definition.bracket.curly.begin.jsoniq"}
{match: "\\}", name: "punctuation.definition.bracket.curly.end.jsoniq"}
{match: "\\(", name: "punctuation.definition.bracket.round.begin.jsoniq"}
{match: "\\)", name: "punctuation.definition.bracket.round.end.jsoniq"}
]
# $variable_name
Variable:
name: "meta.definition.variable.name.jsoniq"
match: "(\\$)(?:[-_a-zA-Z0-9][-._a-zA-Z0-9]*:)?[-_a-zA-Z0-9][-_a-zA-Z0-9]*"
captures:
0: name: "variable.other.jsoniq"
1: name: "punctuation.definition.variable.jsoniq"
# <!-- … -->
XMLComment:
name: "comment.block.jsoniq"
begin: "<!--"
end: "-->"
beginCaptures: 0: name: "punctuation.definition.comment.begin.jsoniq"
endCaptures: 0: name: "punctuation.definition.comment.end.jsoniq"