diff --git a/unified/extractor/tests/rules_macro_smoke.rs b/unified/extractor/tests/rules_macro_smoke.rs deleted file mode 100644 index cde8ae3ca4a..00000000000 --- a/unified/extractor/tests/rules_macro_smoke.rs +++ /dev/null @@ -1,25 +0,0 @@ -/// Smoke test: load a few real Swift translation rules through the new -/// `yeast::rules!` macro using the bare-rule-body syntax, and confirm the -/// input + output schemas accept them. Compiles only — any type-checking -/// error surfaces as a compile-time error. -#[test] -fn rules_macro_compiles_against_real_swift_schemas() { - let _rules: Vec = yeast::rules! { - input: "tree-sitter-swift/node-types.yml", - output: "ast_types.yml", - [ - (simple_identifier) @name - => - (name_expr - identifier: (identifier #{name})), - - (integer_literal) @lit - => - (int_literal #{lit}), - - (line_string_literal) @lit - => - (string_literal #{lit}), - ] - }; -} diff --git a/unified/extractor/tree-sitter-swift/.gitignore b/unified/extractor/tree-sitter-swift/.gitignore deleted file mode 100644 index 53796875297..00000000000 --- a/unified/extractor/tree-sitter-swift/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Generated by tree-sitter from grammar.js. The Cargo build script -# (bindings/rust/build.rs) and Bazel's cargo_build_script regenerate them into -# OUT_DIR. The tree-sitter CLI (parse, test, playground, etc.) expects them in -# src/, so contributors can run `tree-sitter generate` locally to populate -# these — they are intentionally untracked. -src/parser.c -src/grammar.json -src/node-types.json -src/tree_sitter/ diff --git a/unified/extractor/tree-sitter-swift/BUILD.bazel b/unified/extractor/tree-sitter-swift/BUILD.bazel deleted file mode 100644 index f865f22a142..00000000000 --- a/unified/extractor/tree-sitter-swift/BUILD.bazel +++ /dev/null @@ -1,42 +0,0 @@ -load("@rules_rust//cargo:defs.bzl", "cargo_build_script") -load("@rules_rust//rust:defs.bzl", "rust_library") -load("//misc/bazel/3rdparty/tree_sitter_extractors_deps:defs.bzl", "aliases", "all_crate_deps") - -package(default_visibility = ["//visibility:public"]) - -# This will run the build script from the root of the workspace, and -# collect the outputs. -cargo_build_script( - name = "tree-sitter-swift-build", - srcs = ["bindings/rust/build.rs"], - data = glob([ - "src/scanner.c", - ]) + [ - "grammar.js", - ], - deps = all_crate_deps( - build = True, - ), -) - -rust_library( - name = "tree-sitter-swift", - srcs = [ - "bindings/rust/lib.rs", - ], - aliases = aliases(), - compile_data = glob([ - "src/**", - "queries/**", - ]) + [ - "grammar.js", - ], - proc_macro_deps = all_crate_deps( - proc_macro = True, - ), - deps = [":tree-sitter-swift-build"] + all_crate_deps( - normal = True, - ), -) - -exports_files(["Cargo.toml"]) diff --git a/unified/extractor/tree-sitter-swift/Cargo.toml b/unified/extractor/tree-sitter-swift/Cargo.toml deleted file mode 100644 index 8cec03889a8..00000000000 --- a/unified/extractor/tree-sitter-swift/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "tree-sitter-swift" -description = "Swift grammar for the tree-sitter parsing library (vendored copy for the unified extractor)" -version = "0.7.2" -keywords = ["incremental", "parsing", "swift"] -categories = ["parsing", "text-editors"] -repository = "https://github.com/alex-pinkus/tree-sitter-swift" -edition = "2024" -license = "MIT" - -build = "bindings/rust/build.rs" - -[lib] -path = "bindings/rust/lib.rs" - -# When updating these dependencies, run `misc/bazel/3rdparty/update_cargo_deps.sh` -[dependencies] -tree-sitter-language = "0.1" - -[build-dependencies] -cc = "1.2" -tree-sitter-generate = "0.26.8" diff --git a/unified/extractor/tree-sitter-swift/LICENSE b/unified/extractor/tree-sitter-swift/LICENSE deleted file mode 100644 index f158d700531..00000000000 --- a/unified/extractor/tree-sitter-swift/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 alex-pinkus - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/unified/extractor/tree-sitter-swift/README.md b/unified/extractor/tree-sitter-swift/README.md deleted file mode 100644 index 5b54f4b617f..00000000000 --- a/unified/extractor/tree-sitter-swift/README.md +++ /dev/null @@ -1,127 +0,0 @@ -![Parse rate badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/parse_rate) -[![Crates.io badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/crates_io_version)](https://crates.io/crates/tree-sitter-swift) -[![NPM badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/npm_version)](https://www.npmjs.com/package/tree-sitter-swift) -[![Build](https://github.com/alex-pinkus/tree-sitter-swift/actions/workflows/top-repos.yml/badge.svg)](https://github.com/alex-pinkus/tree-sitter-swift/actions/workflows/top-repos.yml) - -# tree-sitter-swift - -This contains a [`tree-sitter`](https://tree-sitter.github.io/tree-sitter) grammar for the Swift programming language. - -## Getting started - -To use this parser to parse Swift code, you'll want to depend on either the Rust crate or the NPM package. - -### Rust - -To use the Rust crate, you'll add this to your `Cargo.toml`: - -``` -tree-sitter = "0.23.0" -tree-sitter-swift = "=0.7.0" -``` - -Then you can use a `tree-sitter` parser with the language declared here: - -``` -let mut parser = tree_sitter::Parser::new(); -parser.set_language(tree_sitter_swift::language())?; - -// ... - -let tree = parser.parse(&my_source_code, None) - .ok_or_else(|| /* error handling code */)?; -``` - -### Javascript - -To use this from NPM, you'll add similar dependencies to `package.json`: - -``` -"dependencies: { - "tree-sitter-swift": "0.7.0", - "tree-sitter": "^0.22.1" -} -``` - -Your usage of the parser will look like: - -``` -const Parser = require("tree-sitter"); -const Swift = require("tree-sitter-swift"); - -const parser = new Parser(); -parser.setLanguage(Swift); - -// ... - -const tree = parser.parse(mySourceCode); -``` - -### Editing the grammar - -With this package checked out, a common workflow for editing the grammar will look something like: - -1. Make a change to `grammar.ts`. -2. Run `npm install && npm test` to see whether the change has had impact on existing parsing behavior. The default - `npm test` target requires `valgrind` to be installed; if you do not have it installed, and do not wish to, you can - substitute `tree-sitter test` directly. -3. Run `tree-sitter parse` on some real Swift codebase and see whether (or where) it fails. -4. Use any failures to create new corpus test cases. - -## Contributions - -All contributions to this repository are welcome. - -If said contribution is to check generated files (e.g., `parser.c`) into the repository, be aware that your contribution will not be accepted. Make sure to read the [FAQ entry](https://github.com/alex-pinkus/tree-sitter-swift?tab=readme-ov-file#where-is-your-parserc) and the [prior](https://github.com/alex-pinkus/tree-sitter-swift/issues/362) [discussions](https://github.com/alex-pinkus/tree-sitter-swift/pull/315) and [compromises](https://github.com/alex-pinkus/tree-sitter-swift/issues/149) that have occurred already on this topic. - -## Using tree-sitter-swift in Web Assembly - -To use tree-sitter-swift as a language for the web bindings version tree-sitter, which will likely be a more modern version than the published node -module. [see](https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/README.md). Follow the instructions below - -1. Install the node modules `npm install web-tree-sitter tree-sitter-swift` -2. Run the tree-sitter cli to create the wasm bundle - ```sh - $ npx tree-sitter build-asm ./node_modules/tree-sitter - ``` -3. Boot tree-sitter wasm like this. - -```js -const Parser = require("web-tree-sitter"); -async function run() { - //needs to happen first - await Parser.init(); - //wait for the load of swift - const Swift = await Parser.Language.load("./tree-sitter-swift.wasm"); - - const parser = new Parser(); - parser.setLanguage(Swift); - - //Parse your swift code here. - const tree = parser.parse('print("Hello, World!")'); -} -//if you want to run this -run().then(console.log, console.error); -``` - -## Frequently asked questions - -### Where is your `parser.c`? - -This repository currently omits most of the code that is autogenerated during a build. This means, for instance, that -`grammar.json` and `parser.c` are both only available following a build. It also significantly reduces noise during -diffs. - -The side benefit of not checking in `parser.c` is that you can guarantee backwards compatibility. Parsers generated by -the tree-sitter CLI aren't always backwards compatible. If you need a parser, generate it yourself using the CLI; all -the information to do so is available in this package. By doing that, you'll also know for sure that your parser version -and your library version are compatible. - -If you need a `parser.c`, and you don't care about the tree-sitter version, but you don't have a local setup that would -allow you to obtain the parser, you can just download one from a recent workflow run in this package. To do so: - -- Go to the [GitHub actions page](https://github.com/alex-pinkus/tree-sitter-swift/actions) for this - repository. -- Click on the "Publish `grammar.json` and `parser.c`" action for the appropriate commit. -- Go down to `Artifacts` and click on `generated-parser-src`. All the relevant parser files will be available in your - download. diff --git a/unified/extractor/tree-sitter-swift/binding.gyp b/unified/extractor/tree-sitter-swift/binding.gyp deleted file mode 100644 index 4d9270af7d4..00000000000 --- a/unified/extractor/tree-sitter-swift/binding.gyp +++ /dev/null @@ -1,44 +0,0 @@ -{ - "targets": [ - { - "target_name": "tree_sitter_swift_binding", - "dependencies": [ - " - -typedef struct TSLanguage TSLanguage; - -extern "C" TSLanguage *tree_sitter_swift(); - -// "tree-sitter", "language" hashed with BLAKE2 -const napi_type_tag LANGUAGE_TYPE_TAG = { - 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 -}; - -Napi::Object Init(Napi::Env env, Napi::Object exports) { - exports["name"] = Napi::String::New(env, "swift"); - auto language = Napi::External::New(env, tree_sitter_swift()); - language.TypeTag(&LANGUAGE_TYPE_TAG); - exports["language"] = language; - return exports; -} - -NODE_API_MODULE(tree_sitter_swift_binding, Init) diff --git a/unified/extractor/tree-sitter-swift/bindings/node/index.js b/unified/extractor/tree-sitter-swift/bindings/node/index.js deleted file mode 100644 index 6657bcf42de..00000000000 --- a/unified/extractor/tree-sitter-swift/bindings/node/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const root = require("path").join(__dirname, "..", ".."); - -module.exports = require("node-gyp-build")(root); - -try { - module.exports.nodeTypeInfo = require("../../src/node-types.json"); -} catch (_) {} diff --git a/unified/extractor/tree-sitter-swift/bindings/rust/build.rs b/unified/extractor/tree-sitter-swift/bindings/rust/build.rs deleted file mode 100644 index 2dd899ea521..00000000000 --- a/unified/extractor/tree-sitter-swift/bindings/rust/build.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - // tree-sitter-generate produces parser.c, grammar.json, node-types.json, - // and src/tree_sitter/*.h headers from grammar.js. We write them into - // OUT_DIR so the build is sandbox-friendly and we don't litter the source - // tree. - let crate_dir: PathBuf = env::var("CARGO_MANIFEST_DIR").unwrap().into(); - let out_dir: PathBuf = env::var("OUT_DIR").unwrap().into(); - let grammar_js = crate_dir.join("grammar.js"); - - tree_sitter_generate::generate_parser_in_directory( - &crate_dir, - Some(&out_dir), - Some(&grammar_js), - tree_sitter_generate::ABI_VERSION_MAX, - None, - // Evaluate grammar.js with the embedded QuickJS runtime instead of - // spawning `node`, which isn't available inside Bazel's sandbox. - Some("native"), - true, - tree_sitter_generate::OptLevel::default(), - ) - .expect("failed to generate tree-sitter-swift parser"); - - let mut c_config = cc::Build::new(); - c_config - .std("c11") - .include(&out_dir) - .include(out_dir.join("tree_sitter")); - - #[cfg(target_env = "msvc")] - c_config.flag("-utf-8"); - - c_config.file(out_dir.join("parser.c")); - - // scanner.c is hand-written and lives in the source tree. - let scanner_path = crate_dir.join("src").join("scanner.c"); - c_config.include(crate_dir.join("src")).file(&scanner_path); - - println!("cargo:rerun-if-changed={}", grammar_js.to_str().unwrap()); - println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); - // Re-export OUT_DIR so consumers can include_str! the generated files. - println!( - "cargo:rustc-env=TREE_SITTER_SWIFT_OUT_DIR={}", - out_dir.to_str().unwrap() - ); - - c_config.compile("tree-sitter-swift"); -} diff --git a/unified/extractor/tree-sitter-swift/bindings/rust/lib.rs b/unified/extractor/tree-sitter-swift/bindings/rust/lib.rs deleted file mode 100644 index 891df87778f..00000000000 --- a/unified/extractor/tree-sitter-swift/bindings/rust/lib.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! This crate provides Swift language support for the [tree-sitter][] parsing library. -//! -//! Typically, you will use the [language][language func] function to add this language to a -//! tree-sitter [Parser][], and then use the parser to parse some code: -//! -//! ``` -//! let code = r#" -//! "#; -//! let mut parser = tree_sitter::Parser::new(); -//! let language = tree_sitter_swift::LANGUAGE; -//! parser -//! .set_language(&language.into()) -//! .expect("Error loading Swift parser"); -//! let tree = parser.parse(code, None).unwrap(); -//! assert!(!tree.root_node().has_error()); -//! ``` -//! -//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html -//! [language func]: fn.language.html -//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html -//! [tree-sitter]: https://tree-sitter.github.io/ - -use tree_sitter_language::LanguageFn; - -unsafe extern "C" { - fn tree_sitter_swift() -> *const (); -} - -/// The tree-sitter [`LanguageFn`] for this grammar. -pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_swift) }; - -/// The content of the [`node-types.json`][] file for this grammar. -/// -/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types -pub const NODE_TYPES: &str = include_str!(concat!(env!("TREE_SITTER_SWIFT_OUT_DIR"), "/node-types.json")); - -pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); -pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm"); -pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); -pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm"); - -#[cfg(test)] -mod tests { - #[test] - fn test_can_load_grammar() { - let mut parser = tree_sitter::Parser::new(); - parser - .set_language(&super::LANGUAGE.into()) - .expect("Error loading Swift parser"); - } - - #[test] - fn test_can_parse_basic_file() { - let mut parser = tree_sitter::Parser::new(); - parser - .set_language(&super::LANGUAGE.into()) - .expect("Error loading Swift parser"); - - let tree = parser - .parse("_ = \"Hello!\"\n", None) - .expect("Unable to parse!"); - - assert_eq!( - "(source_file (assignment target: (directly_assignable_expression (simple_identifier)) result: (line_string_literal text: (line_str_text))))", - tree.root_node().to_sexp(), - ); - } -} diff --git a/unified/extractor/tree-sitter-swift/grammar.js b/unified/extractor/tree-sitter-swift/grammar.js deleted file mode 100644 index 7052d2ebdd5..00000000000 --- a/unified/extractor/tree-sitter-swift/grammar.js +++ /dev/null @@ -1,2113 +0,0 @@ -"use strict"; -/* - * MIT License - * - * Copyright (c) 2021 alex-pinkus - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -const PRECS = { - multiplication: 11, - addition: 10, - infix_operations: 9, - nil_coalescing: 8, - check: 7, - prefix_operations: 7, - comparison: 6, - postfix_operations: 6, - equality: 5, - conjunction: 4, - disjunction: 3, - block: 2, - loop: 1, - keypath: 1, - parameter_pack: 1, - control_transfer: 0, - as: -1, - tuple: -1, - if: -1, - switch: -1, - do: -1, - fully_open_range: -1, - range: -1, - navigation: -1, - expr: -1, - ty: -1, - call: -2, - ternary: -2, - try: -2, - call_suffix: -2, - range_suffix: -2, - ternary_binary_suffix: -2, - await: -2, - assignment: -3, - comment: -3, - lambda: -3, - regex: -4, -}; - -const DYNAMIC_PRECS = { - call: 1, -}; - -const DEC_DIGITS = token(sep1(/[0-9]+/, /_+/)); -const HEX_DIGITS = token(sep1(/[0-9a-fA-F]+/, /_+/)); -const OCT_DIGITS = token(sep1(/[0-7]+/, /_+/)); -const BIN_DIGITS = token(sep1(/[01]+/, /_+/)); -const REAL_EXPONENT = token(seq(/[eE]/, optional(/[+-]/), DEC_DIGITS)); -const HEX_REAL_EXPONENT = token(seq(/[pP]/, optional(/[+-]/), DEC_DIGITS)); - -var LEXICAL_IDENTIFIER; - -if (tree_sitter_version_supports_emoji()) { - LEXICAL_IDENTIFIER = - /[_\p{XID_Start}\p{Emoji}&&[^0-9#*]](\p{EMod}|\x{FE0F}\x{20E3}?)?([_\p{XID_Continue}\p{Emoji}\x{200D}](\p{EMod}|\x{FE0F}\x{20E3}?)?)*/; -} else { - LEXICAL_IDENTIFIER = /[_\p{XID_Start}][_\p{XID_Continue}]*/; -} - -module.exports = grammar({ - name: "swift", - supertypes: ($) => [ - $.expression, - $.unannotated_type, - $.global_declaration, - $.type_level_declaration, - $.local_declaration, - $.protocol_member_declaration, - ], - conflicts: ($) => [ - // @Type(... could either be an annotation constructor invocation or an annotated expression - [$.attribute], - [$._attribute_argument], - // Is `foo { ... }` a constructor invocation or function invocation? - [$.simple_user_type, $.expression], - // To support nested types A.B not being interpreted as `(navigation_expression ... (type_identifier)) (navigation_suffix)` - [$.user_type], - // How to tell the difference between Foo.bar(with:and:), and Foo.bar(with: smth, and: other)? You need GLR - [$.value_argument], - // { (foo, bar) ... - [$.expression, $.lambda_parameter], - [$._primary_expression, $.lambda_parameter], - // (foo) where foo could be a binding pattern or a tuple expression item. - [$._binding_pattern_with_expr, $.tuple_expression_item], - // After a `{` in a function or switch context, it's ambigous whether we're starting a set of local statements or - // applying some modifiers to a capture or pattern. - [$.modifiers], - // `+(...)` is ambigously either "call the function produced by a reference to the operator `+`" or "use the unary - // operator `+` on the result of the parenthetical expression." - [$._additive_operator, $._prefix_unary_operator], - [$.referenceable_operator, $._prefix_unary_operator], - // `{ [self, b, c] ...` could be a capture list or an array literal depending on what else happens. - [$.capture_list_item, $.expression], - [$.capture_list_item, $.expression, $.simple_user_type], - [$._primary_expression, $.capture_list_item], - // a ? b : c () could be calling c(), or it could be calling a function that's produced by the result of - // `(a ? b : c)`. We have a small hack to force it to be the former of these by intentionally introducing a - // conflict. - [$.call_suffix, $.expr_hack_at_ternary_binary_call_suffix], - // try {expression} is a bit magic and applies quite broadly: `try foo()` and `try foo { }` show that this is right - // associative, and `try foo ? bar() : baz` even more so. But it doesn't always win: something like - // `if try foo { } ...` should award its braces to the `if`. In order to make this actually happen, we need to parse - // all the options and pick the best one that doesn't error out. - [$.try_expression, $._unary_expression], - [$.try_expression, $.expression], - // await {expression} has the same special cases as `try`. - [$.await_expression, $._unary_expression], - [$.await_expression, $.expression], - // In a computed property, when you see an @attribute, it's not yet clear if that's going to be for a - // locally-declared class or a getter / setter specifier. - [ - $._local_property_declaration, - $._local_typealias_declaration, - $._local_function_declaration, - $._local_class_declaration, - $.computed_getter, - $.computed_modify, - $.computed_setter, - ], - // The `class` modifier is legal in many of the same positions that a class declaration itself would be. - [$._bodyless_function_declaration, $.property_modifier], - [$.init_declaration, $.property_modifier], - // Patterns, man - [$._navigable_type_expression, $.case_pattern], - [$._no_expr_pattern_already_bound, $._binding_pattern_no_expr], - - // On encountering a closure starting with `{ @Foo ...`, we don't yet know if that attribute applies to the closure - // type or to a declaration within the closure. What a mess! We just have to hope that if we keep going, only one of - // those will parse (because there will be an `in` or a `let`). - [ - $._lambda_type_declaration, - $._local_property_declaration, - $._local_typealias_declaration, - $._local_function_declaration, - $._local_class_declaration, - ], - - // We want `foo() { }` to be treated as one function call, but we _also_ want `if foo() { ... }` to be treated as a - // full if-statement. This means we have to treat it as a conflict rather than purely a left or right associative - // construct, and let the parser realize that the second expression won't parse properly with the `{ ... }` as a - // lambda. - [$.constructor_suffix], - [$.call_suffix], - - // `actor` is allowed to be an identifier, even though it is also a locally permitted declaration. If we encounter - // it, the only way to know what it's meant to be is to keep going. - [$._modifierless_class_declaration, $.property_modifier], - [$._fn_call_lambda_arguments], - - // `borrowing` and `consuming` are legal as identifiers, but are also legal modifiers - [$.parameter_modifiers], - - // These are keywords sometimes, but simple identifiers other times, and it just depends on the rest of their usage. - [$._contextual_simple_identifier, $._modifierless_class_declaration], - [$._contextual_simple_identifier, $.property_behavior_modifier], - [$._contextual_simple_identifier, $.parameter_modifier], - [$._contextual_simple_identifier, $.type_parameter_pack], - [$._contextual_simple_identifier, $.type_pack_expansion], - [$._contextual_simple_identifier, $.visibility_modifier], - ], - extras: ($) => [ - $.comment, - $.multiline_comment, - /\s+/, // Whitespace - ], - externals: ($) => [ - // Comments and raw strings are parsed in a custom scanner because they require us to carry forward state to - // maintain symmetry. For instance, parsing a multiline comment requires us to increment a counter whenever we see - // `/*`, and decrement it whenever we see `*/`. A standard grammar would only be able to exit the comment at the - // first `*/` (like C does). Similarly, when you start a string with `##"`, you're required to include the same - // number of `#` symbols to end it. - $._multiline_comment, - $.raw_str_part, - $.raw_str_continuing_indicator, - $.raw_str_end_part, - // Because Swift doesn't have explicit semicolons, we also do some whitespace handling in a custom scanner. Line - // breaks are _sometimes_ meaningful as the end of a statement: try to write `let foo: Foo let bar: Bar`, for - // instance and the compiler will complain, but add either a newline or a semicolon and it's fine. We borrow the - // idea from the Kotlin grammar that a newline is sometimes a "semicolon". By including `\n` in both `_semi` and - // an anonymous `whitespace` extras, we _should_ be able to let the parser decide if a newline is meaningful. If the - // parser sees something like `foo.bar(1\n)`, it knows that a "semicolon" would not be valid there, so it parses - // that as whitespace. On the other hand, `let foo: Foo\n let bar: Bar` has a meaningful newline. - // Unfortunately, we can't simply stop at that. There are some expressions and statements that remain valid if you - // end them early, but are expected to be parsed across multiple lines. One particular nefarious example is a - // function declaration, where you might have something like `func foo(args: A) -> Foo throws where A: Hashable`. - // This would still be a valid declaration even if it ended after the `)`, the `Foo`, or the `throws`, so a grammar - // that simply interprets a newline as "sometimes a semi" would parse those incorrectly. - // To solve that case, our custom scanner must do a bit of extra lookahead itself. If we're about to generate a - // `_semi`, we advance a bit further to see if the next non-whitespace token would be one of these other operators. - // If so, we ignore the `_semi` and just produce the operator; if not, we produce the `_semi` and let the rest of - // the grammar sort it out. This isn't perfect, but it works well enough most of the time. - $._implicit_semi, - $._explicit_semi, - // Every one of the below operators will suppress a `_semi` if we encounter it after a newline. - $._arrow_operator_custom, - $._dot_custom, - $._conjunction_operator_custom, - $._disjunction_operator_custom, - $._nil_coalescing_operator_custom, - $._eq_custom, - $._eq_eq_custom, - $._plus_then_ws, - $._minus_then_ws, - $._bang_custom, - $._throws_keyword, - $._rethrows_keyword, - $.default_keyword, - $.where_keyword, - $["else"], - $.catch_keyword, - $._as_custom, - $._as_quest_custom, - $._as_bang_custom, - $._async_keyword_custom, - $._custom_operator, - $._hash_symbol_custom, - $._directive_if, - $._directive_elseif, - $._directive_else, - $._directive_endif, - - // Fake operator that will never get triggered, but follows the sequence of characters for `try!`. Tracked by the - // custom scanner so that it can avoid triggering `$.bang` for that case. - $._fake_try_bang, - ], - inline: ($) => [$._locally_permitted_modifiers], - rules: { - //////////////////////////////// - // File Structure - //////////////////////////////// - source_file: ($) => - seq( - optional(field("shebang", $.shebang_line)), - optional( - seq( - field("statement", $._top_level_statement), - repeat(seq($._semi, field("statement", $._top_level_statement))), - optional($._semi) - ) - ) - ), - _semi: ($) => choice($._implicit_semi, $._explicit_semi), - shebang_line: ($) => seq($._hash_symbol, "!", /[^\r\n]*/), - //////////////////////////////// - // Lexical Structure - https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html - //////////////////////////////// - comment: ($) => token(prec(PRECS.comment, seq("//", /.*/))), - // Named wrapper for the unnamed `_multiline_comment` external token, so - // that multi-line comments still appear in the AST (e.g. as extras between - // top-level statements) without being extracted as class body members when - // used only to separate those members. - multiline_comment: ($) => $._multiline_comment, - // Identifiers - simple_identifier: ($) => - choice( - LEXICAL_IDENTIFIER, - /`[^\r\n` ]*`/, - /\$[0-9]+/, - token(seq("$", LEXICAL_IDENTIFIER)), - $._contextual_simple_identifier - ), - // Keywords that were added after they were already legal as identifiers. `tree-sitter` will prefer exact matches - // when parsing so unless we explicitly say that these are legal, the parser will interpret them as their keyword. - _contextual_simple_identifier: ($) => - choice( - "actor", - "async", - "each", - "lazy", - "repeat", - "package", - $._parameter_ownership_modifier - ), - identifier: ($) => sep1(field("part", $.simple_identifier), $._dot), - // Literals - _basic_literal: ($) => - choice( - $.integer_literal, - $.hex_literal, - $.oct_literal, - $.bin_literal, - $.real_literal, - $.boolean_literal, - $._string_literal, - $.regex_literal, - "nil" - ), - real_literal: ($) => - token( - choice( - seq(DEC_DIGITS, REAL_EXPONENT), - seq(optional(DEC_DIGITS), ".", DEC_DIGITS, optional(REAL_EXPONENT)), - seq( - "0x", - HEX_DIGITS, - optional(seq(".", HEX_DIGITS)), - HEX_REAL_EXPONENT - ) - ) - ), - integer_literal: ($) => token(seq(optional(/[1-9]/), DEC_DIGITS)), - hex_literal: ($) => token(seq("0", /[xX]/, HEX_DIGITS)), - oct_literal: ($) => token(seq("0", /[oO]/, OCT_DIGITS)), - bin_literal: ($) => token(seq("0", /[bB]/, BIN_DIGITS)), - boolean_literal: ($) => choice("true", "false"), - // String literals - _string_literal: ($) => - choice( - $.line_string_literal, - $.multi_line_string_literal, - $.raw_string_literal - ), - line_string_literal: ($) => - seq( - '"', - repeat(choice(field("text", $._line_string_content), $._interpolation)), - '"' - ), - _line_string_content: ($) => choice($.line_str_text, $.str_escaped_char), - line_str_text: ($) => /[^\\"]+/, - str_escaped_char: ($) => - choice($._escaped_identifier, $._uni_character_literal), - _uni_character_literal: ($) => seq("\\", "u", /\{[0-9a-fA-F]+\}/), - multi_line_string_literal: ($) => - seq( - '"""', - repeat( - choice(field("text", $._multi_line_string_content), $._interpolation) - ), - '"""' - ), - raw_string_literal: ($) => - seq( - repeat( - seq( - field("text", $.raw_str_part), - field("interpolation", $.raw_str_interpolation), - field("continuing", optional($.raw_str_continuing_indicator)) - ) - ), - field("text", $.raw_str_end_part) - ), - raw_str_interpolation: ($) => - seq(field("start", $.raw_str_interpolation_start), $._interpolation_contents, ")"), - raw_str_interpolation_start: ($) => /\\#*\(/, - _multi_line_string_content: ($) => - choice($.multi_line_str_text, $.str_escaped_char, '"'), - _interpolation: ($) => seq("\\(", $._interpolation_contents, ")"), - _interpolation_contents: ($) => - sep1Opt( - field( - "interpolation", - alias($.value_argument, $.interpolated_expression) - ), - "," - ), - _escaped_identifier: ($) => /\\[0\\tnr"'\n]/, - multi_line_str_text: ($) => /[^\\"]+/, - // Based on https://gitlab.com/woolsweater/tree-sitter-swifter/-/blob/3d47c85bd47ce54cdf2023a9c0e01eb90adfcc1d/grammar.js#L1019 - // But required modifications to hit all of the cases in SE-354 - regex_literal: ($) => - choice( - $._extended_regex_literal, - $._multiline_regex_literal, - $._oneline_regex_literal - ), - - _extended_regex_literal: ($) => - seq($._hash_symbol, /\/((\/[^#])|[^\n])+\/#/), - - _multiline_regex_literal: ($) => - seq($._hash_symbol, /\/\n/, /(\/[^#]|[^/])*?\n\/#/), - - _oneline_regex_literal: ($) => - token( - prec( - PRECS.regex, - seq( - "/", - token.immediate(/[^ \t\n]?[^/\n]*[^ \t\n/]/), - token.immediate("/") - ) - ) - ), - //////////////////////////////// - // Types - https://docs.swift.org/swift-book/ReferenceManual/Types.html - //////////////////////////////// - type_annotation: ($) => - seq(":", field("type", $._possibly_implicitly_unwrapped_type)), - _possibly_implicitly_unwrapped_type: ($) => - choice($.type, $.implicitly_unwrapped_type), - implicitly_unwrapped_type: ($) => - seq(field("name", $.type), token.immediate("!")), - type: ($) => - prec.right( - PRECS.ty, - seq(field("modifiers", optional($.type_modifiers)), field("name", $.unannotated_type)) - ), - unannotated_type: ($) => - prec.right( - PRECS.ty, - choice( - $.user_type, - $.tuple_type, - $.function_type, - $.array_type, - $.dictionary_type, - $.optional_type, - $.metatype, - $.opaque_type, - $.existential_type, - $.protocol_composition_type, - $.type_parameter_pack, - $.type_pack_expansion, - $.suppressed_constraint - ) - ), - // The grammar just calls this whole thing a `type-identifier` but that's a bit confusing. - user_type: ($) => sep1(field("part", $.simple_user_type), $._dot), - simple_user_type: ($) => - prec.right( - PRECS.ty, - seq( - field("name", alias($.simple_identifier, $.type_identifier)), - field("arguments", optional($.type_arguments)) - ) - ), - tuple_type: ($) => - choice( - seq( - "(", - optional(sep1Opt(field("element", $.tuple_type_item), ",")), - ")" - ), - field("element", alias($.parenthesized_type, $.tuple_type_item)) - ), - tuple_type_item: ($) => - prec( - PRECS.expr, - seq( - optional($._tuple_type_item_identifier), - field("modifiers", optional($.parameter_modifiers)), - field("type", $.type) - ) - ), - _tuple_type_item_identifier: ($) => - prec( - PRECS.expr, - seq( - optional(field("external_name", $.wildcard_pattern)), - field("name", $.simple_identifier), - ":" - ) - ), - function_type: ($) => - seq( - field("params", choice($.tuple_type, $.unannotated_type)), - field("async", optional($._async_keyword)), - field("throws", optional(choice($.throws_clause, $.throws))), - $._arrow_operator, - field("return_type", $.type) - ), - array_type: ($) => seq("[", field("element", $.type), "]"), - dictionary_type: ($) => - seq("[", field("key", $.type), ":", field("value", $.type), "]"), - optional_type: ($) => - prec.left( - seq( - field( - "wrapped", - choice($.user_type, $.tuple_type, $.array_type, $.dictionary_type) - ), - repeat1(alias($._immediate_quest, "?")) - ) - ), - metatype: ($) => seq(field("name", $.unannotated_type), ".", choice("Type", "Protocol")), - _quest: ($) => "?", - _immediate_quest: ($) => token.immediate("?"), - opaque_type: ($) => prec.right(seq("some", field("name", $.unannotated_type))), - existential_type: ($) => prec.right(seq("any", field("name", $.unannotated_type))), - type_parameter_pack: ($) => prec.left(seq("each", field("name", $.unannotated_type))), - type_pack_expansion: ($) => prec.left(seq("repeat", field("name", $.unannotated_type))), - protocol_composition_type: ($) => - prec.left( - seq( - field("type", $.unannotated_type), - repeat1(seq("&", prec.right(field("type", $.unannotated_type)))) - ) - ), - suppressed_constraint: ($) => - prec.right( - seq( - "~", - field("suppressed", alias($.simple_identifier, $.type_identifier)) - ) - ), - //////////////////////////////// - // Expressions - https://docs.swift.org/swift-book/ReferenceManual/Expressions.html - //////////////////////////////// - expression: ($) => - prec( - PRECS.expr, - choice( - $.simple_identifier, - $._unary_expression, - $._binary_expression, - $.ternary_expression, - $._primary_expression, - $.if_statement, - $.switch_statement, - $.assignment, - $.value_parameter_pack, - $.value_pack_expansion, - $.optional_chain_marker - ) - ), - optional_chain_marker: ($) => - seq(field("expr", $.expression), alias($._immediate_quest, "?")), - // Unary expressions - _unary_expression: ($) => - choice( - $.postfix_expression, - $.call_expression, - $.macro_invocation, - $.constructor_expression, - $.navigation_expression, - $.prefix_expression, - $.as_expression, - $.selector_expression, - $.open_start_range_expression, - $.open_end_range_expression, - $.directive, - $.diagnostic - ), - postfix_expression: ($) => - prec.left( - PRECS.postfix_operations, - seq( - field("target", $.expression), - field("operation", $._postfix_unary_operator) - ) - ), - constructor_expression: ($) => - prec( - PRECS.call, - seq( - field( - "constructed_type", - choice($.array_type, $.dictionary_type, $.user_type) - ), - field("suffix", $.constructor_suffix) - ) - ), - parenthesized_type: ($) => - seq( - "(", - field("type", choice($.opaque_type, $.existential_type, $.dictionary_type)), - ")" - ), - navigation_expression: ($) => - prec.left( - PRECS.navigation, - seq( - field( - "target", - choice( - $._navigable_type_expression, - $.expression, - $.parenthesized_type - ) - ), - field("suffix", $.navigation_suffix) - ) - ), - _navigable_type_expression: ($) => - choice($.user_type, $.array_type, $.dictionary_type), - open_start_range_expression: ($) => - prec.right( - PRECS.range, - seq( - $._range_operator, - prec.right(PRECS.range_suffix, field("end", $.expression)) - ) - ), - _range_operator: ($) => - choice($._open_ended_range_operator, $._three_dot_operator), - open_end_range_expression: ($) => - prec.right( - PRECS.range, - seq(field("start", $.expression), $._three_dot_operator) - ), - prefix_expression: ($) => - prec.left( - PRECS.prefix_operations, - seq( - field("operation", $._prefix_unary_operator), - field( - "target", - choice( - $.expression, - alias(choice("async", "if", "switch"), $.expression) - ) - ) - ) - ), - as_expression: ($) => - prec.left( - PRECS.as, - seq(field("expr", $.expression), field("operator", $.as_operator), field("type", $.type)) - ), - selector_expression: ($) => - seq( - $._hash_symbol, - "selector", - "(", - optional(choice("getter:", "setter:")), - field("expr", $.expression), - ")" - ), - // Binary expressions - _binary_expression: ($) => - choice( - $.multiplicative_expression, - $.additive_expression, - $.range_expression, - $.infix_expression, - $.nil_coalescing_expression, - $.check_expression, - $.equality_expression, - $.comparison_expression, - $.conjunction_expression, - $.disjunction_expression, - $.bitwise_operation - ), - multiplicative_expression: ($) => - prec.left( - PRECS.multiplication, - seq( - field("lhs", $.expression), - field("op", $._multiplicative_operator), - field("rhs", $.expression) - ) - ), - additive_expression: ($) => - prec.left( - PRECS.addition, - seq( - field("lhs", $.expression), - field("op", $._additive_operator), - field("rhs", $.expression) - ) - ), - range_expression: ($) => - prec.right( - PRECS.range, - seq( - field("start", $.expression), - field("op", $._range_operator), - field("end", $._expr_hack_at_ternary_binary_suffix) - ) - ), - infix_expression: ($) => - prec.left( - PRECS.infix_operations, - seq( - field("lhs", $.expression), - field("op", $.custom_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - nil_coalescing_expression: ($) => - prec.right( - PRECS.nil_coalescing, - seq( - field("value", $.expression), - $._nil_coalescing_operator, - field("if_nil", $._expr_hack_at_ternary_binary_suffix) - ) - ), - check_expression: ($) => - prec.left( - PRECS.check, - seq( - field("target", $.expression), - field("op", $._is_operator), - field("type", $.type) - ) - ), - comparison_expression: ($) => - prec.left( - seq( - field("lhs", $.expression), - field("op", $._comparison_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - equality_expression: ($) => - prec.left( - PRECS.equality, - seq( - field("lhs", $.expression), - field("op", $._equality_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - conjunction_expression: ($) => - prec.left( - PRECS.conjunction, - seq( - field("lhs", $.expression), - field("op", $._conjunction_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - disjunction_expression: ($) => - prec.left( - PRECS.disjunction, - seq( - field("lhs", $.expression), - field("op", $._disjunction_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - bitwise_operation: ($) => - prec.left( - seq( - field("lhs", $.expression), - field("op", $._bitwise_binary_operator), - field("rhs", $._expr_hack_at_ternary_binary_suffix) - ) - ), - custom_operator: ($) => choice(token(/[\/]+[*]+/), $._custom_operator), - // Suffixes - navigation_suffix: ($) => - seq( - $._dot, - field("suffix", choice($.simple_identifier, $.integer_literal)) - ), - call_suffix: ($) => - prec( - PRECS.call_suffix, - choice( - field("arguments", $.value_arguments), - prec.dynamic(-1, $._fn_call_lambda_arguments), // Prefer to treat `foo() { }` as one call not two - seq(field("arguments", $.value_arguments), $._fn_call_lambda_arguments) - ) - ), - constructor_suffix: ($) => - prec( - PRECS.call_suffix, - choice( - field("arguments", alias($._constructor_value_arguments, $.value_arguments)), - prec.dynamic(-1, $._fn_call_lambda_arguments), // As above - seq( - field("arguments", alias($._constructor_value_arguments, $.value_arguments)), - $._fn_call_lambda_arguments - ) - ) - ), - _constructor_value_arguments: ($) => - seq("(", optional(sep1Opt(field("argument", $.value_argument), ",")), ")"), - _fn_call_lambda_arguments: ($) => - sep1(field("lambda", $.lambda_literal), seq(field("name", $.simple_identifier), ":")), - type_arguments: ($) => prec.left(seq("<", sep1Opt(field("argument", $.type), ","), ">")), - value_arguments: ($) => - seq( - choice( - seq("(", optional(sep1Opt(field("argument", $.value_argument), ",")), ")"), - seq("[", optional(sep1Opt(field("argument", $.value_argument), ",")), "]") - ) - ), - value_argument_label: ($) => - prec.left( - field("name", choice( - $.simple_identifier, - // We don't rely on $._contextual_simple_identifier here because - // these don't usually fall into that category. - alias("if", $.simple_identifier), - alias("switch", $.simple_identifier) - )) - ), - value_argument: ($) => - prec.left( - seq( - field("type_modifiers", optional($.type_modifiers)), - choice( - repeat1( - seq(field("reference_specifier", $.value_argument_label), ":") - ), - seq( - optional(seq(field("name", $.value_argument_label), ":")), - field("value", $.expression) - ) - ) - ) - ), - try_expression: ($) => - prec.right( - PRECS["try"], - seq( - field("operator", $.try_operator), - field( - "expr", - choice( - // Prefer direct calls, e.g. `try foo()`, over indirect like `try a ? b() : c`. This allows us to have - // left associativity for the direct calls, which is technically wrong but is the only way to resolve the - // ambiguity of `if foo { ... }` in the correct direction. - prec.right(-2, $.expression), - prec.left(0, $._binary_expression), - prec.left(0, $.call_expression), - // Similarly special case the ternary expression, where `try` may come earlier than it is actually needed. - // When the parser just encounters some identifier after a `try`, it should prefer the `call_expression` (so - // this should be lower in priority than that), but when we encounter an ambiguous expression that might be - // either `try (foo() ? ...)` or `(try foo()) ? ...`, we should prefer the former. We accomplish that by - // giving it a _static precedence_ of -1 but a _dynamic precedence_ of 1. - prec.dynamic(1, prec.left(-1, $.ternary_expression)) - ) - ) - ) - ), - await_expression: ($) => - prec.right( - PRECS.await, - seq( - $._await_operator, - field( - "expr", - choice( - // Prefer direct calls over indirect (same as with `try`). - prec.right(-2, $.expression), - prec.left(0, $.call_expression), - // Special case ternary to `await` the whole thing (same as with `try`). - prec.dynamic(1, prec.left(-1, $.ternary_expression)) - ) - ) - ) - ), - _await_operator: ($) => alias("await", "await"), - ternary_expression: ($) => - prec.right( - PRECS.ternary, - seq( - field("condition", $.expression), - $._quest, - field("if_true", $.expression), - ":", - field("if_false", $._expr_hack_at_ternary_binary_suffix) - ) - ), - _expr_hack_at_ternary_binary_suffix: ($) => - prec.left( - PRECS.ternary_binary_suffix, - choice( - $.expression, - alias($.expr_hack_at_ternary_binary_call, $.call_expression) - ) - ), - expr_hack_at_ternary_binary_call: ($) => - seq( - field("function", $.expression), - field("suffix", alias($.expr_hack_at_ternary_binary_call_suffix, $.call_suffix)) - ), - expr_hack_at_ternary_binary_call_suffix: ($) => - prec(PRECS.call_suffix, field("arguments", $.value_arguments)), - call_expression: ($) => - prec( - PRECS.call, - prec.dynamic(DYNAMIC_PRECS.call, seq(field("function", $.expression), field("suffix", $.call_suffix))) - ), - macro_invocation: ($) => - prec( - PRECS.call, - prec.dynamic( - DYNAMIC_PRECS.call, - seq( - $._hash_symbol, - field("name", $.simple_identifier), - field("type_parameters", optional($.type_parameters)), - field("suffix", $.call_suffix) - ) - ) - ), - _primary_expression: ($) => - choice( - $.tuple_expression, - $._basic_literal, - $.lambda_literal, - $.special_literal, - $.playground_literal, - $.array_literal, - $.dictionary_literal, - $.self_expression, - $.super_expression, - $.try_expression, - $.await_expression, - $.referenceable_operator, - $.key_path_expression, - $.key_path_string_expression, - prec.right( - PRECS.fully_open_range, - alias($._three_dot_operator, $.fully_open_range) - ) - ), - tuple_expression: ($) => - prec.right( - PRECS.tuple, - seq( - "(", - sep1Opt(field("element", $.tuple_expression_item), ","), - ")" - ) - ), - tuple_expression_item: ($) => - seq( - optional(seq(field("name", $.simple_identifier), ":")), - field("value", $.expression) - ), - array_literal: ($) => - seq("[", optional(sep1Opt(field("element", $.expression), ",")), "]"), - dictionary_literal: ($) => - seq( - "[", - choice(":", sep1Opt(field("element", $.dictionary_literal_item), ",")), - optional(","), - "]" - ), - dictionary_literal_item: ($) => - seq(field("key", $.expression), ":", field("value", $.expression)), - special_literal: ($) => - seq( - $._hash_symbol, - choice( - "file", - "fileID", - "filePath", - "line", - "column", - "function", - "dsohandle" - ) - ), - playground_literal: ($) => - seq( - $._hash_symbol, - field("kind", choice("colorLiteral", "fileLiteral", "imageLiteral")), - "(", - sep1Opt(field("argument", $.playground_literal_argument), ","), - ")" - ), - playground_literal_argument: ($) => - seq(field("name", $.simple_identifier), ":", field("value", $.expression)), - lambda_literal: ($) => - prec.left( - PRECS.lambda, - seq( - choice("{", "^{"), - optional($._lambda_type_declaration), - optional($._statements), - "}" - ) - ), - _lambda_type_declaration: ($) => - seq( - repeat(field("attribute", $.attribute)), - prec(PRECS.expr, optional(field("captures", $.capture_list))), - optional(field("type", $.lambda_function_type)), - "in" - ), - capture_list: ($) => seq("[", sep1Opt(field("item", $.capture_list_item), ","), "]"), - capture_list_item: ($) => - choice( - field("name", $.self_expression), - prec( - PRECS.expr, - seq( - field("ownership", optional($.ownership_modifier)), - field("name", $.simple_identifier), - optional(seq($._equal_sign, field("value", $.expression))) - ) - ) - ), - lambda_function_type: ($) => - prec( - PRECS.expr, - seq( - choice( - field("params", $.lambda_function_type_parameters), - seq("(", field("params", optional($.lambda_function_type_parameters)), ")") - ), - field("async", optional($._async_keyword)), - field("throws", optional(choice($.throws_clause, $.throws))), - optional( - seq( - $._arrow_operator, - field("return_type", $._possibly_implicitly_unwrapped_type) - ) - ) - ) - ), - lambda_function_type_parameters: ($) => sep1Opt(field("parameter", $.lambda_parameter), ","), - lambda_parameter: ($) => - seq( - choice( - field("name", $.self_expression), - prec(PRECS.expr, field("name", $.simple_identifier)), - prec( - PRECS.expr, - seq( - optional(field("external_name", $.simple_identifier)), - field("name", $.simple_identifier), - ":", - field("modifiers", optional($.parameter_modifiers)), - field("type", $._possibly_implicitly_unwrapped_type) - ) - ) - ) - ), - self_expression: ($) => "self", - super_expression: ($) => seq("super"), - _else_options: ($) => choice(field("else_branch", $.block), field("else_branch", $.if_statement)), - if_statement: ($) => - prec.right( - PRECS["if"], - seq( - "if", - sep1(field("condition", $.if_condition), ","), - field("body", $.block), - optional(seq(alias($["else"], "else"), $._else_options)) - ) - ), - if_condition: ($) => - field("kind", choice($.if_let_binding, $.expression, $.availability_condition)), - if_let_binding: ($) => - seq( - $._direct_or_indirect_binding, - optional(seq($._equal_sign, field("value", $.expression))), - field("where", optional($.where_clause)) - ), - guard_statement: ($) => - prec.right( - PRECS["if"], - seq( - "guard", - sep1(field("condition", $.if_condition), ","), - alias($["else"], "else"), - field("body", $.block) - ) - ), - switch_statement: ($) => - prec.right( - PRECS["switch"], - seq( - "switch", - field("expr", $.expression), - "{", - repeat(field("entry", $.switch_entry)), - "}" - ) - ), - switch_entry: ($) => - seq( - field("modifiers", optional($.modifiers)), - choice( - seq( - "case", - field("pattern", $.switch_pattern), - field("where", optional($.where_clause)), - repeat(seq(",", field("pattern", $.switch_pattern))) - ), - field("default", $.default_keyword) - ), - ":", - $._statements, - optional("fallthrough") - ), - switch_pattern: ($) => field("pattern", alias($._binding_pattern_with_expr, $.pattern)), - do_statement: ($) => - prec.right(PRECS["do"], seq("do", field("body", $.block), repeat(field("catch", $.catch_block)))), - catch_block: ($) => - seq( - field("keyword", $.catch_keyword), - field("error", optional(alias($._binding_pattern_no_expr, $.pattern))), - field("where", optional($.where_clause)), - field("body", $.block) - ), - where_clause: ($) => prec.left(seq(field("keyword", $.where_keyword), field("expr", $.expression))), - key_path_expression: ($) => - prec.right( - PRECS.keypath, - seq( - "\\", - field("type", optional( - choice($.simple_user_type, $.array_type, $.dictionary_type) - )), - repeat(seq(".", field("component", $.key_path_component))) - ) - ), - key_path_string_expression: ($) => - prec.left(seq($._hash_symbol, "keyPath", "(", field("expr", $.expression), ")")), - key_path_component: ($) => - prec.left( - choice( - seq(field("name", $.simple_identifier), repeat(field("postfix", $.key_path_postfix))), - repeat1(field("postfix", $.key_path_postfix)) - ) - ), - key_path_postfix: ($) => - choice( - "?", - field("force_unwrap", $.bang), - "self", - seq("[", optional(sep1(field("argument", $.value_argument), ",")), "]") - ), - try_operator: ($) => - prec.right( - seq("try", choice(optional($._try_operator_type), $._fake_try_bang)) - ), - _try_operator_type: ($) => - choice(token.immediate("!"), token.immediate("?")), - _assignment_and_operator: ($) => - choice("+=", "-=", "*=", "/=", "%=", $._equal_sign), - _equality_operator: ($) => choice("!=", "!==", $._eq_eq, "==="), - _comparison_operator: ($) => choice("<", ">", "<=", ">="), - _three_dot_operator: ($) => alias("...", "..."), // Weird alias to satisfy highlight queries - _open_ended_range_operator: ($) => alias("..<", "..<"), - _is_operator: ($) => "is", - _additive_operator: ($) => - choice( - alias($._plus_then_ws, "+"), - alias($._minus_then_ws, "-"), - "+", - "-" - ), - // The `/` operator conflicts with a regex literal (which itself appears to conflict with a - // comment, for some reason), so we must give it equivalent token precedence. - _multiplicative_operator: ($) => - choice("*", alias(token(prec(PRECS.regex, "/")), "/"), "%"), - as_operator: ($) => choice($._as, $._as_quest, $._as_bang), - _prefix_unary_operator: ($) => - prec.right( - choice( - "++", - "--", - "-", - "+", - $.bang, - "&", - "~", - $._dot, - $.custom_operator - ) - ), - _bitwise_binary_operator: ($) => choice("&", "|", "^", "<<", ">>"), - _postfix_unary_operator: ($) => choice("++", "--", $.bang), - directly_assignable_expression: ($) => field("expr", $.expression), - - //////////////////////////////// - // Statements - https://docs.swift.org/swift-book/ReferenceManual/Statements.html - //////////////////////////////// - _statements: ($) => - prec.left( - // Left precedence is required in switch statements - seq( - field("statement", $._local_statement), - repeat(seq($._semi, field("statement", $._local_statement))), - optional($._semi) - ) - ), - _local_statement: ($) => - choice( - $.expression, - $.local_declaration, - $._labeled_statement, - $.control_transfer_statement - ), - _top_level_statement: ($) => - choice( - $.expression, - $.global_declaration, - $._labeled_statement, - $._throw_statement - ), - block: ($) => prec(PRECS.block, seq("{", optional($._statements), "}")), - _labeled_statement: ($) => - seq( - optional($.statement_label), - choice( - $.for_statement, - $.while_statement, - $.repeat_while_statement, - $.do_statement, - $.if_statement, - $.guard_statement, - $.switch_statement - ) - ), - statement_label: ($) => token(/[a-zA-Z_][a-zA-Z_0-9]*:/), - for_statement: ($) => - prec( - PRECS.loop, - seq( - "for", - field("try", optional($.try_operator)), - optional($._await_operator), - field("item", alias($._binding_pattern_no_expr, $.pattern)), - field("type", optional($.type_annotation)), - "in", - field("collection", $._for_statement_collection), - field("where", optional($.where_clause)), - field("body", $.block) - ) - ), - _for_statement_collection: ($) => - // If this expression has "await", this triggers some special-cased logic to prefer function calls. We prefer - // the opposite, though, since function calls may contain trailing code blocks, which are undesirable here. - // - // To fix that, we simply undo the special casing by defining our own `await_expression`. - choice($.expression, alias($.for_statement_await, $.await_expression)), - for_statement_await: ($) => seq($._await_operator, field("expr", $.expression)), - - while_statement: ($) => - prec( - PRECS.loop, - seq( - "while", - sep1(field("condition", $.if_condition), ","), - field("body", $.block) - ) - ), - repeat_while_statement: ($) => - prec( - PRECS.loop, - seq( - "repeat", - field("body", $.block), - // Make sure we make it to the `while` before assuming this is a parameter pack. - repeat($._implicit_semi), - "while", - sep1(field("condition", $.if_condition), ",") - ) - ), - control_transfer_statement: ($) => - choice( - prec.right( - PRECS.control_transfer, - seq(field("kind", $.throw_keyword), field("result", $.expression)) - ), - prec.right( - PRECS.control_transfer, - seq( - field("kind", $._optionally_valueful_control_keyword), - field("result", optional($.expression)) - ) - ) - ), - _throw_statement: ($) => seq($.throw_keyword, $.expression), - throw_keyword: ($) => "throw", - _optionally_valueful_control_keyword: ($) => - choice("return", "continue", "break", "yield"), - assignment: ($) => - prec.left( - PRECS.assignment, - seq( - field("target", $.directly_assignable_expression), - field("operator", $._assignment_and_operator), - field("result", $.expression) - ) - ), - value_parameter_pack: ($) => - prec.left(PRECS.parameter_pack, seq("each", field("expr", $.expression))), - value_pack_expansion: ($) => - prec.left(PRECS.parameter_pack, seq("repeat", field("expr", $.expression))), - availability_condition: ($) => - seq( - $._hash_symbol, - choice("available", "unavailable"), - "(", - sep1Opt($._availability_argument, ","), - ")" - ), - _availability_argument: ($) => - choice(seq(field("platform", $.identifier), sep1(field("version", $.integer_literal), ".")), "*"), - //////////////////////////////// - // Declarations - https://docs.swift.org/swift-book/ReferenceManual/Declarations.html - //////////////////////////////// - global_declaration: ($) => - choice( - $.import_declaration, - $.property_declaration, - $.typealias_declaration, - $.function_declaration, - $.init_declaration, - $.class_declaration, - $.protocol_declaration, - $.operator_declaration, - $.precedence_group_declaration, - $.associatedtype_declaration, - $.macro_declaration - ), - type_level_declaration: ($) => - choice( - $.import_declaration, - $.property_declaration, - $.typealias_declaration, - $.function_declaration, - $.init_declaration, - $.class_declaration, - $.protocol_declaration, - $.deinit_declaration, - $.subscript_declaration, - $.operator_declaration, - $.precedence_group_declaration, - $.associatedtype_declaration - ), - local_declaration: ($) => - choice( - alias($._local_property_declaration, $.property_declaration), - alias($._local_typealias_declaration, $.typealias_declaration), - alias($._local_function_declaration, $.function_declaration), - alias($._local_class_declaration, $.class_declaration) - ), - _local_property_declaration: ($) => - seq( - field("modifiers", optional($._locally_permitted_modifiers)), - $._modifierless_property_declaration - ), - _local_typealias_declaration: ($) => - seq( - field("modifiers", optional($._locally_permitted_modifiers)), - $._modifierless_typealias_declaration - ), - _local_function_declaration: ($) => - seq( - field("modifiers", optional($._locally_permitted_modifiers)), - $._modifierless_function_declaration - ), - _local_class_declaration: ($) => - seq( - field("modifiers", optional($._locally_permitted_modifiers)), - $._modifierless_class_declaration - ), - import_declaration: ($) => - seq( - field("modifiers", optional($.modifiers)), - "import", - optional(field("scoped_import_kind", $._import_kind)), - field("name", $.identifier) - ), - _import_kind: ($) => - choice( - "typealias", - "struct", - "class", - "enum", - "protocol", - "let", - "var", - "func" - ), - protocol_property_declaration: ($) => - prec.right( - seq( - field("modifiers", optional($.modifiers)), - field("name", alias($._binding_kind_and_pattern, $.pattern)), - field("type", optional($.type_annotation)), - field("type_constraints", optional($.type_constraints)), - field("requirements", $.protocol_property_requirements) - ) - ), - protocol_property_requirements: ($) => - seq("{", repeat(field("accessor", choice($.getter_specifier, $.setter_specifier))), "}"), - property_declaration: ($) => - seq(field("modifiers", optional($.modifiers)), $._modifierless_property_declaration), - _modifierless_property_declaration: ($) => - prec.right( - seq( - $._possibly_async_binding_pattern_kind, - sep1(field("declarator", $.property_binding), ",") - ) - ), - property_binding: ($) => - prec.left( - seq( - field("name", alias($._no_expr_pattern_already_bound, $.pattern)), - field("type", optional($.type_annotation)), - field("type_constraints", optional($.type_constraints)), - optional( - choice( - $._expression_with_willset_didset, - $._expression_without_willset_didset, - field("observers", $.willset_didset_block), - field("computed_value", $.computed_property) - ) - ) - ) - ), - _expression_with_willset_didset: ($) => - prec.dynamic( - 1, - seq( - $._equal_sign, - field("value", $.expression), - field("observers", $.willset_didset_block) - ) - ), - _expression_without_willset_didset: ($) => - seq($._equal_sign, field("value", $.expression)), - willset_didset_block: ($) => - choice( - seq("{", field("willset", $.willset_clause), field("didset", optional($.didset_clause)), "}"), - seq("{", field("didset", $.didset_clause), field("willset", optional($.willset_clause)), "}") - ), - willset_clause: ($) => - seq( - field("modifiers", optional($.modifiers)), - "willSet", - optional(seq("(", field("parameter", $.simple_identifier), ")")), - field("body", $.block) - ), - didset_clause: ($) => - seq( - field("modifiers", optional($.modifiers)), - "didSet", - optional(seq("(", field("parameter", $.simple_identifier), ")")), - field("body", $.block) - ), - typealias_declaration: ($) => - seq(field("modifiers", optional($.modifiers)), $._modifierless_typealias_declaration), - _modifierless_typealias_declaration: ($) => - seq( - "typealias", - field("name", alias($.simple_identifier, $.type_identifier)), - field("type_parameters", optional($.type_parameters)), - $._equal_sign, - field("value", $.type) - ), - function_declaration: ($) => - prec.right( - seq($._bodyless_function_declaration, field("body", $.block)) - ), - _modifierless_function_declaration: ($) => - prec.right( - seq( - $._modifierless_function_declaration_no_body, - field("body", $.block) - ) - ), - _bodyless_function_declaration: ($) => - seq( - field("modifiers", optional($.modifiers)), - optional("class"), // XXX: This should be possible in non-last position, but that creates parsing ambiguity - $._modifierless_function_declaration_no_body - ), - _modifierless_function_declaration_no_body: ($) => - prec.right( - seq( - $._non_constructor_function_decl, - field("type_parameters", optional($.type_parameters)), - $._function_value_parameters, - field("async", optional($._async_keyword)), - field("throws", optional(choice($.throws_clause, $.throws))), - optional( - seq( - $._arrow_operator, - field("return_type", $._possibly_implicitly_unwrapped_type) - ) - ), - field("type_constraints", optional($.type_constraints)) - ) - ), - macro_declaration: ($) => - seq( - $._macro_head, - field("name", $.simple_identifier), - field("type_parameters", optional($.type_parameters)), - $._macro_signature, - optional(field("definition", $.macro_definition)), - field("type_constraints", optional($.type_constraints)) - ), - _macro_head: ($) => seq(field("modifiers", optional($.modifiers)), "macro"), - _macro_signature: ($) => - seq( - $._function_value_parameters, - optional(seq($._arrow_operator, field("return_type", $.unannotated_type))) - ), - macro_definition: ($) => - seq( - $._equal_sign, - field("body", choice($.expression, $.external_macro_definition)) - ), - - external_macro_definition: ($) => - seq($._hash_symbol, "externalMacro", field("arguments", $.value_arguments)), - - class_declaration: ($) => - seq(field("modifiers", optional($.modifiers)), $._modifierless_class_declaration), - _modifierless_class_declaration: ($) => - prec.right( - choice( - seq( - field("declaration_kind", choice("class", "struct", "actor")), - field("name", alias($.simple_identifier, $.type_identifier)), - field("type_parameters", optional($.type_parameters)), - optional(seq(":", $._inheritance_specifiers)), - field("type_constraints", optional($.type_constraints)), - field("body", $.class_body) - ), - seq( - field("declaration_kind", "extension"), - field("name", $.unannotated_type), - field("type_parameters", optional($.type_parameters)), - optional(seq(":", $._inheritance_specifiers)), - field("type_constraints", optional($.type_constraints)), - field("body", $.class_body) - ), - seq( - optional("indirect"), - field("declaration_kind", "enum"), - field("name", alias($.simple_identifier, $.type_identifier)), - field("type_parameters", optional($.type_parameters)), - optional(seq(":", $._inheritance_specifiers)), - field("type_constraints", optional($.type_constraints)), - field("body", $.enum_class_body) - ) - ) - ), - class_body: ($) => seq("{", optional($._class_member_declarations), "}"), - _inheritance_specifiers: ($) => - prec.left(sep1($._annotated_inheritance_specifier, choice(",", "&"))), - _annotated_inheritance_specifier: ($) => - seq(repeat(field("attribute", $.attribute)), field("inherits", $.inheritance_specifier)), - inheritance_specifier: ($) => - prec.left( - field( - "inherits_from", - choice($.user_type, $.function_type, $.suppressed_constraint) - ) - ), - type_parameters: ($) => - seq( - "<", - sep1Opt(field("parameter", $.type_parameter), ","), - field("constraints", optional($.type_constraints)), - ">" - ), - type_parameter: ($) => - seq( - field("modifiers", optional($.type_parameter_modifiers)), - field("name", $._type_parameter_possibly_packed), - optional(seq(":", field("type", $.type))) - ), - _type_parameter_possibly_packed: ($) => - choice( - alias($.simple_identifier, $.type_identifier), - $.type_parameter_pack - ), - - type_constraints: ($) => - prec.right(seq(field("keyword", $.where_keyword), sep1Opt(field("constraint", $.type_constraint), ","))), - type_constraint: ($) => - field("constraint", choice($.inheritance_constraint, $.equality_constraint)), - inheritance_constraint: ($) => - seq( - repeat(field("attribute", $.attribute)), - field("constrained_type", $._constrained_type), - ":", - field("inherits_from", $._possibly_implicitly_unwrapped_type) - ), - equality_constraint: ($) => - seq( - repeat(field("attribute", $.attribute)), - field("constrained_type", $._constrained_type), - choice($._equal_sign, $._eq_eq), - field("must_equal", $.type) - ), - _constrained_type: ($) => choice($.identifier, $.nested_type_identifier), - nested_type_identifier: ($) => - seq( - field("base", $.unannotated_type), - optional(seq(".", sep1(field("member", $.simple_identifier), "."))) - ), - _class_member_separator: ($) => choice($._semi, $._multiline_comment), - _class_member_declarations: ($) => - seq( - sep1(field("member", $.type_level_declaration), $._class_member_separator), - optional($._class_member_separator) - ), - _function_value_parameters: ($) => - repeat1( - seq("(", optional(sep1Opt(field("parameter", $.function_parameter), ",")), ")") - ), - function_parameter: ($) => - seq( - field("attribute", optional($.attribute)), - field("parameter", $.parameter), - optional(seq($._equal_sign, field("default_value", $.expression))) - ), - parameter: ($) => - seq( - optional(field("external_name", $.simple_identifier)), - field("name", $.simple_identifier), - ":", - field("modifiers", optional($.parameter_modifiers)), - field("type", $._possibly_implicitly_unwrapped_type), - optional($._three_dot_operator) - ), - _non_constructor_function_decl: ($) => - seq( - "func", - field("name", choice($.simple_identifier, $.referenceable_operator)) - ), - referenceable_operator: ($) => - field("operator", choice( - $.custom_operator, - $._comparison_operator, - $._additive_operator, - $._multiplicative_operator, - $._equality_operator, - $._assignment_and_operator, - "++", - "--", - $.bang, - "~", - "|", - "^", - "<<", - ">>", - "&" - )), - // Hide the fact that certain symbols come from the custom scanner by aliasing them to their - // string variants. This keeps us from having to see them in the syntax tree (which would be - // noisy) but allows callers to refer to them as nodes by their text form like with any - // operator. - _equal_sign: ($) => alias($._eq_custom, "="), - _eq_eq: ($) => alias($._eq_eq_custom, "=="), - _dot: ($) => alias($._dot_custom, "."), - _arrow_operator: ($) => alias($._arrow_operator_custom, "->"), - _conjunction_operator: ($) => alias($._conjunction_operator_custom, "&&"), - _disjunction_operator: ($) => alias($._disjunction_operator_custom, "||"), - _nil_coalescing_operator: ($) => - alias($._nil_coalescing_operator_custom, "??"), - _as: ($) => alias($._as_custom, "as"), - _as_quest: ($) => alias($._as_quest_custom, "as?"), - _as_bang: ($) => alias($._as_bang_custom, "as!"), - _hash_symbol: ($) => alias($._hash_symbol_custom, "#"), - bang: ($) => choice($._bang_custom, "!"), - _async_keyword: ($) => alias($._async_keyword_custom, "async"), - _async_modifier: ($) => token("async"), - throws: ($) => choice($._throws_keyword, $._rethrows_keyword), - throws_clause: ($) => - seq($._throws_keyword, "(", field("type", $.unannotated_type), ")"), - enum_class_body: ($) => - seq("{", repeat(field("member", choice($.enum_entry, $.type_level_declaration))), "}"), - enum_entry: ($) => - seq( - field("modifiers", optional($.modifiers)), - optional("indirect"), - "case", - sep1(field("case", $.enum_case_entry), ","), - optional(";") - ), - enum_case_entry: ($) => - seq( - field("name", $.simple_identifier), - optional($._enum_entry_suffix) - ), - _enum_entry_suffix: ($) => - choice( - field("data_contents", $.enum_type_parameters), - seq($._equal_sign, field("raw_value", $.expression)) - ), - enum_type_parameters: ($) => - seq( - "(", - optional(sep1(field("parameter", $.enum_type_parameter), ",")), - ")" - ), - enum_type_parameter: ($) => - seq( - optional( - seq(optional(field("external_name", $.wildcard_pattern)), field("name", $.simple_identifier), ":") - ), - field("type", $.type), - optional(seq($._equal_sign, field("default_value", $.expression))) - ), - protocol_declaration: ($) => - prec.right( - seq( - field("modifiers", optional($.modifiers)), - "protocol", - field("name", alias($.simple_identifier, $.type_identifier)), - field("type_parameters", optional($.type_parameters)), - optional(seq(":", $._inheritance_specifiers)), - field("type_constraints", optional($.type_constraints)), - field("body", $.protocol_body) - ) - ), - protocol_body: ($) => - seq("{", optional($._protocol_member_declarations), "}"), - _protocol_member_declarations: ($) => - seq(sep1(field("member", $.protocol_member_declaration), $._semi), optional($._semi)), - protocol_member_declaration: ($) => - choice( - $.protocol_function_declaration, - $.init_declaration, - $.deinit_declaration, - $.protocol_property_declaration, - $.typealias_declaration, - $.associatedtype_declaration, - $.subscript_declaration - ), - protocol_function_declaration: ($) => - seq( - $._bodyless_function_declaration, - optional(field("body", $.block)) - ), - init_declaration: ($) => - prec.right( - seq( - field("modifiers", optional($.modifiers)), - optional("class"), - "init", - optional(choice($._quest, field("bang", $.bang))), - field("type_parameters", optional($.type_parameters)), - $._function_value_parameters, - field("async", optional($._async_keyword)), - field("throws", optional(choice($.throws_clause, $.throws))), - field("type_constraints", optional($.type_constraints)), - optional(field("body", $.block)) - ) - ), - deinit_declaration: ($) => - prec.right( - seq(field("modifiers", optional($.modifiers)), "deinit", field("body", $.block)) - ), - subscript_declaration: ($) => - prec.right( - seq( - field("modifiers", optional($.modifiers)), - "subscript", - field("type_parameters", optional($.type_parameters)), - $._function_value_parameters, - optional( - seq( - $._arrow_operator, - field("return_type", $._possibly_implicitly_unwrapped_type) - ) - ), - field("type_constraints", optional($.type_constraints)), - field("body", $.computed_property) - ) - ), - computed_property: ($) => - seq( - "{", - choice( - optional($._statements), - repeat( - field("accessor", choice($.computed_getter, $.computed_setter, $.computed_modify)) - ) - ), - "}" - ), - computed_getter: ($) => - seq(repeat(field("attribute", $.attribute)), field("specifier", $.getter_specifier), optional(field("body", $.block))), - computed_modify: ($) => - seq(repeat(field("attribute", $.attribute)), field("specifier", $.modify_specifier), optional(field("body", $.block))), - computed_setter: ($) => - seq( - repeat(field("attribute", $.attribute)), - field("specifier", $.setter_specifier), - optional(seq("(", field("parameter", $.simple_identifier), ")")), - optional(field("body", $.block)) - ), - getter_specifier: ($) => - seq(field("mutation", optional($.mutation_modifier)), "get", optional($._getter_effects)), - setter_specifier: ($) => seq(field("mutation", optional($.mutation_modifier)), "set"), - modify_specifier: ($) => seq(field("mutation", optional($.mutation_modifier)), "_modify"), - _getter_effects: ($) => - repeat1(field("effect", choice(alias($._async_keyword, $.async_keyword), $.throws_clause, $.throws))), - operator_declaration: ($) => - seq( - field("kind", choice("prefix", "infix", "postfix")), - "operator", - field("name", $.referenceable_operator), - optional(seq(":", field("precedence_group", $.simple_identifier))), - field("body", optional($.deprecated_operator_declaration_body)) - ), - // The Swift compiler no longer accepts these, but some very old code still uses it. - deprecated_operator_declaration_body: ($) => - seq("{", repeat(field("entry", choice($.simple_identifier, $._basic_literal))), "}"), - precedence_group_declaration: ($) => - seq( - "precedencegroup", - field("name", $.simple_identifier), - "{", - field("attributes", optional($.precedence_group_attributes)), - "}" - ), - precedence_group_attributes: ($) => repeat1(field("attribute", $.precedence_group_attribute)), - precedence_group_attribute: ($) => - seq( - field("name", $.simple_identifier), - ":", - field("value", choice($.simple_identifier, $.boolean_literal)) - ), - associatedtype_declaration: ($) => - seq( - field("modifiers", optional($.modifiers)), - "associatedtype", - field("name", alias($.simple_identifier, $.type_identifier)), - optional(seq(":", field("must_inherit", $.type))), - field("type_constraints", optional($.type_constraints)), - optional(seq($._equal_sign, field("default_value", $.type))) - ), - //////////////////////////////// - // Attributes - https://docs.swift.org/swift-book/ReferenceManual/Attributes.html - //////////////////////////////// - attribute: ($) => - seq( - "@", - field("name", $.user_type), - // attribute arguments are a mess of special cases, maybe this is good enough? - optional(seq("(", sep1Opt($._attribute_argument, ","), ")")) - ), - _attribute_argument: ($) => - choice( - // labeled function parameters, used in custom property wrappers - seq(field("argument_name", $.simple_identifier), ":", field("argument", $.expression)), - // Unlabeled function parameters, simple identifiers, or `*` - field("argument", $.expression), - // References to param names (used in `@objc(foo:bar:)`) - repeat1(seq(field("param_ref", $.simple_identifier), ":")), - // Version restrictions (iOS 3.4.5, Swift 5.0.0) - seq(repeat1(field("platform", $.simple_identifier)), sep1(field("version", $.integer_literal), ".")) - ), - //////////////////////////////// - // Patterns - https://docs.swift.org/swift-book/ReferenceManual/Patterns.html - //////////////////////////////// - _universally_allowed_pattern: ($) => - choice( - $.wildcard_pattern, - $.tuple_pattern, - $.type_casting_pattern, - $.case_pattern - ), - _bound_identifier: ($) => field("bound_identifier", $.simple_identifier), - - _binding_pattern_no_expr: ($) => - seq( - field("kind", choice( - $._universally_allowed_pattern, - $.binding_pattern, - $._bound_identifier - )), - optional($._quest) - ), - _no_expr_pattern_already_bound: ($) => - seq( - field("kind", choice($._universally_allowed_pattern, $._bound_identifier)), - optional($._quest) - ), - _binding_pattern_with_expr: ($) => - seq( - field("kind", choice( - $._universally_allowed_pattern, - $.binding_pattern, - $.expression - )), - optional($._quest) - ), - _non_binding_pattern_with_expr: ($) => - seq( - field("kind", choice($._universally_allowed_pattern, $.expression)), - optional($._quest) - ), - _direct_or_indirect_binding: ($) => - seq( - choice( - field("pattern", alias($._binding_kind_and_pattern, $.pattern)), - seq("case", field("pattern", alias($._binding_pattern_no_expr, $.pattern))) - ), - field("type", optional($.type_annotation)) - ), - value_binding_pattern: ($) => field("mutability", choice("var", "let")), - _possibly_async_binding_pattern_kind: ($) => - seq(optional($._async_modifier), field("binding", $.value_binding_pattern)), - _binding_kind_and_pattern: ($) => - seq( - $._possibly_async_binding_pattern_kind, - $._no_expr_pattern_already_bound - ), - wildcard_pattern: ($) => "_", - tuple_pattern_item: ($) => - choice( - seq( - field("name", $.simple_identifier), - ":", - field("pattern", alias($._binding_pattern_with_expr, $.pattern)) - ), - field("pattern", alias($._binding_pattern_with_expr, $.pattern)) - ), - tuple_pattern: ($) => seq("(", sep1Opt(field("item", $.tuple_pattern_item), ","), ")"), - case_pattern: ($) => - seq( - optional("case"), - optional(field("type", $.user_type)), // XXX this should just be _type but that creates ambiguity - field("dot", $._dot), - field("name", $.simple_identifier), - optional(field("arguments", $.tuple_pattern)) - ), - type_casting_pattern: ($) => - choice( - seq("is", field("type", $.type)), - seq(field("pattern", alias($._binding_pattern_no_expr, $.pattern)), $._as, field("type", $.type)) - ), - binding_pattern: ($) => - seq( - seq(optional("case"), field("binding", $.value_binding_pattern)), - field("pattern", alias($._no_expr_pattern_already_bound, $.pattern)) - ), - - // ========== - // Modifiers - // ========== - modifiers: ($) => - repeat1( - prec.left( - field("modifier", choice($._non_local_scope_modifier, $._locally_permitted_modifiers)) - ) - ), - _locally_permitted_modifiers: ($) => - repeat1(choice($.attribute, $._locally_permitted_modifier)), - parameter_modifiers: ($) => repeat1(field("modifier", $.parameter_modifier)), - _modifier: ($) => - choice($._non_local_scope_modifier, $._locally_permitted_modifier), - _non_local_scope_modifier: ($) => - choice( - $.member_modifier, - $.visibility_modifier, - $.function_modifier, - $.mutation_modifier, - $.property_modifier, - $.parameter_modifier - ), - _locally_permitted_modifier: ($) => - choice( - $.ownership_modifier, - $.inheritance_modifier, - $.property_behavior_modifier - ), - property_behavior_modifier: ($) => "lazy", - type_modifiers: ($) => repeat1(field("attribute", $.attribute)), - member_modifier: ($) => - choice("override", "convenience", "required", "nonisolated"), - visibility_modifier: ($) => - seq( - choice( - "public", - "private", - "internal", - "fileprivate", - "open", - "package" - ), - optional(seq("(", "set", ")")) - ), - type_parameter_modifiers: ($) => repeat1(field("attribute", $.attribute)), - function_modifier: ($) => choice("infix", "postfix", "prefix"), - mutation_modifier: ($) => choice("mutating", "nonmutating"), - property_modifier: ($) => - choice("static", "dynamic", "optional", "class", "distributed"), - inheritance_modifier: ($) => choice("final"), - parameter_modifier: ($) => - choice( - "inout", - "@escaping", - "@autoclosure", - $._parameter_ownership_modifier - ), - ownership_modifier: ($) => - choice("weak", "unowned", "unowned(safe)", "unowned(unsafe)"), - _parameter_ownership_modifier: ($) => choice("borrowing", "consuming"), - use_site_target: ($) => - seq( - choice( - "property", - "get", - "set", - "receiver", - "param", - "setparam", - "delegate" - ), - ":" - ), - directive: ($) => - prec.right( - PRECS.comment, - choice( - seq(alias($._directive_if, "#if"), field("condition", $.compilation_condition)), - seq(alias($._directive_elseif, "#elseif"), field("condition", $.compilation_condition)), - seq(alias($._directive_else, "#else")), - seq(alias($._directive_endif, "#endif")) - ) - ), - compilation_condition: ($) => - prec.right( - choice( - seq("os", "(", field("name", $.simple_identifier), ")"), - seq("arch", "(", field("name", $.simple_identifier), ")"), - seq( - "swift", - "(", - $._comparison_operator, - sep1(field("version", $.integer_literal), "."), - ")" - ), - seq( - "compiler", - "(", - $._comparison_operator, - sep1(field("version", $.integer_literal), "."), - ")" - ), - seq("canImport", "(", sep1(field("name", $.simple_identifier), "."), ")"), - seq("targetEnvironment", "(", field("name", $.simple_identifier), ")"), - field("value", $.boolean_literal), - field("name", $.simple_identifier), - seq("(", field("inner", $.compilation_condition), ")"), - seq("!", field("operand", $.compilation_condition)), - seq( - field("lhs", $.compilation_condition), - $._conjunction_operator, - field("rhs", $.compilation_condition) - ), - seq( - field("lhs", $.compilation_condition), - $._disjunction_operator, - field("rhs", $.compilation_condition) - ) - ) - ), - diagnostic: ($) => - prec( - PRECS.comment, - seq( - $._hash_symbol, - choice( - // Using regexes here, rather than actually validating the string literal, because complex string literals - // cannot be used inside `token()` and we need that to ensure we get the right precedence. - seq(/error([^\r\n]*)/), - seq(/warning([^\r\n]*)/), - seq(/sourceLocation([^\r\n]*)/) - ) - ) - ), - // Dumping ground for any nodes that used to exist in the grammar, but have since been removed for whatever - // reason. - // Neovim applies updates non-atomically to the parser and the queries. Meanwhile, `tree-sitter` rejects any query - // that contains any unrecognized nodes. Putting those two facts together, we see that we must never remove nodes - // that once existed. - unused_for_backward_compatibility: ($) => - choice(alias("unused1", "try?"), alias("unused2", "try!")), - }, -}); -function sep1(rule, separator) { - return seq(rule, repeat(seq(separator, rule))); -} -function sep1Opt(rule, separator) { - return seq(rule, repeat(seq(separator, rule)), optional(separator)); -} - -function tree_sitter_version_supports_emoji() { - try { - return ( - TREE_SITTER_CLI_VERSION_MAJOR > 0 || - TREE_SITTER_CLI_VERSION_MINOR > 20 || - TREE_SITTER_CLI_VERSION_PATCH >= 5 - ); - } catch (err) { - if (err instanceof ReferenceError) { - return false; - } else { - throw err; - } - } -} diff --git a/unified/extractor/tree-sitter-swift/node-types.yml b/unified/extractor/tree-sitter-swift/node-types.yml deleted file mode 100644 index 35dfb985b4a..00000000000 --- a/unified/extractor/tree-sitter-swift/node-types.yml +++ /dev/null @@ -1,875 +0,0 @@ -supertypes: - expression: - - additive_expression - - array_literal - - as_expression - - assignment - - await_expression - - bin_literal - - bitwise_operation - - boolean_literal - - call_expression - - check_expression - - comparison_expression - - conjunction_expression - - constructor_expression - - diagnostic - - dictionary_literal - - directive - - disjunction_expression - - equality_expression - - fully_open_range - - hex_literal - - if_statement - - infix_expression - - integer_literal - - key_path_expression - - key_path_string_expression - - lambda_literal - - line_string_literal - - macro_invocation - - multi_line_string_literal - - multiplicative_expression - - navigation_expression - - "nil" - - nil_coalescing_expression - - oct_literal - - open_end_range_expression - - open_start_range_expression - - optional_chain_marker - - playground_literal - - postfix_expression - - prefix_expression - - range_expression - - raw_string_literal - - real_literal - - referenceable_operator - - regex_literal - - selector_expression - - self_expression - - simple_identifier - - special_literal - - super_expression - - switch_statement - - ternary_expression - - try_expression - - tuple_expression - - value_pack_expansion - - value_parameter_pack - global_declaration: - - associatedtype_declaration - - class_declaration - - function_declaration - - import_declaration - - init_declaration - - macro_declaration - - operator_declaration - - precedence_group_declaration - - property_declaration - - protocol_declaration - - typealias_declaration - local_declaration: - - class_declaration - - function_declaration - - property_declaration - - typealias_declaration - protocol_member_declaration: - - associatedtype_declaration - - deinit_declaration - - init_declaration - - protocol_function_declaration - - protocol_property_declaration - - subscript_declaration - - typealias_declaration - type_level_declaration: - - associatedtype_declaration - - class_declaration - - deinit_declaration - - function_declaration - - import_declaration - - init_declaration - - operator_declaration - - precedence_group_declaration - - property_declaration - - protocol_declaration - - subscript_declaration - - typealias_declaration - unannotated_type: - - array_type - - dictionary_type - - existential_type - - function_type - - metatype - - opaque_type - - optional_type - - protocol_composition_type - - suppressed_constraint - - tuple_type - - type_pack_expansion - - type_parameter_pack - - user_type - -named: - additive_expression: - lhs: expression - op: ["+", "-"] - rhs: expression - array_literal: - element*: expression - array_type: - element: type - as_expression: - expr: expression - operator: as_operator - type: type - as_operator: - assignment: - operator: ["%=", "*=", "+=", "-=", "/=", "="] - result: expression - target: directly_assignable_expression - associatedtype_declaration: - default_value?: type - modifiers?: modifiers - must_inherit?: type - name: type_identifier - type_constraints?: type_constraints - async_keyword: - attribute: - argument*: expression - argument_name*: simple_identifier - name: user_type - param_ref*: simple_identifier - platform*: simple_identifier - version*: integer_literal - availability_condition: - platform*: identifier - version*: integer_literal - await_expression: - expr: expression - bang: - bin_literal: - binding_pattern: - binding: value_binding_pattern - pattern: pattern - bitwise_operation: - lhs: expression - op: ["&", "<<", ">>", "^", "|"] - rhs: expression - block: - statement*: [control_transfer_statement, do_statement, expression, for_statement, guard_statement, local_declaration, repeat_while_statement, statement_label, while_statement] - boolean_literal: - call_expression: - function: expression - suffix: call_suffix - call_suffix: - arguments?: value_arguments - lambda*: lambda_literal - name*: simple_identifier - capture_list: - item+: capture_list_item - capture_list_item: - name: [self_expression, simple_identifier] - ownership?: ownership_modifier - value?: expression - case_pattern: - arguments?: tuple_pattern - dot: "." - name: simple_identifier - type?: user_type - catch_block: - body: block - error?: pattern - keyword: catch_keyword - where?: where_clause - catch_keyword: - check_expression: - op: "is" - target: expression - type: type - class_body: - member*: type_level_declaration - class_declaration: - attribute*: attribute - body: [class_body, enum_class_body] - declaration_kind: ["actor", "class", "enum", "extension", "struct"] - inherits*: inheritance_specifier - modifiers*: [attribute, inheritance_modifier, modifiers, ownership_modifier, property_behavior_modifier] - name: [type_identifier, unannotated_type] - type_constraints?: type_constraints - type_parameters?: type_parameters - comment: - comparison_expression: - lhs: expression - op: ["<", "<=", ">", ">="] - rhs: expression - compilation_condition: - inner?: compilation_condition - lhs?: compilation_condition - name*: simple_identifier - operand?: compilation_condition - rhs?: compilation_condition - value?: boolean_literal - version*: integer_literal - computed_getter: - attribute*: attribute - body?: block - specifier: getter_specifier - computed_modify: - attribute*: attribute - body?: block - specifier: modify_specifier - computed_property: - accessor*: [computed_getter, computed_modify, computed_setter] - statement*: [control_transfer_statement, do_statement, expression, for_statement, guard_statement, local_declaration, repeat_while_statement, statement_label, while_statement] - computed_setter: - attribute*: attribute - body?: block - parameter?: simple_identifier - specifier: setter_specifier - conjunction_expression: - lhs: expression - op: "&&" - rhs: expression - constructor_expression: - constructed_type: [array_type, dictionary_type, user_type] - suffix: constructor_suffix - constructor_suffix: - arguments?: value_arguments - lambda*: lambda_literal - name*: simple_identifier - control_transfer_statement: - kind: ["break", "continue", "return", throw_keyword, "yield"] - result?: expression - custom_operator: - default_keyword: - deinit_declaration: - body: block - modifiers?: modifiers - deprecated_operator_declaration_body: - entry*: [bin_literal, boolean_literal, hex_literal, integer_literal, line_string_literal, multi_line_string_literal, "nil", oct_literal, raw_string_literal, real_literal, regex_literal, simple_identifier] - diagnostic: - dictionary_literal: - element*: dictionary_literal_item - dictionary_literal_item: - key: expression - value: expression - dictionary_type: - key: type - value: type - didset_clause: - body: block - modifiers?: modifiers - parameter?: simple_identifier - directive: - condition?: compilation_condition - directly_assignable_expression: - expr: expression - disjunction_expression: - lhs: expression - op: "||" - rhs: expression - do_statement: - body: block - catch*: catch_block - enum_case_entry: - data_contents?: enum_type_parameters - name: simple_identifier - raw_value?: expression - enum_class_body: - member*: [enum_entry, type_level_declaration] - enum_entry: - case+: enum_case_entry - modifiers?: modifiers - enum_type_parameter: - default_value?: expression - external_name?: wildcard_pattern - name?: simple_identifier - type: type - enum_type_parameters: - parameter*: enum_type_parameter - equality_constraint: - attribute*: attribute - constrained_type: [identifier, nested_type_identifier] - must_equal: type - equality_expression: - lhs: expression - op: ["!=", "!==", "==", "==="] - rhs: expression - existential_type: - name: unannotated_type - external_macro_definition: - arguments: value_arguments - for_statement: - body: block - collection: expression - item: pattern - try?: try_operator - type?: type_annotation - where?: where_clause - fully_open_range: - function_declaration: - async?: "async" - body: block - modifiers*: [attribute, inheritance_modifier, modifiers, ownership_modifier, property_behavior_modifier] - name: [referenceable_operator, simple_identifier] - parameter*: function_parameter - return_type?: [implicitly_unwrapped_type, type] - throws?: [throws, throws_clause] - type_constraints?: type_constraints - type_parameters?: type_parameters - function_modifier: - function_parameter: - attribute?: attribute - default_value?: expression - parameter: parameter - function_type: - async?: "async" - params: unannotated_type - return_type: type - throws?: [throws, throws_clause] - getter_specifier: - effect*: [async_keyword, throws, throws_clause] - mutation?: mutation_modifier - guard_statement: - body: block - condition+: if_condition - hex_literal: - identifier: - part+: simple_identifier - if_condition: - kind: [availability_condition, expression, if_let_binding] - if_let_binding: - pattern: pattern - type?: type_annotation - value?: expression - where?: where_clause - if_statement: - body: block - condition+: if_condition - else_branch?: [block, if_statement] - implicitly_unwrapped_type: - name: type - import_declaration: - modifiers?: modifiers - name: identifier - scoped_import_kind?: ["class", "enum", "func", "let", "protocol", "struct", "typealias", "var"] - infix_expression: - lhs: expression - op: custom_operator - rhs: expression - inheritance_constraint: - attribute*: attribute - constrained_type: [identifier, nested_type_identifier] - inherits_from: [implicitly_unwrapped_type, type] - inheritance_modifier: - inheritance_specifier: - inherits_from: [function_type, suppressed_constraint, user_type] - init_declaration: - async?: "async" - bang?: bang - body?: block - modifiers?: modifiers - parameter*: function_parameter - throws?: [throws, throws_clause] - type_constraints?: type_constraints - type_parameters?: type_parameters - integer_literal: - interpolated_expression: - name?: value_argument_label - reference_specifier*: value_argument_label - type_modifiers?: type_modifiers - value?: expression - key_path_component: - name?: simple_identifier - postfix*: key_path_postfix - key_path_expression: - component*: key_path_component - type?: [array_type, dictionary_type, simple_user_type] - key_path_postfix: - argument*: value_argument - force_unwrap?: bang - key_path_string_expression: - expr: expression - lambda_function_type: - async?: "async" - params?: lambda_function_type_parameters - return_type?: [implicitly_unwrapped_type, type] - throws?: [throws, throws_clause] - lambda_function_type_parameters: - parameter+: lambda_parameter - lambda_literal: - attribute*: attribute - captures?: capture_list - statement*: [control_transfer_statement, do_statement, expression, for_statement, guard_statement, local_declaration, repeat_while_statement, statement_label, while_statement] - type?: lambda_function_type - lambda_parameter: - external_name?: simple_identifier - modifiers?: parameter_modifiers - name: [self_expression, simple_identifier] - type?: [implicitly_unwrapped_type, type] - line_str_text: - line_string_literal: - interpolation*: interpolated_expression - text*: [line_str_text, str_escaped_char] - macro_declaration: - definition?: macro_definition - modifiers?: modifiers - name: simple_identifier - parameter*: function_parameter - return_type?: unannotated_type - type_constraints?: type_constraints - type_parameters?: type_parameters - macro_definition: - body: [expression, external_macro_definition] - macro_invocation: - name: simple_identifier - suffix: call_suffix - type_parameters?: type_parameters - member_modifier: - metatype: - name: unannotated_type - modifiers: - modifier+: [attribute, function_modifier, inheritance_modifier, member_modifier, mutation_modifier, ownership_modifier, parameter_modifier, property_behavior_modifier, property_modifier, visibility_modifier] - modify_specifier: - mutation?: mutation_modifier - multi_line_str_text: - multi_line_string_literal: - interpolation*: interpolated_expression - text*: ["\"", multi_line_str_text, str_escaped_char] - multiline_comment: - multiplicative_expression: - lhs: expression - op: ["%", "*", "/"] - rhs: expression - mutation_modifier: - navigation_expression: - suffix: navigation_suffix - target: [array_type, dictionary_type, expression, parenthesized_type, user_type] - navigation_suffix: - suffix: [integer_literal, simple_identifier] - nested_type_identifier: - base: unannotated_type - member*: simple_identifier - nil_coalescing_expression: - if_nil: expression - value: expression - oct_literal: - opaque_type: - name: unannotated_type - open_end_range_expression: - start: expression - open_start_range_expression: - end: expression - operator_declaration: - body?: deprecated_operator_declaration_body - kind: ["infix", "postfix", "prefix"] - name: referenceable_operator - precedence_group?: simple_identifier - optional_chain_marker: - expr: expression - optional_type: - wrapped: [array_type, dictionary_type, tuple_type, user_type] - ownership_modifier: - parameter: - external_name?: simple_identifier - modifiers?: parameter_modifiers - name: simple_identifier - type: [implicitly_unwrapped_type, type] - parameter_modifier: - parameter_modifiers: - modifier+: parameter_modifier - parenthesized_type: - type: [dictionary_type, existential_type, opaque_type] - pattern: - binding?: value_binding_pattern - bound_identifier?: simple_identifier - kind: [binding_pattern, case_pattern, expression, tuple_pattern, type_casting_pattern, wildcard_pattern] - playground_literal: - argument+: playground_literal_argument - kind: ["colorLiteral", "fileLiteral", "imageLiteral"] - playground_literal_argument: - name: simple_identifier - value: expression - postfix_expression: - operation: ["++", "--", bang] - target: expression - precedence_group_attribute: - name: simple_identifier - value: [boolean_literal, simple_identifier] - precedence_group_attributes: - attribute+: precedence_group_attribute - precedence_group_declaration: - attributes?: precedence_group_attributes - name: simple_identifier - prefix_expression: - operation: ["&", "+", "++", "-", "--", ".", bang, custom_operator, "~"] - target: expression - property_behavior_modifier: - property_binding: - computed_value?: computed_property - name: pattern - observers?: willset_didset_block - type?: type_annotation - type_constraints?: type_constraints - value?: expression - property_declaration: - binding: value_binding_pattern - declarator+: property_binding - modifiers*: [attribute, inheritance_modifier, modifiers, ownership_modifier, property_behavior_modifier] - property_modifier: - protocol_body: - member*: protocol_member_declaration - protocol_composition_type: - type+: unannotated_type - protocol_declaration: - attribute*: attribute - body: protocol_body - inherits*: inheritance_specifier - modifiers?: modifiers - name: type_identifier - type_constraints?: type_constraints - type_parameters?: type_parameters - protocol_function_declaration: - async?: "async" - body?: block - modifiers?: modifiers - name: [referenceable_operator, simple_identifier] - parameter*: function_parameter - return_type?: [implicitly_unwrapped_type, type] - throws?: [throws, throws_clause] - type_constraints?: type_constraints - type_parameters?: type_parameters - protocol_property_declaration: - modifiers?: modifiers - name: pattern - requirements: protocol_property_requirements - type?: type_annotation - type_constraints?: type_constraints - protocol_property_requirements: - accessor*: [getter_specifier, setter_specifier] - range_expression: - end: expression - op: ["...", "..<"] - start: expression - raw_str_continuing_indicator: - raw_str_end_part: - raw_str_interpolation: - interpolation+: interpolated_expression - start: raw_str_interpolation_start - raw_str_interpolation_start: - raw_str_part: - raw_string_literal: - continuing*: raw_str_continuing_indicator - interpolation*: raw_str_interpolation - text+: [raw_str_end_part, raw_str_part] - real_literal: - referenceable_operator: - operator: ["!=", "!==", "%", "%=", "&", "*", "*=", "+", "++", "+=", "-", "--", "-=", "/", "/=", "<", "<<", "<=", "=", "==", "===", ">", ">=", ">>", "^", bang, custom_operator, "|", "~"] - regex_literal: - repeat_while_statement: - body: block - condition+: if_condition - selector_expression: - expr: expression - self_expression: - setter_specifier: - mutation?: mutation_modifier - shebang_line: - simple_identifier: - simple_user_type: - arguments?: type_arguments - name: type_identifier - source_file: - shebang?: shebang_line - statement*: [do_statement, expression, for_statement, global_declaration, guard_statement, repeat_while_statement, statement_label, throw_keyword, while_statement] - special_literal: - statement_label: - str_escaped_char: - subscript_declaration: - body: computed_property - modifiers?: modifiers - parameter*: function_parameter - return_type?: [implicitly_unwrapped_type, type] - type_constraints?: type_constraints - type_parameters?: type_parameters - super_expression: - suppressed_constraint: - suppressed: type_identifier - switch_entry: - default?: default_keyword - modifiers?: modifiers - pattern*: switch_pattern - statement+: [control_transfer_statement, do_statement, expression, for_statement, guard_statement, local_declaration, repeat_while_statement, statement_label, while_statement] - where?: where_clause - switch_pattern: - pattern: pattern - switch_statement: - entry*: switch_entry - expr: expression - ternary_expression: - condition: expression - if_false: expression - if_true: expression - throw_keyword: - throws: - throws_clause: - type: unannotated_type - try_expression: - expr: expression - operator: try_operator - try_operator: - tuple_expression: - element+: tuple_expression_item - tuple_expression_item: - name?: simple_identifier - value: expression - tuple_pattern: - item+: tuple_pattern_item - tuple_pattern_item: - name?: simple_identifier - pattern: pattern - tuple_type: - element*: tuple_type_item - tuple_type_item: - external_name?: wildcard_pattern - modifiers?: parameter_modifiers - name?: simple_identifier - type: [dictionary_type, existential_type, opaque_type, type] - type: - modifiers?: type_modifiers - name: unannotated_type - type_annotation: - type: [implicitly_unwrapped_type, type] - type_arguments: - argument+: type - type_casting_pattern: - pattern?: pattern - type: type - type_constraint: - constraint: [equality_constraint, inheritance_constraint] - type_constraints: - constraint+: type_constraint - keyword: where_keyword - type_identifier: - type_modifiers: - attribute+: attribute - type_pack_expansion: - name: unannotated_type - type_parameter: - modifiers?: type_parameter_modifiers - name: [type_identifier, type_parameter_pack] - type?: type - type_parameter_modifiers: - attribute+: attribute - type_parameter_pack: - name: unannotated_type - type_parameters: - constraints?: type_constraints - parameter+: type_parameter - typealias_declaration: - modifiers*: [attribute, inheritance_modifier, modifiers, ownership_modifier, property_behavior_modifier] - name: type_identifier - type_parameters?: type_parameters - value: type - user_type: - part+: simple_user_type - value_argument: - name?: value_argument_label - reference_specifier*: value_argument_label - type_modifiers?: type_modifiers - value?: expression - value_argument_label: - name: simple_identifier - value_arguments: - argument*: value_argument - value_binding_pattern: - mutability: ["let", "var"] - value_pack_expansion: - expr: expression - value_parameter_pack: - expr: expression - visibility_modifier: - where_clause: - expr: expression - keyword: where_keyword - where_keyword: - while_statement: - body: block - condition+: if_condition - wildcard_pattern: - willset_clause: - body: block - modifiers?: modifiers - parameter?: simple_identifier - willset_didset_block: - didset?: didset_clause - willset?: willset_clause - -unnamed: - - "?" - - "!" - - "!=" - - "!==" - - "\"" - - "\"\"\"" - - "#" - - "#else" - - "#elseif" - - "#endif" - - "#if" - - "%" - - "%=" - - "&" - - "&&" - - "(" - - ")" - - "*" - - "*=" - - "+" - - "++" - - "+=" - - "," - - "-" - - "--" - - "-=" - - "->" - - "." - - "..." - - "..<" - - "/" - - "/=" - - ":" - - ";" - - "<" - - "<<" - - "<=" - - "=" - - "==" - - "===" - - ">" - - ">=" - - ">>" - - "?" - - "??" - - "@" - - "@autoclosure" - - "@escaping" - - "Protocol" - - "Type" - - "[" - - "\\" - - "\\(" - - "]" - - "^" - - "^{" - - "_modify" - - "actor" - - "any" - - "arch" - - "as" - - "as!" - - "as?" - - "associatedtype" - - "async" - - "available" - - "await" - - "borrowing" - - "break" - - "canImport" - - "case" - - "class" - - "colorLiteral" - - "column" - - "compiler" - - "consuming" - - "continue" - - "convenience" - - "deinit" - - "didSet" - - "distributed" - - "do" - - "dsohandle" - - "dynamic" - - "each" - - "else" - - "enum" - - "extension" - - "externalMacro" - - "fallthrough" - - "false" - - "file" - - "fileID" - - "fileLiteral" - - "filePath" - - "fileprivate" - - "final" - - "for" - - "func" - - "function" - - "get" - - "getter:" - - "guard" - - "if" - - "imageLiteral" - - "import" - - "in" - - "indirect" - - "infix" - - "init" - - "inout" - - "internal" - - "is" - - "keyPath" - - "lazy" - - "let" - - "line" - - "macro" - - "mutating" - - "nil" - - "nonisolated" - - "nonmutating" - - "open" - - "operator" - - "optional" - - "os" - - "override" - - "package" - - "postfix" - - "precedencegroup" - - "prefix" - - "private" - - "protocol" - - "public" - - "repeat" - - "required" - - "return" - - "selector" - - "self" - - "set" - - "setter:" - - "some" - - "static" - - "struct" - - "subscript" - - "super" - - "swift" - - "switch" - - "targetEnvironment" - - "true" - - "try" - - "typealias" - - "u" - - "unavailable" - - "unowned" - - "unowned(safe)" - - "unowned(unsafe)" - - "var" - - "weak" - - "while" - - "willSet" - - "yield" - - "{" - - "|" - - "||" - - "}" - - "~" diff --git a/unified/extractor/tree-sitter-swift/package.json b/unified/extractor/tree-sitter-swift/package.json deleted file mode 100644 index 68dcf7cc42f..00000000000 --- a/unified/extractor/tree-sitter-swift/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "tree-sitter-swift", - "version": "0.7.2", - "description": "A tree-sitter grammar for the Swift programming language.", - "main": "bindings/node/index.js", - "types": "bindings/node", - "scripts": { - "install": "node-gyp-build", - "prestart": "tree-sitter build --wasm", - "start": "tree-sitter playground", - "test": "node --test bindings/node/*_test.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/alex-pinkus/tree-sitter-swift.git" - }, - "tree-sitter": [ - { - "scope": "source.swift", - "file-types": [ - "swift" - ], - "injection-regex": "swift", - "highlights": "queries/highlights.scm", - "locals": "queries/locals.scm", - "injections": "queries/injections.scm" - } - ], - "keywords": [ - "parser", - "swift" - ], - "files": [ - "grammar.js", - "tree-sitter.json", - "binding.gyp", - "prebuilds/**", - "bindings/node/*", - "queries/*", - "scripts/*", - "src/**" - ], - "author": "Alex Pinkus ", - "license": "MIT", - "bugs": { - "url": "https://github.com/alex-pinkus/tree-sitter-swift/issues" - }, - "homepage": "https://github.com/alex-pinkus/tree-sitter-swift#readme", - "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0", - "tree-sitter-cli": "^0.23", - "which": "2.0.2" - }, - "peerDependencies": { - "tree-sitter": "^0.22.1" - }, - "peerDependenciesMeta": { - "tree_sitter": { - "optional": true - } - }, - "devDependencies": { - "node-gyp": "^10.0.1", - "prebuildify": "^6.0.0", - "prettier": "2.3.2" - } -} diff --git a/unified/extractor/tree-sitter-swift/queries/folds.scm b/unified/extractor/tree-sitter-swift/queries/folds.scm deleted file mode 100644 index ca7f72593aa..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/folds.scm +++ /dev/null @@ -1,35 +0,0 @@ -; format-ignore -[ - (protocol_body) ; protocol Foo { ... } - (class_body) ; class Foo { ... } - (enum_class_body) ; enum Foo { ... } - (function_body) ; func Foo (...) {...} - (computed_property) ; { ... } - - (computed_getter) ; get { ... } - (computed_setter) ; set { ... } - - (do_statement) - (if_statement) - (for_statement) - (switch_statement) - (while_statement) - (guard_statement) - (switch_entry) - - (type_parameters) ; x - (tuple_type) ; (...) - (array_type) ; [String] - (dictionary_type) ; [Foo: Bar] - - (call_expression) ; callFunc(...) - (tuple_expression) ; ( foo + bar ) - (array_literal) ; [ foo, bar ] - (dictionary_literal) ; [ foo: bar, x: y ] - (lambda_literal) - (willset_didset_block) - (willset_clause) - (didset_clause) - - (import_declaration)+ -] @fold diff --git a/unified/extractor/tree-sitter-swift/queries/highlights.scm b/unified/extractor/tree-sitter-swift/queries/highlights.scm deleted file mode 100644 index 82ad68d4ed1..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/highlights.scm +++ /dev/null @@ -1,336 +0,0 @@ -[ - "." - ";" - ":" - "," -] @punctuation.delimiter - -[ - "(" - ")" - "[" - "]" - "{" - "}" -] @punctuation.bracket - -; Identifiers -(type_identifier) @type - -[ - (self_expression) - (super_expression) -] @variable.builtin - -; Declarations -[ - "func" - "deinit" -] @keyword.function - -[ - (visibility_modifier) - (member_modifier) - (function_modifier) - (property_modifier) - (parameter_modifier) - (inheritance_modifier) - (mutation_modifier) -] @keyword.modifier - -(simple_identifier) @variable - -(function_declaration - (simple_identifier) @function.method) - -(protocol_function_declaration - name: (simple_identifier) @function.method) - -(init_declaration - "init" @constructor) - -(parameter - external_name: (simple_identifier) @variable.parameter) - -(parameter - name: (simple_identifier) @variable.parameter) - -(type_parameter - (type_identifier) @variable.parameter) - -(inheritance_constraint - (identifier - (simple_identifier) @variable.parameter)) - -(equality_constraint - (identifier - (simple_identifier) @variable.parameter)) - -[ - "protocol" - "extension" - "indirect" - "nonisolated" - "override" - "convenience" - "required" - "some" - "any" - "weak" - "unowned" - "didSet" - "willSet" - "subscript" - "let" - "var" - (throws) - (where_keyword) - (getter_specifier) - (setter_specifier) - (modify_specifier) - (else) - (as_operator) -] @keyword - -[ - "enum" - "struct" - "class" - "typealias" -] @keyword.type - -[ - "async" - "await" -] @keyword.coroutine - -(shebang_line) @keyword.directive - -(class_body - (property_declaration - (pattern - (simple_identifier) @variable.member))) - -(protocol_property_declaration - (pattern - (simple_identifier) @variable.member)) - -(navigation_expression - (navigation_suffix - (simple_identifier) @variable.member)) - -(value_argument - name: (value_argument_label - (simple_identifier) @variable.member)) - -(import_declaration - "import" @keyword.import) - -(enum_entry - "case" @keyword) - -(modifiers - (attribute - "@" @attribute - (user_type - (type_identifier) @attribute))) - -; Function calls -(call_expression - (simple_identifier) @function.call) ; foo() - -(call_expression - ; foo.bar.baz(): highlight the baz() - (navigation_expression - (navigation_suffix - (simple_identifier) @function.call))) - -(call_expression - (prefix_expression - (simple_identifier) @function.call)) ; .foo() - -((navigation_expression - (simple_identifier) @type) ; SomeType.method(): highlight SomeType as a type - (#match? @type "^[A-Z]")) - -(directive) @keyword.directive - -; See https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/#Keywords-and-Punctuation -[ - (diagnostic) - (availability_condition) - (playground_literal) - (key_path_string_expression) - (selector_expression) - (external_macro_definition) -] @function.macro - -(special_literal) @constant.macro - -; Statements -(for_statement - "for" @keyword.repeat) - -(for_statement - "in" @keyword.repeat) - -[ - "while" - "repeat" - "continue" - "break" -] @keyword.repeat - -(guard_statement - "guard" @keyword.conditional) - -(if_statement - "if" @keyword.conditional) - -(switch_statement - "switch" @keyword.conditional) - -(switch_entry - "case" @keyword) - -(switch_entry - "fallthrough" @keyword) - -(switch_entry - (default_keyword) @keyword) - -"return" @keyword.return - -(ternary_expression - [ - "?" - ":" - ] @keyword.conditional.ternary) - -[ - (try_operator) - "do" - (throw_keyword) - (catch_keyword) -] @keyword.exception - -(statement_label) @label - -; Comments -[ - (comment) - (multiline_comment) -] @comment @spell - -((comment) @comment.documentation - (#match? @comment.documentation "^///[^/]")) - -((comment) @comment.documentation - (#match? @comment.documentation "^///$")) - -((multiline_comment) @comment.documentation - (#match? @comment.documentation "^/[*][*][^*].*[*]/$")) - -; String literals -(line_str_text) @string - -(str_escaped_char) @string.escape - -(multi_line_str_text) @string - -(raw_str_part) @string - -(raw_str_end_part) @string - -(line_string_literal - [ - "\\(" - ")" - ] @punctuation.special) - -(multi_line_string_literal - [ - "\\(" - ")" - ] @punctuation.special) - -(raw_str_interpolation - [ - (raw_str_interpolation_start) - ")" - ] @punctuation.special) - -[ - "\"" - "\"\"\"" -] @string - -; Lambda literals -(lambda_literal - "in" @keyword.operator) - -; Basic literals -[ - (integer_literal) - (hex_literal) - (oct_literal) - (bin_literal) -] @number - -(real_literal) @number.float - -(boolean_literal) @boolean - -"nil" @constant.builtin - -(wildcard_pattern) @character.special - -; Regex literals -(regex_literal) @string.regexp - -; Operators -(custom_operator) @operator - -[ - "+" - "-" - "*" - "/" - "%" - "=" - "+=" - "-=" - "*=" - "/=" - "<" - ">" - "<<" - ">>" - "<=" - ">=" - "++" - "--" - "^" - "&" - "&&" - "|" - "||" - "~" - "%=" - "!=" - "!==" - "==" - "===" - "?" - "??" - "->" - "..<" - "..." - (bang) -] @operator - -(type_arguments - [ - "<" - ">" - ] @punctuation.bracket) diff --git a/unified/extractor/tree-sitter-swift/queries/indents.scm b/unified/extractor/tree-sitter-swift/queries/indents.scm deleted file mode 100644 index ec8f8af95c6..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/indents.scm +++ /dev/null @@ -1,123 +0,0 @@ -; format-ignore -[ - ; ... refers to the section that will get affected by this indent.begin capture - (protocol_body) ; protocol Foo { ... } - (class_body) ; class Foo { ... } - (enum_class_body) ; enum Foo { ... } - (function_declaration) ; func Foo (...) {...} - (init_declaration) ; init(...) {...} - (deinit_declaration) ; deinit {...} - (computed_property) ; { ... } - (subscript_declaration) ; subscript Foo(...) { ... } - - (computed_getter) ; get { ... } - (computed_setter) ; set { ... } - - (assignment) ; a = b - - (control_transfer_statement) ; return ... - (for_statement) - (while_statement) - (repeat_while_statement) - (do_statement) - (if_statement) - (switch_statement) - (guard_statement) - - (type_parameters) ; x - (tuple_type) ; (...) - (array_type) ; [String] - (dictionary_type) ; [Foo: Bar] - - (call_expression) ; callFunc(...) - (tuple_expression) ; ( foo + bar ) - (array_literal) ; [ foo, bar ] - (dictionary_literal) ; [ foo: bar, x: y ] - (lambda_literal) - (willset_didset_block) - (willset_clause) - (didset_clause) -] @indent.begin - -(init_declaration) @indent.begin - -(init_declaration - [ - "init" - "(" - ] @indent.branch) - -; indentation for init parameters -(init_declaration - ")" @indent.branch @indent.end) - -(init_declaration - (parameter) @indent.begin - (#set! indent.immediate)) - -; @something(...) -(modifiers - (attribute) @indent.begin) - -(function_declaration - (modifiers - . - (attribute) - (_)* @indent.branch) - . - _ @indent.branch - (#not-kind-eq? @indent.branch "type_parameters" "parameter")) - -(ERROR - [ - "<" - "{" - "(" - "[" - ]) @indent.begin - -; if-elseif -(if_statement - (if_statement) @indent.dedent) - -; case Foo: -; default Foo: -; @attribute default Foo: -(switch_entry - . - _ @indent.branch) - -(function_declaration - ")" @indent.branch) - -(type_parameters - ">" @indent.branch @indent.end .) - -(tuple_expression - ")" @indent.branch @indent.end) - -(value_arguments - ")" @indent.branch @indent.end) - -(tuple_type - ")" @indent.branch @indent.end) - -(modifiers - (attribute - ")" @indent.branch @indent.end)) - -[ - "}" - "]" -] @indent.branch @indent.end - -[ - ; (ERROR) - (comment) - (multiline_comment) - (raw_str_part) - (multi_line_string_literal) -] @indent.auto - -(directive) @indent.ignore - diff --git a/unified/extractor/tree-sitter-swift/queries/injections.scm b/unified/extractor/tree-sitter-swift/queries/injections.scm deleted file mode 100644 index 512cfa0d522..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/injections.scm +++ /dev/null @@ -1,10 +0,0 @@ -; Parse regex syntax within regex literals - -((regex_literal) @injection.content - (#set! injection.language "regex")) - -([ - (comment) - (multiline_comment) -] @injection.content - (#set! injection.language "comment")) diff --git a/unified/extractor/tree-sitter-swift/queries/locals.scm b/unified/extractor/tree-sitter-swift/queries/locals.scm deleted file mode 100644 index 78032a81810..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/locals.scm +++ /dev/null @@ -1,23 +0,0 @@ -(import_declaration - (identifier) @local.definition.import) - -(function_declaration - name: (simple_identifier) @local.definition.function) - -; Scopes -[ - (statements) - (for_statement) - (while_statement) - (repeat_while_statement) - (do_statement) - (if_statement) - (guard_statement) - (switch_statement) - (property_declaration) - (function_declaration) - (class_declaration) - (protocol_declaration) -] @local.scope - - diff --git a/unified/extractor/tree-sitter-swift/queries/outline.scm b/unified/extractor/tree-sitter-swift/queries/outline.scm deleted file mode 100644 index 31fe5d9d4a4..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/outline.scm +++ /dev/null @@ -1,66 +0,0 @@ -(protocol_declaration - declaration_kind: "protocol" @name - . - _ * @name - . - body: (protocol_body) -) @item - -(class_declaration - declaration_kind: ( - [ - "actor" - "class" - "extension" - "enum" - "struct" - ] - ) @name - . - _ * @name - . - body: (_) -) @item - -(init_declaration - name: "init" @name - . - _ * @name - . - body: (function_body) -) @item - -(deinit_declaration - "deinit" @name) @item - -(function_declaration - "func" @name - . - _ * @name - . - body: (function_body) -) @item - -(class_body - (property_declaration - (value_binding_pattern) @name - name: (pattern) @name - (type_annotation)? @name - ) @item -) - -(enum_class_body - (property_declaration - (value_binding_pattern) @name - name: (pattern) @name - (type_annotation)? @name - ) @item -) - -( - (protocol_function_declaration) @name -) @item - -( - (protocol_property_declaration) @name -) @item diff --git a/unified/extractor/tree-sitter-swift/queries/tags.scm b/unified/extractor/tree-sitter-swift/queries/tags.scm deleted file mode 100644 index 0038571e5d7..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/tags.scm +++ /dev/null @@ -1,51 +0,0 @@ -(class_declaration - name: (type_identifier) @name) @definition.class - -(protocol_declaration - name: (type_identifier) @name) @definition.interface - -(class_declaration - (class_body - [ - (function_declaration - name: (simple_identifier) @name - ) - (subscript_declaration - (parameter (simple_identifier) @name) - ) - (init_declaration "init" @name) - (deinit_declaration "deinit" @name) - ] - ) -) @definition.method - -(protocol_declaration - (protocol_body - [ - (protocol_function_declaration - name: (simple_identifier) @name - ) - (subscript_declaration - (parameter (simple_identifier) @name) - ) - (init_declaration "init" @name) - ] - ) -) @definition.method - -(class_declaration - (class_body - [ - (property_declaration - (pattern (simple_identifier) @name) - ) - ] - ) -) @definition.property - -(property_declaration - (pattern (simple_identifier) @name) -) @definition.property - -(function_declaration - name: (simple_identifier) @name) @definition.function \ No newline at end of file diff --git a/unified/extractor/tree-sitter-swift/queries/textobjects.scm b/unified/extractor/tree-sitter-swift/queries/textobjects.scm deleted file mode 100644 index da689a1b29f..00000000000 --- a/unified/extractor/tree-sitter-swift/queries/textobjects.scm +++ /dev/null @@ -1,19 +0,0 @@ - - -; MARK: Structure - -(function_declaration - body: (_) @function.inside) @function.around - -; TODO: Classes/structs/enums - - -; MARK: Tests - -; Only matches prefix test. Other conventions -; might be nice to add! -(function_declaration - name: (simple_identifier) @_name - (#match? @_name "^test") -) - diff --git a/unified/extractor/tree-sitter-swift/src/scanner.c b/unified/extractor/tree-sitter-swift/src/scanner.c deleted file mode 100644 index bb2dcac58b2..00000000000 --- a/unified/extractor/tree-sitter-swift/src/scanner.c +++ /dev/null @@ -1,929 +0,0 @@ -#include "tree_sitter/parser.h" -#include -#include - -#define TOKEN_COUNT 33 - -enum TokenType { - BLOCK_COMMENT, - RAW_STR_PART, - RAW_STR_CONTINUING_INDICATOR, - RAW_STR_END_PART, - IMPLICIT_SEMI, - EXPLICIT_SEMI, - ARROW_OPERATOR, - DOT_OPERATOR, - CONJUNCTION_OPERATOR, - DISJUNCTION_OPERATOR, - NIL_COALESCING_OPERATOR, - EQUAL_SIGN, - EQ_EQ, - PLUS_THEN_WS, - MINUS_THEN_WS, - BANG, - THROWS_KEYWORD, - RETHROWS_KEYWORD, - DEFAULT_KEYWORD, - WHERE_KEYWORD, - ELSE_KEYWORD, - CATCH_KEYWORD, - AS_KEYWORD, - AS_QUEST, - AS_BANG, - ASYNC_KEYWORD, - CUSTOM_OPERATOR, - HASH_SYMBOL, - DIRECTIVE_IF, - DIRECTIVE_ELSEIF, - DIRECTIVE_ELSE, - DIRECTIVE_ENDIF, - FAKE_TRY_BANG -}; - -#define OPERATOR_COUNT 20 - -const char* OPERATORS[OPERATOR_COUNT] = { - "->", - ".", - "&&", - "||", - "??", - "=", - "==", - "+", - "-", - "!", - "throws", - "rethrows", - "default", - "where", - "else", - "catch", - "as", - "as?", - "as!", - "async" -}; - -enum IllegalTerminatorGroup { - ALPHANUMERIC, - OPERATOR_SYMBOLS, - OPERATOR_OR_DOT, - NON_WHITESPACE -}; - -const enum IllegalTerminatorGroup OP_ILLEGAL_TERMINATORS[OPERATOR_COUNT] = { - OPERATOR_SYMBOLS, // -> - OPERATOR_OR_DOT, // . - OPERATOR_SYMBOLS, // && - OPERATOR_SYMBOLS, // || - OPERATOR_SYMBOLS, // ?? - OPERATOR_SYMBOLS, // = - OPERATOR_SYMBOLS, // == - NON_WHITESPACE, // + - NON_WHITESPACE, // - - OPERATOR_SYMBOLS, // ! - ALPHANUMERIC, // throws - ALPHANUMERIC, // rethrows - ALPHANUMERIC, // default - ALPHANUMERIC, // where - ALPHANUMERIC, // else - ALPHANUMERIC, // catch - ALPHANUMERIC, // as - OPERATOR_SYMBOLS, // as? - OPERATOR_SYMBOLS, // as! - ALPHANUMERIC // async -}; - -const enum TokenType OP_SYMBOLS[OPERATOR_COUNT] = { - ARROW_OPERATOR, - DOT_OPERATOR, - CONJUNCTION_OPERATOR, - DISJUNCTION_OPERATOR, - NIL_COALESCING_OPERATOR, - EQUAL_SIGN, - EQ_EQ, - PLUS_THEN_WS, - MINUS_THEN_WS, - BANG, - THROWS_KEYWORD, - RETHROWS_KEYWORD, - DEFAULT_KEYWORD, - WHERE_KEYWORD, - ELSE_KEYWORD, - CATCH_KEYWORD, - AS_KEYWORD, - AS_QUEST, - AS_BANG, - ASYNC_KEYWORD -}; - -const uint64_t OP_SYMBOL_SUPPRESSOR[OPERATOR_COUNT] = { - 0, // ARROW_OPERATOR, - 0, // DOT_OPERATOR, - 0, // CONJUNCTION_OPERATOR, - 0, // DISJUNCTION_OPERATOR, - 0, // NIL_COALESCING_OPERATOR, - 0, // EQUAL_SIGN, - 0, // EQ_EQ, - 0, // PLUS_THEN_WS, - 0, // MINUS_THEN_WS, - 1UL << FAKE_TRY_BANG, // BANG, - 0, // THROWS_KEYWORD, - 0, // RETHROWS_KEYWORD, - 0, // DEFAULT_KEYWORD, - 0, // WHERE_KEYWORD, - 0, // ELSE_KEYWORD, - 0, // CATCH_KEYWORD, - 0, // AS_KEYWORD, - 0, // AS_QUEST, - 0, // AS_BANG, - 0, // ASYNC_KEYWORD -}; - -#define RESERVED_OP_COUNT 31 - -const char* RESERVED_OPS[RESERVED_OP_COUNT] = { - "/", - "=", - "-", - "+", - "!", - "*", - "%", - "<", - ">", - "&", - "|", - "^", - "?", - "~", - ".", - "..", - "->", - "/*", - "*/", - "+=", - "-=", - "*=", - "/=", - "%=", - ">>", - "<<", - "++", - "--", - "===", - "...", - "..<" -}; - -static bool is_cross_semi_token(enum TokenType op) { - switch(op) { - case ARROW_OPERATOR: - case DOT_OPERATOR: - case CONJUNCTION_OPERATOR: - case DISJUNCTION_OPERATOR: - case NIL_COALESCING_OPERATOR: - case EQUAL_SIGN: - case EQ_EQ: - case PLUS_THEN_WS: - case MINUS_THEN_WS: - case THROWS_KEYWORD: - case RETHROWS_KEYWORD: - case DEFAULT_KEYWORD: - case WHERE_KEYWORD: - case ELSE_KEYWORD: - case CATCH_KEYWORD: - case AS_KEYWORD: - case AS_QUEST: - case AS_BANG: - case ASYNC_KEYWORD: - case CUSTOM_OPERATOR: - return true; - case BANG: - default: - return false; - } -} - -#define NON_CONSUMING_CROSS_SEMI_CHAR_COUNT 3 -const uint32_t NON_CONSUMING_CROSS_SEMI_CHARS[NON_CONSUMING_CROSS_SEMI_CHAR_COUNT] = { '?', ':', '{' }; - -/** - * All possible results of having performed some sort of parsing. - * - * A parser can return a result along two dimensions: - * 1. Should the scanner continue trying to find another result? - * 2. Was some result produced by this parsing attempt? - * - * These are flattened into a single enum together. When the function returns one of the `TOKEN_FOUND` cases, it - * will always populate its `symbol_result` field. When it returns one of the `STOP_PARSING` cases, callers should - * immediately return (with the value, if there is one). - */ -enum ParseDirective { - CONTINUE_PARSING_NOTHING_FOUND, - CONTINUE_PARSING_TOKEN_FOUND, - CONTINUE_PARSING_SLASH_CONSUMED, - STOP_PARSING_NOTHING_FOUND, - STOP_PARSING_TOKEN_FOUND, - STOP_PARSING_END_OF_FILE -}; - -struct ScannerState { - uint32_t ongoing_raw_str_hash_count; -}; - -void *tree_sitter_swift_external_scanner_create() { - return calloc(1, sizeof(struct ScannerState)); -} - -void tree_sitter_swift_external_scanner_destroy(void *payload) { - free(payload); -} - -void tree_sitter_swift_external_scanner_reset(void *payload) { - struct ScannerState *state = (struct ScannerState *)payload; - state->ongoing_raw_str_hash_count = 0; -} - -unsigned tree_sitter_swift_external_scanner_serialize(void *payload, char *buffer) { - struct ScannerState *state = (struct ScannerState *)payload; - uint32_t hash_count = state->ongoing_raw_str_hash_count; - buffer[0] = (hash_count >> 24) & 0xff; - buffer[1] = (hash_count >> 16) & 0xff; - buffer[2] = (hash_count >> 8) & 0xff; - buffer[3] = (hash_count) & 0xff; - return 4; -} - -void tree_sitter_swift_external_scanner_deserialize( - void *payload, - const char *buffer, - unsigned length -) { - if (length < 4) { - return; - } - - uint32_t hash_count = ( - (((uint32_t) buffer[0]) << 24) | - (((uint32_t) buffer[1]) << 16) | - (((uint32_t) buffer[2]) << 8) | - (((uint32_t) buffer[3])) - ); - struct ScannerState *state = (struct ScannerState *)payload; - state->ongoing_raw_str_hash_count = hash_count; -} - -static void advance(TSLexer *lexer) { - lexer->advance(lexer, false); -} - -static bool should_treat_as_wspace(int32_t character) { - return iswspace(character) || (((int32_t) ';') == character); -} - -static int32_t encountered_op_count(bool *encountered_operator) { - int32_t encountered = 0; - for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) { - if (encountered_operator[op_idx]) { - encountered++; - } - } - - return encountered; -} - -static bool any_reserved_ops(uint8_t *encountered_reserved_ops) { - for (int op_idx = 0; op_idx < RESERVED_OP_COUNT; op_idx++) { - if (encountered_reserved_ops[op_idx] == 2) { - return true; - } - } - - return false; -} - -static bool is_legal_custom_operator( - int32_t char_idx, - int32_t first_char, - int32_t cur_char -) { - bool is_first_char = !char_idx; - switch (cur_char) { - case '=': - case '-': - case '+': - case '!': - case '%': - case '<': - case '>': - case '&': - case '|': - case '^': - case '?': - case '~': - return true; - case '.': - // Grammar allows `.` for any operator that starts with `.` - return is_first_char || first_char == '.'; - case '*': - case '/': - // Not listed in the grammar, but `/*` and `//` can't be the start of an operator since they start comments - return char_idx != 1 || first_char != '/'; - default: - if ( - (cur_char >= 0x00A1 && cur_char <= 0x00A7) || - (cur_char == 0x00A9) || - (cur_char == 0x00AB) || - (cur_char == 0x00AC) || - (cur_char == 0x00AE) || - (cur_char >= 0x00B0 && cur_char <= 0x00B1) || - (cur_char == 0x00B6) || - (cur_char == 0x00BB) || - (cur_char == 0x00BF) || - (cur_char == 0x00D7) || - (cur_char == 0x00F7) || - (cur_char >= 0x2016 && cur_char <= 0x2017) || - (cur_char >= 0x2020 && cur_char <= 0x2027) || - (cur_char >= 0x2030 && cur_char <= 0x203E) || - (cur_char >= 0x2041 && cur_char <= 0x2053) || - (cur_char >= 0x2055 && cur_char <= 0x205E) || - (cur_char >= 0x2190 && cur_char <= 0x23FF) || - (cur_char >= 0x2500 && cur_char <= 0x2775) || - (cur_char >= 0x2794 && cur_char <= 0x2BFF) || - (cur_char >= 0x2E00 && cur_char <= 0x2E7F) || - (cur_char >= 0x3001 && cur_char <= 0x3003) || - (cur_char >= 0x3008 && cur_char <= 0x3020) || - (cur_char == 0x3030) - ) { - return true; - } else if ( - (cur_char >= 0x0300 && cur_char <= 0x036f) || - (cur_char >= 0x1DC0 && cur_char <= 0x1DFF) || - (cur_char >= 0x20D0 && cur_char <= 0x20FF) || - (cur_char >= 0xFE00 && cur_char <= 0xFE0F) || - (cur_char >= 0xFE20 && cur_char <= 0xFE2F) || - (cur_char >= 0xE0100 && cur_char <= 0xE01EF) - ) { - return !is_first_char; - } else { - return false; - } - } -} - -static bool eat_operators( - TSLexer *lexer, - const bool *valid_symbols, - bool mark_end, - const int32_t prior_char, - enum TokenType *symbol_result -) { - bool possible_operators[OPERATOR_COUNT]; - uint8_t reserved_operators[RESERVED_OP_COUNT]; - for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) { - possible_operators[op_idx] = valid_symbols[OP_SYMBOLS[op_idx]] && (!prior_char || OPERATORS[op_idx][0] == prior_char); - } - for (int op_idx = 0; op_idx < RESERVED_OP_COUNT; op_idx++) { - reserved_operators[op_idx] = !prior_char || RESERVED_OPS[op_idx][0] == prior_char; - } - - bool possible_custom_operator = valid_symbols[CUSTOM_OPERATOR]; - int32_t first_char = prior_char ? prior_char : lexer->lookahead; - int32_t last_examined_char = first_char; - - int32_t str_idx = prior_char ? 1 : 0; - int32_t full_match = -1; - while(true) { - for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) { - if (!possible_operators[op_idx]) { - continue; - } - - if (OPERATORS[op_idx][str_idx] == '\0') { - // Make sure that the operator is allowed to have the next character as its lookahead. - enum IllegalTerminatorGroup illegal_terminators = OP_ILLEGAL_TERMINATORS[op_idx]; - switch (lexer->lookahead) { - // See "Operators": - // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418 - case '/': - case '=': - case '-': - case '+': - case '!': - case '*': - case '%': - case '<': - case '>': - case '&': - case '|': - case '^': - case '?': - case '~': - if (illegal_terminators == OPERATOR_SYMBOLS) { - break; - } // Otherwise, intentionally fall through to the OPERATOR_OR_DOT case - // fall through - case '.': - if (illegal_terminators == OPERATOR_OR_DOT) { - break; - } // Otherwise, fall through to DEFAULT which checks its groups directly - // fall through - default: - if (iswalnum(lexer->lookahead) && illegal_terminators == ALPHANUMERIC) { - break; - } - - if (!iswspace(lexer->lookahead) && illegal_terminators == NON_WHITESPACE) { - break; - } - - full_match = op_idx; - if (mark_end) { - lexer->mark_end(lexer); - } - } - - possible_operators[op_idx] = false; - continue; - } - - if (OPERATORS[op_idx][str_idx] != lexer->lookahead) { - possible_operators[op_idx] = false; - continue; - } - } - - for (int op_idx = 0; op_idx < RESERVED_OP_COUNT; op_idx++) { - if (!reserved_operators[op_idx]) { - continue; - } - - if (RESERVED_OPS[op_idx][str_idx] == '\0') { - reserved_operators[op_idx] = 0; - continue; - } - - if (RESERVED_OPS[op_idx][str_idx] != lexer->lookahead) { - reserved_operators[op_idx] = 0; - continue; - } - - if (RESERVED_OPS[op_idx][str_idx + 1] == '\0') { - reserved_operators[op_idx] = 2; - continue; - } - } - - possible_custom_operator = possible_custom_operator && is_legal_custom_operator( - str_idx, - first_char, - lexer->lookahead - ); - - uint32_t encountered_ops = encountered_op_count(possible_operators); - if (encountered_ops == 0) { - if (!possible_custom_operator) { - break; - } else if (mark_end && full_match == -1) { - lexer->mark_end(lexer); - } - } - - last_examined_char = lexer->lookahead; - lexer->advance(lexer, false); - str_idx += 1; - - if (encountered_ops == 0 && !is_legal_custom_operator( - str_idx, - first_char, - lexer->lookahead - )) { - break; - } - } - - if (full_match != -1) { - // We have a match -- first see if that match has a symbol that suppresses it. For example, in `try!`, we do not - // want to emit the `!` as a symbol in our scanner, because we want the parser to have the chance to parse it as - // an immediate token. - uint64_t suppressing_symbols = OP_SYMBOL_SUPPRESSOR[full_match]; - if (suppressing_symbols) { - for (uint64_t suppressor = 0; suppressor < TOKEN_COUNT; suppressor++) { - if (!(suppressing_symbols & 1ULL << suppressor)) { - continue; - } - - // The suppressing symbol is valid in this position, so skip it. - if (valid_symbols[suppressor]) { - return false; - } - } - } - *symbol_result = OP_SYMBOLS[full_match]; - return true; - } - - if (possible_custom_operator && !any_reserved_ops(reserved_operators)) { - if ((last_examined_char != '<' || iswspace(lexer->lookahead)) && mark_end) { - lexer->mark_end(lexer); - } - *symbol_result = CUSTOM_OPERATOR; - return true; - } - - return false; -} - -static enum ParseDirective eat_comment( - TSLexer *lexer, - const bool *valid_symbols, - bool mark_end, - enum TokenType *symbol_result -) { - if (lexer->lookahead != '/') { - return CONTINUE_PARSING_NOTHING_FOUND; - } - - advance(lexer); - - if (lexer->lookahead != '*') { - return CONTINUE_PARSING_SLASH_CONSUMED; - } - - advance(lexer); - - bool after_star = false; - unsigned nesting_depth = 1; - for (;;) { - switch (lexer->lookahead) { - case '\0': - return STOP_PARSING_END_OF_FILE; - case '*': - advance(lexer); - after_star = true; - break; - case '/': - if (after_star) { - advance(lexer); - after_star = false; - nesting_depth--; - if (nesting_depth == 0) { - if (mark_end) { - lexer->mark_end(lexer); - } - *symbol_result = BLOCK_COMMENT; - return STOP_PARSING_TOKEN_FOUND; - } - } else { - advance(lexer); - after_star = false; - if (lexer->lookahead == '*') { - nesting_depth++; - advance(lexer); - } - } - break; - default: - advance(lexer); - after_star = false; - break; - } - } -} - -static enum ParseDirective eat_whitespace( - TSLexer *lexer, - const bool *valid_symbols, - enum TokenType *symbol_result -) { - enum ParseDirective ws_directive = CONTINUE_PARSING_NOTHING_FOUND; - bool semi_is_valid = valid_symbols[IMPLICIT_SEMI] && valid_symbols[EXPLICIT_SEMI]; - uint32_t lookahead; - while (should_treat_as_wspace(lookahead = lexer->lookahead)) { - if (lookahead == ';') { - if (semi_is_valid) { - ws_directive = STOP_PARSING_TOKEN_FOUND; - lexer->advance(lexer, false); - } - - break; - } - - lexer->advance(lexer, true); - - lexer->mark_end(lexer); - - if (ws_directive == CONTINUE_PARSING_NOTHING_FOUND && (lookahead == '\n' || lookahead == '\r')) { - ws_directive = CONTINUE_PARSING_TOKEN_FOUND; - } - } - - enum ParseDirective any_comment = CONTINUE_PARSING_NOTHING_FOUND; - if (ws_directive == CONTINUE_PARSING_TOKEN_FOUND && lookahead == '/') { - bool has_seen_single_comment = false; - while (lexer->lookahead == '/') { - // It's possible that this is a comment - start an exploratory mission to find out, and if it is, look for what - // comes after it. We care about what comes after it for the purpose of suppressing the newline. - - enum TokenType multiline_comment_result; - any_comment = eat_comment(lexer, valid_symbols, /* mark_end */ false, &multiline_comment_result); - if (any_comment == STOP_PARSING_TOKEN_FOUND) { - // This is a multiline comment. This scanner should be parsing those, so we might want to bail out and - // emit it instead. However, we only want to do that if we haven't advanced through a _single_ line - // comment on the way - otherwise that will get lumped into this. - if (!has_seen_single_comment) { - lexer->mark_end(lexer); - *symbol_result = multiline_comment_result; - return STOP_PARSING_TOKEN_FOUND; - } - } else if (any_comment == STOP_PARSING_END_OF_FILE) { - return STOP_PARSING_END_OF_FILE; - } else if (any_comment == CONTINUE_PARSING_SLASH_CONSUMED) { - // We accidentally ate a slash -- we should actually bail out, say we saw nothing, and let the next pass - // take it from after the newline. - return CONTINUE_PARSING_SLASH_CONSUMED; - } else if (lexer->lookahead == '/') { - // There wasn't a multiline comment, which we know means that the comment parser ate its `/` and then - // bailed out. If it had seen anything comment-like after that first `/` it would have continued going - // and eventually had a well-formed comment or an EOF. Thus, if we're currently looking at a `/`, it's - // the second one of those and it means we have a single-line comment. - has_seen_single_comment = true; - while (lexer->lookahead != '\n' && lexer->lookahead != '\0') { - lexer->advance(lexer, true); - } - } else if (iswspace(lexer->lookahead)) { - // We didn't see any type of comment - in fact, we saw an operator that we don't normally treat as an - // operator. Still, this is a reason to stop parsing. - return STOP_PARSING_NOTHING_FOUND; - } - - // If we skipped through some comment, we're at whitespace now, so advance. - while(iswspace(lexer->lookahead)) { - any_comment = CONTINUE_PARSING_NOTHING_FOUND; // We're advancing, so clear out the comment - lexer->advance(lexer, true); - } - } - - enum TokenType operator_result; - bool saw_operator = eat_operators( - lexer, - valid_symbols, - /* mark_end */ false, - '\0', - &operator_result - ); - if (saw_operator) { - // The operator we saw should suppress the newline, so bail out. - return STOP_PARSING_NOTHING_FOUND; - } else { - // Promote the implicit newline to an explicit one so we don't check for operators again. - *symbol_result = IMPLICIT_SEMI; - ws_directive = STOP_PARSING_TOKEN_FOUND; - } - } - - // Let's consume operators that can live after a "semicolon" style newline. Before we do that, though, we want to - // check for a set of characters that we do not consume, but that still suppress the semi. - if (ws_directive == CONTINUE_PARSING_TOKEN_FOUND) { - for (int i = 0; i < NON_CONSUMING_CROSS_SEMI_CHAR_COUNT; i++) { - if (NON_CONSUMING_CROSS_SEMI_CHARS[i] == lookahead) { - return CONTINUE_PARSING_NOTHING_FOUND; - } - } - } - - if (semi_is_valid && ws_directive != CONTINUE_PARSING_NOTHING_FOUND) { - *symbol_result = lookahead == ';' ? EXPLICIT_SEMI : IMPLICIT_SEMI; - return ws_directive; - } - - return CONTINUE_PARSING_NOTHING_FOUND; -} - -#define DIRECTIVE_COUNT 4 -const char* DIRECTIVES[OPERATOR_COUNT] = { - "if", - "elseif", - "else", - "endif" -}; - -const enum TokenType DIRECTIVE_SYMBOLS[DIRECTIVE_COUNT] = { - DIRECTIVE_IF, - DIRECTIVE_ELSEIF, - DIRECTIVE_ELSE, - DIRECTIVE_ENDIF -}; - -static enum TokenType find_possible_compiler_directive(TSLexer *lexer) { - bool possible_directives[DIRECTIVE_COUNT]; - for (int dir_idx = 0; dir_idx < DIRECTIVE_COUNT; dir_idx++) { - possible_directives[dir_idx] = true; - } - - int32_t str_idx = 0; - int32_t full_match = -1; - while(true) { - for (int dir_idx = 0; dir_idx < DIRECTIVE_COUNT; dir_idx++) { - if (!possible_directives[dir_idx]) { - continue; - } - - uint8_t expected_char = DIRECTIVES[dir_idx][str_idx]; - if (expected_char == '\0') { - full_match = dir_idx; - lexer->mark_end(lexer); - } - - if (expected_char != lexer->lookahead) { - possible_directives[dir_idx] = false; - continue; - } - } - - uint8_t match_count = 0; - for (int dir_idx = 0; dir_idx < DIRECTIVE_COUNT; dir_idx += 1) { - if (possible_directives[dir_idx]) { - match_count += 1; - } - } - - if (match_count == 0) { - break; - } - - lexer->advance(lexer, false); - str_idx += 1; - } - - if (full_match == -1) { - // No compiler directive found, so just match the starting symbol - return HASH_SYMBOL; - } - - return DIRECTIVE_SYMBOLS[full_match]; -} - -static bool eat_raw_str_part( - struct ScannerState *state, - TSLexer *lexer, - const bool *valid_symbols, - enum TokenType *symbol_result -) { - uint32_t hash_count = state->ongoing_raw_str_hash_count; - if (!valid_symbols[RAW_STR_PART]) { - return false; - } else if (hash_count == 0) { - // If this is a raw_str_part, it's the first one - look for hashes - while (lexer->lookahead == '#') { - hash_count += 1; - advance(lexer); - } - - if (hash_count == 0) { - return false; - } - - if (lexer->lookahead == '"') { - advance(lexer); - } else if (hash_count == 1) { - lexer->mark_end(lexer); - *symbol_result = find_possible_compiler_directive(lexer); - return true; - } else { - return false; - } - - } else if (valid_symbols[RAW_STR_CONTINUING_INDICATOR]) { - // This is the end of an interpolation - now it's another raw_str_part. This is a synthetic - // marker to tell us that the grammar just consumed a `(` symbol to close a raw - // interpolation (since we don't want to fire on every `(` in existence). We don't have - // anything to do except continue. - } else { - return false; - } - - // We're in a state where anything other than `hash_count` hash symbols in a row should be eaten - // and is part of a string. - // The last character _before_ the hashes will tell us what happens next. - // Matters are also complicated by the fact that we don't want to consume every character we - // visit; if we see a `\#(`, for instance, with the appropriate number of hash symbols, we want - // to end our parsing _before_ that sequence. This allows highlighting tools to treat that as a - // separate token. - while (lexer->lookahead != '\0') { - uint8_t last_char = '\0'; - lexer->mark_end(lexer); // We always want to parse thru the start of the string so far - // Advance through anything that isn't a hash symbol, because we want to count those. - while (lexer->lookahead != '#' && lexer->lookahead != '\0') { - last_char = lexer->lookahead; - advance(lexer); - if (last_char != '\\' || lexer->lookahead == '\\') { - // Mark a new end, but only if we didn't just advance past a `\` symbol, since we - // don't want to consume that. Exception: if this is a `\` that happens _right - // after_ another `\`, we for some reason _do_ want to consume that, because - // apparently that is parsed as a literal `\` followed by something escaped. - lexer->mark_end(lexer); - } - } - - // We hit at least one hash - count them and see if they match. - uint32_t current_hash_count = 0; - while (lexer->lookahead == '#' && current_hash_count < hash_count) { - current_hash_count += 1; - advance(lexer); - } - - // If we saw exactly the right number of hashes, one of three things is true: - // 1. We're trying to interpolate into this string. - // 2. The string just ended. - // 3. This was just some hash characters doing nothing important. - if (current_hash_count == hash_count) { - if (last_char == '\\' && lexer->lookahead == '(') { - // Interpolation case! Don't consume those chars; they get saved for grammar.js. - *symbol_result = RAW_STR_PART; - state->ongoing_raw_str_hash_count = hash_count; - return true; - } else if (last_char == '"') { - // The string is finished! Mark the end here, on the very last hash symbol. - lexer->mark_end(lexer); - *symbol_result = RAW_STR_END_PART; - state->ongoing_raw_str_hash_count = 0; - return true; - } - // Nothing special happened - let the string continue. - } - } - - return false; -} - -bool tree_sitter_swift_external_scanner_scan( - void *payload, - TSLexer *lexer, - const bool *valid_symbols -) { - // Figure out our scanner state - struct ScannerState *state = (struct ScannerState *)payload; - - // Consume any whitespace at the start. - enum TokenType ws_result; - enum ParseDirective ws_directive = eat_whitespace(lexer, valid_symbols, &ws_result); - if (ws_directive == STOP_PARSING_TOKEN_FOUND) { - lexer->result_symbol = ws_result; - return true; - } - - if (ws_directive == STOP_PARSING_NOTHING_FOUND || ws_directive == STOP_PARSING_END_OF_FILE) { - return false; - } - - bool has_ws_result = (ws_directive == CONTINUE_PARSING_TOKEN_FOUND); - - // Now consume comments (before custom operators so that those aren't treated as comments) - enum TokenType comment_result; - enum ParseDirective comment = ws_directive == CONTINUE_PARSING_SLASH_CONSUMED ? ws_directive : eat_comment(lexer, valid_symbols, /* mark_end */ true, &comment_result); - if (comment == STOP_PARSING_TOKEN_FOUND) { - lexer->mark_end(lexer); - lexer->result_symbol = comment_result; - return true; - } - - if (comment == STOP_PARSING_END_OF_FILE) { - return false; - } - // Now consume any operators that might cause our whitespace to be suppressed. - enum TokenType operator_result; - bool saw_operator = eat_operators( - lexer, - valid_symbols, - /* mark_end */ !has_ws_result, - comment == CONTINUE_PARSING_SLASH_CONSUMED ? '/' : '\0', - &operator_result - ); - - if (saw_operator && (!has_ws_result || is_cross_semi_token(operator_result))) { - lexer->result_symbol = operator_result; - if (has_ws_result) lexer->mark_end(lexer); - return true; - } - - if (has_ws_result) { - // Don't `mark_end`, since we may have advanced through some operators. - lexer->result_symbol = ws_result; - return true; - } - - // NOTE: this will consume any `#` characters it sees, even if it does not find a result. Keep - // it at the end so that it doesn't interfere with special literals or selectors! - enum TokenType raw_str_result; - bool saw_raw_str_part = eat_raw_str_part(state, lexer, valid_symbols, &raw_str_result); - if (saw_raw_str_part) { - lexer->result_symbol = raw_str_result; - return true; - } - - return false; -} - diff --git a/unified/extractor/tree-sitter-swift/tree-sitter.json b/unified/extractor/tree-sitter-swift/tree-sitter.json deleted file mode 100644 index 3cd49a28a38..00000000000 --- a/unified/extractor/tree-sitter-swift/tree-sitter.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "grammars": [ - { - "name": "swift", - "camelcase": "Swift", - "scope": "source.swift", - "path": ".", - "file-types": [ - "swift" - ], - "highlights": "queries/highlights.scm", - "injections": "queries/injections.scm", - "locals": "queries/locals.scm", - "injection-regex": "swift" - } - ], - "metadata": { - "version": "0.7.2", - "license": "MIT", - "description": "A tree-sitter grammar for the Swift programming language.", - "authors": [ - { - "name": "Alex Pinkus", - "email": "alex.pinkus@gmail.com" - } - ], - "links": { - "repository": "git+https://github.com/alex-pinkus/tree-sitter-swift.git" - } - }, - "bindings": { - "c": true, - "go": true, - "node": true, - "python": true, - "rust": true, - "swift": true - } -} diff --git a/unified/scripts/regenerate-grammar.sh b/unified/scripts/regenerate-grammar.sh deleted file mode 100755 index b7a5ce263fb..00000000000 --- a/unified/scripts/regenerate-grammar.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# Regenerate the vendored tree-sitter-swift parser tables from grammar.js, -# then refresh the human-readable node-types.yml companion file. -# -# Run this after editing -# unified/extractor/tree-sitter-swift/grammar.js so that: -# * src/parser.c, src/grammar.json, src/node-types.json (and the -# src/tree_sitter/*.h headers) reflect the current grammar; and -# * node-types.yml shows the same information in a form that's -# pleasant to review in PR diffs. -# -# Requirements: tree-sitter CLI on PATH, and a working cargo toolchain. -set -euo pipefail - -cd "$(dirname "$0")/.." -SWIFT_DIR="extractor/tree-sitter-swift" - -( - cd "$SWIFT_DIR" - tree-sitter generate -) - -# Build yeast's node_types_yaml binary and use it to convert the freshly -# generated src/node-types.json into the human-readable node-types.yml. -cargo run --release --quiet -p yeast --bin node_types_yaml -- \ - --from-json "$SWIFT_DIR/src/node-types.json" > "$SWIFT_DIR/node-types.yml" - -echo "Regenerated $SWIFT_DIR/{src/parser.c,src/grammar.json,src/node-types.json,node-types.yml}"