basb-cli
Version:
Blog as Second Brain!
337 lines (317 loc) • 7.47 kB
JavaScript
import {
concat,
either
} from '../../lib/regex.js';
export const keywordWrapper = keyword => concat(
/\b/,
keyword,
/\w$/.test(keyword) ? /\b/ : /\B/
);
// Keywords that require a leading dot.
export const dotKeywords = [
'Protocol', // contextual
'Type' // contextual
].map(keywordWrapper);
// Keywords that may have a leading dot.
export const optionalDotKeywords = [
'init',
'self'
].map(keywordWrapper);
// should register as keyword, not type
export const keywordTypes = [
'Any',
'Self'
];
// Regular keywords and literals.
export const keywords = [
// strings below will be fed into the regular `keywords` engine while regex
// will result in additional modes being created to scan for those keywords to
// avoid conflicts with other rules
'actor',
'any', // contextual
'associatedtype',
'async',
'await',
/as\?/, // operator
/as!/, // operator
'as', // operator
'borrowing', // contextual
'break',
'case',
'catch',
'class',
'consume', // contextual
'consuming', // contextual
'continue',
'convenience', // contextual
'copy', // contextual
'default',
'defer',
'deinit',
'didSet', // contextual
'distributed',
'do',
'dynamic', // contextual
'each',
'else',
'enum',
'extension',
'fallthrough',
/fileprivate\(set\)/,
'fileprivate',
'final', // contextual
'for',
'func',
'get', // contextual
'guard',
'if',
'import',
'indirect', // contextual
'infix', // contextual
/init\?/,
/init!/,
'inout',
/internal\(set\)/,
'internal',
'in',
'is', // operator
'isolated', // contextual
'nonisolated', // contextual
'lazy', // contextual
'let',
'macro',
'mutating', // contextual
'nonmutating', // contextual
/open\(set\)/, // contextual
'open', // contextual
'operator',
'optional', // contextual
'override', // contextual
'postfix', // contextual
'precedencegroup',
'prefix', // contextual
/private\(set\)/,
'private',
'protocol',
/public\(set\)/,
'public',
'repeat',
'required', // contextual
'rethrows',
'return',
'set', // contextual
'some', // contextual
'static',
'struct',
'subscript',
'super',
'switch',
'throws',
'throw',
/try\?/, // operator
/try!/, // operator
'try', // operator
'typealias',
/unowned\(safe\)/, // contextual
/unowned\(unsafe\)/, // contextual
'unowned', // contextual
'var',
'weak', // contextual
'where',
'while',
'willSet' // contextual
];
// NOTE: Contextual keywords are reserved only in specific contexts.
// Ideally, these should be matched using modes to avoid 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 (#).
// #(un)available is handled separately.
export const numberSignKeywords = [
'#colorLiteral',
'#column',
'#dsohandle',
'#else',
'#elseif',
'#endif',
'#error',
'#file',
'#fileID',
'#fileLiteral',
'#filePath',
'#function',
'#if',
'#imageLiteral',
'#keyPath',
'#line',
'#selector',
'#sourceLocation',
'#warning'
];
// Global functions in the Standard Library.
export const builtIns = [
'abs',
'all',
'any',
'assert',
'assertionFailure',
'debugPrint',
'dump',
'fatalError',
'getVaList',
'isKnownUniquelyReferenced',
'max',
'min',
'numericCast',
'pointwiseMax',
'pointwiseMin',
'precondition',
'preconditionFailure',
'print',
'readLine',
'repeatElement',
'sequence',
'stride',
'swap',
'swift_unboxFromSwiftValueWithType',
'transcode',
'type',
'unsafeBitCast',
'unsafeDowncast',
'withExtendedLifetime',
'withUnsafeMutablePointer',
'withUnsafePointer',
'withVaList',
'withoutActuallyEscaping',
'zip'
];
// Valid first characters for operators.
export const operatorHead = either(
/[/=\-+!*%<>&|^~?]/,
/[\u00A1-\u00A7]/,
/[\u00A9\u00AB]/,
/[\u00AC\u00AE]/,
/[\u00B0\u00B1]/,
/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,
/[\u2016-\u2017]/,
/[\u2020-\u2027]/,
/[\u2030-\u203E]/,
/[\u2041-\u2053]/,
/[\u2055-\u205E]/,
/[\u2190-\u23FF]/,
/[\u2500-\u2775]/,
/[\u2794-\u2BFF]/,
/[\u2E00-\u2E7F]/,
/[\u3001-\u3003]/,
/[\u3008-\u3020]/,
/[\u3030]/
);
// Valid characters for operators.
export const operatorCharacter = either(
operatorHead,
/[\u0300-\u036F]/,
/[\u1DC0-\u1DFF]/,
/[\u20D0-\u20FF]/,
/[\uFE00-\uFE0F]/,
/[\uFE20-\uFE2F]/
// TODO: The following characters are also allowed, but the regex isn't supported yet.
// /[\u{E0100}-\u{E01EF}]/u
);
// Valid operator.
export const operator = concat(operatorHead, operatorCharacter, '*');
// Valid first characters for identifiers.
export const identifierHead = either(
/[a-zA-Z_]/,
/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,
/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,
/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,
/[\u1E00-\u1FFF]/,
/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,
/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,
/[\u2C00-\u2DFF\u2E80-\u2FFF]/,
/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,
/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,
/[\uFE47-\uFEFE\uFF00-\uFFFD]/ // Should be /[\uFE47-\uFFFD]/, but we have to exclude FEFF.
// The following characters are also allowed, but the regexes aren't supported yet.
// /[\u{10000}-\u{1FFFD}\u{20000-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}]/u,
// /[\u{50000}-\u{5FFFD}\u{60000-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}]/u,
// /[\u{90000}-\u{9FFFD}\u{A0000-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}]/u,
// /[\u{D0000}-\u{DFFFD}\u{E0000-\u{EFFFD}]/u
);
// Valid characters for identifiers.
export const identifierCharacter = either(
identifierHead,
/\d/,
/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/
);
// Valid identifier.
export const identifier = concat(identifierHead, identifierCharacter, '*');
// Valid type identifier.
export const typeIdentifier = concat(/[A-Z]/, identifierCharacter, '*');
// Built-in attributes, which are highlighted as keywords.
// @available is handled separately.
// https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes
export const keywordAttributes = [
'attached',
'autoclosure',
concat(/convention\(/, either('swift', 'block', 'c'), /\)/),
'discardableResult',
'dynamicCallable',
'dynamicMemberLookup',
'escaping',
'freestanding',
'frozen',
'GKInspectable',
'IBAction',
'IBDesignable',
'IBInspectable',
'IBOutlet',
'IBSegueAction',
'inlinable',
'main',
'nonobjc',
'NSApplicationMain',
'NSCopying',
'NSManaged',
concat(/objc\(/, identifier, /\)/),
'objc',
'objcMembers',
'propertyWrapper',
'requires_stored_property_inits',
'resultBuilder',
'Sendable',
'testable',
'UIApplicationMain',
'unchecked',
'unknown',
'usableFromInline',
'warn_unqualified_access'
];
// Contextual keywords used in @available and #(un)available.
export const availabilityKeywords = [
'iOS',
'iOSApplicationExtension',
'macOS',
'macOSApplicationExtension',
'macCatalyst',
'macCatalystApplicationExtension',
'watchOS',
'watchOSApplicationExtension',
'tvOS',
'tvOSApplicationExtension',
'swift'
];