--- # This file is transformed into the equivalent JSON TextMate grammar, with the following additional # features available: # # The `regexOptions` Property # A top-level property named `regexOptions` may be defined with a string value. This string # represents the set of regular expression options to apply to all regular expressions throughout # the file. # # Macros # The `macros` element defines a map of macro names to replacement text. When a `match`, `begin`, or # `end` property has a value that is a single-key map, the value is replaced with the value of the # macro named by the key, with any use of `(?#)` in the macro text replaced with the text of the # value of the key, surrounded by a non-capturing group (`(?:)`). For example: # # The `beginPattern` and `endPattern` Properties # A rule can have a `beginPattern` or `endPattern` property whose value is a reference to another # rule (e.g. `#other-rule`). The `beginPattern` property is replaced as follows: # # my-rule: # beginPattern: '#other-rule' # # would be transformed to # # my-rule: # begin: '(?#other-rule)' # beginCaptures: # '0': # patterns: # - include: '#other-rule' # # An `endPattern` property is transformed similary. # # macros: # repeat: '(?#)*' # repository: # multi-letter: # match: # repeat: '[A-Za-z]' # name: scope.multi-letter # # would be transformed to # # repository: # multi-letter: # match: '(?:[A-Za-z])*' # name: scope.multi-letter # # Reference Expansion # Any comment of the form `(?#ref-id)` in a `match`, `begin`, or `end` property will be replaced # with the match text of the rule named "ref-id". If the rule named "ref-id" consists of just a # `patterns` property with a list of `include` directives, the replacement pattern is the # disjunction of the match patterns of all of the included rules. name: QL scopeName: source.ql fileTypes: [ql, qll] uuid: 7F6926BF-1C6C-468A-A7AA-215EBAC86A4E regexOptions: 'x' # Ignore pattern whitespace # Macros are parameterized patterns that can be used as a match elsewhere in the file. # To use a macro, replace the string for a `match`, `begin`, or `end` property with a single-element # map whose key is the name of the macro to invoke, and whose value is a string to be substituted for # any usage of `(?#)` in the macro pattern definition. macros: keyword: '\b(?#)(?#end-of-id)' patterns: - include: '#module-member' repository: # A character that can appear somewhere in an identifier. id-character: match: '[0-9A-Za-z_]' # Matches a position containing a non-identifier character. Used to ensure we do not match partial # identifiers/keywords in other rules. end-of-id: match: '(?!(?#id-character))' # A QL "simple identifier", which can begin with either an uppercase or a lowercase letter. simple-id: match: '\b [A-Za-z][0-9A-Za-z_]* (?#end-of-id)' # An identifier beginning with a lowercase letter. lower-id: match: '\b [a-z][0-9A-Za-z_]* (?#end-of-id)' # An identifier beginning with an uppercase letter. upper-id: match: '\b [A-Z][0-9A-Za-z_]* (?#end-of-id)' # An identifier beginning with an `@` followed by a lowercase letter. Used to represent database # types. at-lower-id: match: '@[a-z][0-9A-Za-z_]* (?#end-of-id)' # A pattern that can start a comment. comment-start: match: '// | /\*' # A pattern that can start a run of whitespace or a comment. # Commonly used as a negative lookahead in the `end` regex of a nonterminal, when searching for # tokens that can't start a child of that nonterminal. whitespace-or-comment-start: match: '\s | $ | (?#comment-start)' # All tokens that can appear in any context. non-context-sensitive: patterns: - include: '#comment' - include: '#literal' - include: '#operator-or-punctuation' - include: '#keyword' # Operators and punctuation relational-operator: match: '<=|<|>=|>' name: keyword.operator.relational.ql comparison-operator: match: '=|\!\=' name: keyword.operator.comparison.ql arithmetic-operator: match: '\+|-|\*|/|%' name: keyword.operator.arithmetic.ql comma: match: ',' name: punctuation.separator.comma.ql semicolon: match: ';' name: punctuation.separator.statement.ql dot: match: '\.' name: punctuation.accessor.ql dotdot: match: '\.\.' name: punctuation.operator.range.ql pipe: match: '\|' name: punctuation.separator.pipe.ql open-paren: match: '\(' name: punctuation.parenthesis.open.ql close-paren: match: '\)' name: punctuation.parenthesis.close.ql open-brace: match: '\{' name: punctuation.curlybrace.open.ql close-brace: match: '\}' name: punctuation.curlybrace.close.ql open-bracket: match: '\[' name: punctuation.squarebracket.open.ql close-bracket: match: '\]' name: punctuation.squarebracket.close.ql open-angle: match: '<' name: punctuation.anglebracket.open.ql close-angle: match: '>' name: punctuation.anglebracket.close.ql operator-or-punctuation: patterns: - include: '#relational-operator' - include: '#comparison-operator' - include: '#arithmetic-operator' - include: '#comma' - include: '#semicolon' - include: '#dot' - include: '#dotdot' - include: '#pipe' - include: '#open-paren' - include: '#close-paren' - include: '#open-brace' - include: '#close-brace' - include: '#open-bracket' - include: '#close-bracket' - include: '#open-angle' - include: '#close-angle' # Keywords dont-care: match: keyword: '_' name: variable.language.dont-care.ql and: match: keyword: 'and' name: keyword.other.and.ql any: match: keyword: 'any' name: keyword.quantifier.any.ql as: match: keyword: 'as' name: keyword.other.as.ql asc: match: keyword: 'asc' name: keyword.order.asc.ql avg: match: keyword: 'avg' name: keyword.aggregate.avg.ql boolean: match: keyword: 'boolean' name: keyword.type.boolean.ql by: match: keyword: 'by' name: keyword.order.by.ql class: match: keyword: 'class' name: keyword.other.class.ql concat: match: keyword: 'concat' name: keyword.aggregate.concat.ql count: match: keyword: 'count' name: keyword.aggregate.count.ql date: match: keyword: 'date' name: keyword.type.date.ql desc: match: keyword: 'desc' name: keyword.order.desc.ql else: match: keyword: 'else' name: keyword.other.else.ql exists: match: keyword: 'exists' name: keyword.quantifier.exists.ql extends: match: keyword: 'extends' name: keyword.other.extends.ql false: match: keyword: 'false' name: constant.language.boolean.false.ql float: match: keyword: 'float' name: keyword.type.float.ql forall: match: keyword: 'forall' name: keyword.quantifier.forall.ql forex: match: keyword: 'forex' name: keyword.quantifier.forex.ql from: match: keyword: 'from' name: keyword.other.from.ql if: match: keyword: 'if' name: keyword.other.if.ql implies: match: keyword: 'implies' name: keyword.other.implies.ql import: match: keyword: 'import' name: keyword.other.import.ql in: match: keyword: 'in' name: keyword.other.in.ql instanceof: match: keyword: 'instanceof' name: keyword.other.instanceof.ql int: match: keyword: 'int' name: keyword.type.int.ql max: match: keyword: 'max' name: keyword.aggregate.max.ql min: match: keyword: 'min' name: keyword.aggregate.min.ql module: match: keyword: 'module' name: keyword.other.module.ql newtype: match: keyword: 'newtype' name: keyword.other.newtype.ql none: match: keyword: 'none' name: keyword.quantifier.none.ql not: match: keyword: 'not' name: keyword.other.not.ql or: match: keyword: 'or' name: keyword.other.or.ql order: match: keyword: 'order' name: keyword.order.order.ql predicate: match: keyword: 'predicate' name: keyword.other.predicate.ql rank: match: keyword: 'rank' name: keyword.aggregate.rank.ql result: match: keyword: 'result' name: variable.language.result.ql select: match: keyword: 'select' name: keyword.query.select.ql strictconcat: match: keyword: 'strictconcat' name: keyword.aggregate.strictconcat.ql strictcount: match: keyword: 'strictcount' name: keyword.aggregate.strictcount.ql strictsum: match: keyword: 'strictsum' name: keyword.aggregate.strictsum.ql string: match: keyword: 'string' name: keyword.type.string.ql sum: match: keyword: 'sum' name: keyword.aggregate.sum.ql super: match: keyword: 'super' name: variable.language.super.ql then: match: keyword: 'then' name: keyword.other.then.ql this: match: keyword: 'this' name: variable.language.this.ql true: match: keyword: 'true' name: constant.language.boolean.true.ql unique: match: keyword: 'unique' name: keyword.aggregate.unique.ql where: match: keyword: 'where' name: keyword.query.where.ql # Any "true" keyword (not including annotations). keyword: patterns: - include: '#dont-care' - include: '#and' - include: '#any' - include: '#as' - include: '#asc' - include: '#avg' - include: '#boolean' - include: '#by' - include: '#class' - include: '#concat' - include: '#count' - include: '#date' - include: '#desc' - include: '#else' - include: '#exists' - include: '#extends' - include: '#false' - include: '#float' - include: '#forall' - include: '#forex' - include: '#from' - include: '#if' - include: '#implies' - include: '#import' - include: '#in' - include: '#instanceof' - include: '#int' - include: '#max' - include: '#min' - include: '#module' - include: '#newtype' - include: '#none' - include: '#not' - include: '#or' - include: '#order' - include: '#predicate' - include: '#rank' - include: '#result' - include: '#select' - include: '#strictconcat' - include: '#strictcount' - include: '#strictsum' - include: '#string' - include: '#sum' - include: '#super' - include: '#then' - include: '#this' - include: '#true' # `unique` is not really a keyword, but we'll highlight it as if it is. - include: '#unique' - include: '#where' # A keyword that can be the first token of a predicate declaration. predicate-start-keyword: patterns: - include: '#boolean' - include: '#date' - include: '#float' - include: '#int' - include: '#predicate' - include: '#string' # Annotation keywords abstract: match: keyword: 'abstract' name: storage.modifier.abstract.ql additional: match: keyword: 'additional' name: storage.modifier.additional.ql bindingset: match: keyword: 'bindingset' name: storage.modifier.bindingset.ql cached: match: keyword: 'cached' name: storage.modifier.cached.ql default: match: keyword: 'default' name: storage.modifier.default.ql deprecated: match: keyword: 'deprecated' name: storage.modifier.deprecated.ql external: match: keyword: 'external' name: storage.modifier.external.ql final: match: keyword: 'final' name: storage.modifier.final.ql language: match: keyword: 'language' name: storage.modifier.language.ql library: match: keyword: 'library' name: storage.modifier.library.ql override: match: keyword: 'override' name: storage.modifier.override.ql pragma: match: keyword: 'pragma' name: storage.modifier.pragma.ql private: match: keyword: 'private' name: storage.modifier.private.ql query: match: keyword: 'query' name: storage.modifier.query.ql signature: match: keyword: 'signature' name: storage.modifier.signature.ql transient: match: keyword: 'transient' name: storage.modifier.transient.ql annotation-keyword: patterns: - include: '#abstract' - include: '#additional' - include: '#bindingset' - include: '#cached' - include: '#default' - include: '#deprecated' - include: '#external' - include: '#final' - include: '#language' - include: '#library' - include: '#override' - include: '#pragma' - include: '#private' - include: '#query' - include: '#signature' - include: '#transient' implements: match: keyword: 'implements' name: keyword.other.implements.ql # A QL comment, regardless of form. comment: patterns: # A QLDoc (`/** */`) comment. - begin: '/\*\*' end: '\*/' name: comment.block.documentation.ql # Highlight tag names within the QLDoc. patterns: - begin: '(?<=/\*\*)([^*]|\*(?!/))*$' while: '(^|\G)\s*([^*]|\*(?!/))(?=([^*]|[*](?!/))*$)' patterns: - include: 'text.html.markdown#fenced_code_block' - include: 'text.html.markdown#lists' - include: 'text.html.markdown#inline' - match: '\G\s* (@\S+)' name: keyword.tag.ql # A block (`/* */`) comment. - begin: '/\*' end: '\*/' name: comment.block.ql # A single line (`//`) comment. - match: //.*$ name: comment.line.double-slash.ql # List of rules that can be matched within the body of a module, including at file scope. module-member: patterns: - include: '#import-directive' - include: '#import-as-clause' - include: '#module-declaration' - include: '#newtype-declaration' # See the comment on newtype-declaration for why we include these next three nonterminals at the # module-member level instead of as part of the newtype-declaration. - include: '#newtype-branch-name-with-prefix' - include: '#predicate-parameter-list' - include: '#predicate-body' - include: '#class-declaration' - include: '#select-clause' - include: '#predicate-or-field-declaration' - include: '#non-context-sensitive' - include: '#annotation' # The argument list of an instantiation, enclosed in angle brackets. instantiation-args: beginPattern: '#open-angle' endPattern: '#close-angle' name: meta.type.parameters.ql patterns: # Include `#instantiation-args` first so that `#open-angle` and `#close-angle` take precedence # over `#relational-operator`. - include: '#instantiation-args' - include: '#non-context-sensitive' - match: '(?#simple-id)' name: entity.name.type.namespace.ql # An `import` directive. Note that we parse the optional `as` clause as a separate top-level # directive, because otherwise it's too hard to figure out where the `import` directive ends. import-directive: beginPattern: '#import' # TextMate makes it tricky to tell whether an identifier that we encounter is part of the # `import` directive or whether it's the first token of the next module-level declaration. # To find the end of the import directive, we'll look for a zero-width match where the previous # token is either an identifier (other than `import`) or a `>`, and the next token is not a `.`, # `<`, `,`, or `::`. This works for nearly all real-world `import` directives, but it will end the # `import` directive too early if there is a comment or line break between two components of the # module expression. end: '(?)|[A-Za-z0-9_]) (?!\s*(\.|\:\:|\,|(?#open-angle)))' name: meta.block.import-directive.ql patterns: # Include `#instantiation-args` first so that `#open-angle` and `#close-angle` take precedence # over `#relational-operator`. - include: '#instantiation-args' - include: '#non-context-sensitive' - match: '(?#simple-id)' name: entity.name.type.namespace.ql # The end pattern for an `as` clause, whether on an `import` directive, in an aggregate, or on a # `select`. end-of-as-clause: match: '(?: (?<=(?#id-character)) (?!(?#id-character)) (?