Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(swift) Support operator and precedencegroup declarations. #2938

Merged
merged 2 commits into from Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGES.md
Expand Up @@ -4,7 +4,19 @@ New Languages:

- Added 3rd party Laravel Blade grammar to SUPPORTED_LANGUAGES (#2944) [Michael Newton][]

Language grammar improvements:

- enh(swift) Improved highlighting for operator and precedencegroup declarations. (#2938) [Steven Van Impe][]

Parser:

- add `modes.MATCH_NOTHING_RE` that will never match
- This can be used with `end` to hold a mode open (it must then be ended with
`endsParent` in one of it's children modes) [Josh Goebel][]

[Michael Newton]: https://github.com/miken32
[Steven Van Impe]: https://github.com/svanimpe/
[Josh Goebel]: https://github.com/joshgoebel


## Version 10.5.0
Expand Down
15 changes: 11 additions & 4 deletions src/languages/lib/kws_swift.js
Expand Up @@ -117,17 +117,24 @@ export const keywords = [
// NOTE: Contextual keywords are reserved only in specific contexts.
// Ideally, these should be matched using modes to avoid false positives.

// TODO: Create a PRECEDENCE_GROUP mode to match the remaining contextual keywords:
// assignment associativity higherThan left lowerThan none right
// These aren't included in the list because they result in mostly false positives.

// Literals.
export const literals = [
'false',
'nil',
'true'
];

// Keywords used in precedence groups.
export const precedencegroupKeywords = [
'assignment',
'associativity',
'higherThan',
'left',
'lowerThan',
'none',
'right'
];

// Keywords that start with a number sign (#).
// #available is handled separately.
export const numberSignKeywords = [
Expand Down
39 changes: 39 additions & 0 deletions src/languages/swift.js
Expand Up @@ -413,6 +413,43 @@ export default function(hljs) {
],
illegal: /\[|%/
};
// https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380
const OPERATOR_DECLARATION = {
beginKeywords: 'operator',
end: hljs.MATCH_NOTHING_RE,
contains: [
{
className: 'title',
match: Swift.operator,
endsParent: true,
relevance: 0
}
]
};

// https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID550
const PRECEDENCEGROUP = {
beginKeywords: 'precedencegroup',
end: hljs.MATCH_NOTHING_RE,
contains: [
{
className: 'title',
match: Swift.typeIdentifier,
relevance: 0
},
{
begin: /{/,
end: /}/,
relevance: 0,
endsParent: true,
keywords: [
...Swift.precedencegroupKeywords,
...Swift.literals
].join(' '),
contains: [ TYPE ]
}
]
};

// Add supported submodes to string interpolation.
for (const variant of STRING.variants) {
Expand Down Expand Up @@ -460,6 +497,8 @@ export default function(hljs) {
...KEYWORD_MODES
]
},
OPERATOR_DECLARATION,
PRECEDENCEGROUP,
{
beginKeywords: 'import',
end: /$/,
Expand Down
1 change: 1 addition & 0 deletions src/lib/modes.js
Expand Up @@ -2,6 +2,7 @@ import { inherit } from './utils.js';
import * as regex from './regex.js';

// Common regexps
export const MATCH_NOTHING_RE = /\b\B/;
export const IDENT_RE = '[a-zA-Z]\\w*';
export const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*';
export const NUMBER_RE = '\\b\\d+(\\.\\d+)?';
Expand Down
3 changes: 3 additions & 0 deletions test/markup/swift/operator-declarations.expect.txt
@@ -0,0 +1,3 @@
<span class="hljs-keyword">prefix</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">+++</span>
<span class="hljs-keyword">postfix</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">+++</span>
<span class="hljs-keyword">infix</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">+-</span>: <span class="hljs-type">AdditionPrecedence</span>
3 changes: 3 additions & 0 deletions test/markup/swift/operator-declarations.txt
@@ -0,0 +1,3 @@
prefix operator +++
postfix operator +++
infix operator +-: AdditionPrecedence
8 changes: 8 additions & 0 deletions test/markup/swift/precedencegroup.expect.txt
@@ -0,0 +1,8 @@
<span class="hljs-keyword">precedencegroup</span> <span class="hljs-title">MyGroup</span> {
<span class="hljs-keyword">higherThan</span>: <span class="hljs-type">OtherGroup</span>, <span class="hljs-type">AnotherGroup</span>
<span class="hljs-keyword">lowerThan</span>: <span class="hljs-type">OtherGroup</span>, <span class="hljs-type">AnotherGroup</span>
<span class="hljs-keyword">assignment</span>: <span class="hljs-keyword">true</span>
<span class="hljs-keyword">associativity</span>: <span class="hljs-keyword">left</span>
<span class="hljs-keyword">associativity</span>: <span class="hljs-keyword">right</span>
<span class="hljs-keyword">associativity</span>: <span class="hljs-keyword">none</span>
}
8 changes: 8 additions & 0 deletions test/markup/swift/precedencegroup.txt
@@ -0,0 +1,8 @@
precedencegroup MyGroup {
higherThan: OtherGroup, AnotherGroup
lowerThan: OtherGroup, AnotherGroup
assignment: true
associativity: left
associativity: right
associativity: none
}
1 change: 1 addition & 0 deletions types/index.d.ts
Expand Up @@ -58,6 +58,7 @@ interface ModesAPI {
// built in regex
IDENT_RE: string
UNDERSCORE_IDENT_RE: string
MATCH_NOTHING_RE: string
NUMBER_RE: string
C_NUMBER_RE: string
BINARY_NUMBER_RE: string
Expand Down