Add context predicate parser

Nathan Sobo created

Change summary

Cargo.lock                                               |   1 
gpui/Cargo.toml                                          |   1 
gpui/build.rs                                            |  12 
gpui/grammars/context-predicate/.gitignore               |   2 
gpui/grammars/context-predicate/binding.gyp              |  18 
gpui/grammars/context-predicate/corpus/expressions.txt   |  49 
gpui/grammars/context-predicate/grammar.js               |  31 
gpui/grammars/context-predicate/index.js                 |  13 
gpui/grammars/context-predicate/package-lock.json        |  44 
gpui/grammars/context-predicate/package.json             |  10 
gpui/grammars/context-predicate/src/binding.cc           |  28 
gpui/grammars/context-predicate/src/grammar.json         | 208 +++
gpui/grammars/context-predicate/src/node-types.json      | 353 ++++++
gpui/grammars/context-predicate/src/parser.c             | 527 ++++++++++
gpui/grammars/context-predicate/src/tree_sitter/parser.h | 238 ++++
gpui/src/keymap.rs                                       |   4 
16 files changed, 1,537 insertions(+), 2 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -576,6 +576,7 @@ dependencies = [
  "anyhow",
  "async-task 4.0.3 (git+https://github.com/zedit-io/async-task?rev=341b57d6de98cdfd7b418567b8de2022ca993a6e)",
  "bindgen",
+ "cc",
  "cocoa",
  "core-foundation",
  "core-text",

gpui/Cargo.toml 🔗

@@ -15,6 +15,7 @@ tree-sitter = "0.17"
 
 [build-dependencies]
 bindgen = "0.57"
+cc = "1.0.67"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 anyhow = "1"

gpui/build.rs 🔗

@@ -2,6 +2,7 @@ use std::{env, path::PathBuf};
 
 fn main() {
     generate_dispatch_bindings();
+    compile_context_predicate_parser();
 }
 
 fn generate_dispatch_bindings() {
@@ -21,3 +22,14 @@ fn generate_dispatch_bindings() {
         .write_to_file(out_path.join("dispatch_sys.rs"))
         .expect("couldn't write bindings");
 }
+
+fn compile_context_predicate_parser() {
+    let dir = PathBuf::from("./grammars/context-predicate/src");
+    let parser_c = dir.join("parser.c");
+
+    println!("cargo:rerun-if-changed={}", &parser_c.to_str().unwrap());
+    cc::Build::new()
+        .include(&dir)
+        .file(parser_c)
+        .compile("tree_sitter_context_predicate");
+}

gpui/grammars/context-predicate/binding.gyp 🔗

@@ -0,0 +1,18 @@
+{
+  "targets": [
+    {
+      "target_name": "tree_sitter_context_predicate_binding",
+      "include_dirs": [
+        "<!(node -e \"require('nan')\")",
+        "src"
+      ],
+      "sources": [
+        "src/parser.c",
+        "src/binding.cc"
+      ],
+      "cflags_c": [
+        "-std=c99",
+      ]
+    }
+  ]
+}

gpui/grammars/context-predicate/corpus/expressions.txt 🔗

@@ -0,0 +1,49 @@
+==================
+Identifiers
+==================
+
+abc12
+
+---
+
+(source (identifier))
+
+==================
+Negation
+==================
+
+!abc
+
+---
+
+(source (not (identifier)))
+
+==================
+And/Or
+==================
+
+a || b && c && d
+
+---
+
+(source
+  (or
+    (identifier)
+    (and
+      (and (identifier) (identifier))
+      (identifier))))
+
+==================
+Expressions
+==================
+
+a && (b == c || d != e)
+
+---
+
+(source
+  (and
+    (identifier)
+    (parenthesized (or
+      (equal (identifier) (identifier))
+      (not_equal (identifier) (identifier))))))

gpui/grammars/context-predicate/grammar.js 🔗

@@ -0,0 +1,31 @@
+module.exports = grammar({
+  name: 'context_predicate',
+
+  rules: {
+    source: $ => $._expression,
+
+    _expression: $ => choice(
+      $.identifier,
+      $.not,
+      $.and,
+      $.or,
+      $.equal,
+      $.not_equal,
+      $.parenthesized,
+    ),
+
+    identifier: $ => /[A-Za-z0-9_-]+/,
+
+    not: $ => prec(3, seq("!", field("expression", $._expression))),
+
+    and: $ => prec.left(2, seq(field("left", $._expression), "&&", field("right", $._expression))),
+
+    or: $ => prec.left(1, seq(field("left", $._expression), "||", field("right", $._expression))),
+
+    equal: $ => seq(field("left", $.identifier), "==", field("right", $.identifier)),
+
+    not_equal: $ => seq(field("left", $.identifier), "!=", field("right", $.identifier)),
+
+    parenthesized: $ => seq("(", field("expression", $._expression), ")"),
+  }
+});

gpui/grammars/context-predicate/index.js 🔗

@@ -0,0 +1,13 @@
+try {
+  module.exports = require("./build/Release/tree_sitter_context_predicate_binding");
+} catch (error) {
+  try {
+    module.exports = require("./build/Debug/tree_sitter_context_predicate_binding");
+  } catch (_) {
+    throw error
+  }
+}
+
+try {
+  module.exports.nodeTypeInfo = require("./src/node-types.json");
+} catch (_) { }

gpui/grammars/context-predicate/package-lock.json 🔗

@@ -0,0 +1,44 @@
+{
+  "name": "tree-sitter-context-predicate",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "tree-sitter-context-predicate",
+      "dependencies": {
+        "nan": "^2.14.0"
+      },
+      "devDependencies": {
+        "tree-sitter-cli": "^0.18.3"
+      }
+    },
+    "node_modules/nan": {
+      "version": "2.14.2",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ=="
+    },
+    "node_modules/tree-sitter-cli": {
+      "version": "0.18.3",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.18.3.tgz",
+      "integrity": "sha512-ntN8Siljy7dlazb4cSYtZCfibaNppIy6RIr/XGt44GW1hAy/yuTLtKVi4kqYlImB4/7H0AjktcSlQRmI8zLNng==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "tree-sitter": "cli.js"
+      }
+    }
+  },
+  "dependencies": {
+    "nan": {
+      "version": "2.14.2",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ=="
+    },
+    "tree-sitter-cli": {
+      "version": "0.18.3",
+      "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.18.3.tgz",
+      "integrity": "sha512-ntN8Siljy7dlazb4cSYtZCfibaNppIy6RIr/XGt44GW1hAy/yuTLtKVi4kqYlImB4/7H0AjktcSlQRmI8zLNng==",
+      "dev": true
+    }
+  }
+}

gpui/grammars/context-predicate/package.json 🔗

@@ -0,0 +1,10 @@
+{
+  "name": "tree-sitter-context-predicate",
+  "main": "index.js",
+  "devDependencies": {
+    "tree-sitter-cli": "^0.18.3"
+  },
+  "dependencies": {
+    "nan": "^2.14.0"
+  }
+}

gpui/grammars/context-predicate/src/binding.cc 🔗

@@ -0,0 +1,28 @@
+#include "tree_sitter/parser.h"
+#include <node.h>
+#include "nan.h"
+
+using namespace v8;
+
+extern "C" TSLanguage * tree_sitter_context_predicate();
+
+namespace {
+
+NAN_METHOD(New) {}
+
+void Init(Local<Object> exports, Local<Object> module) {
+  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
+  tpl->SetClassName(Nan::New("Language").ToLocalChecked());
+  tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+  Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
+  Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
+  Nan::SetInternalFieldPointer(instance, 0, tree_sitter_context_predicate());
+
+  Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("context_predicate").ToLocalChecked());
+  Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
+}
+
+NODE_MODULE(tree_sitter_context_predicate_binding, Init)
+
+}  // namespace

gpui/grammars/context-predicate/src/grammar.json 🔗

@@ -0,0 +1,208 @@
+{
+  "name": "context_predicate",
+  "rules": {
+    "source": {
+      "type": "SYMBOL",
+      "name": "_expression"
+    },
+    "_expression": {
+      "type": "CHOICE",
+      "members": [
+        {
+          "type": "SYMBOL",
+          "name": "identifier"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "not"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "and"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "or"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "equal"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "not_equal"
+        },
+        {
+          "type": "SYMBOL",
+          "name": "parenthesized"
+        }
+      ]
+    },
+    "identifier": {
+      "type": "PATTERN",
+      "value": "[A-Za-z0-9_-]+"
+    },
+    "not": {
+      "type": "PREC",
+      "value": 3,
+      "content": {
+        "type": "SEQ",
+        "members": [
+          {
+            "type": "STRING",
+            "value": "!"
+          },
+          {
+            "type": "FIELD",
+            "name": "expression",
+            "content": {
+              "type": "SYMBOL",
+              "name": "_expression"
+            }
+          }
+        ]
+      }
+    },
+    "and": {
+      "type": "PREC_LEFT",
+      "value": 2,
+      "content": {
+        "type": "SEQ",
+        "members": [
+          {
+            "type": "FIELD",
+            "name": "left",
+            "content": {
+              "type": "SYMBOL",
+              "name": "_expression"
+            }
+          },
+          {
+            "type": "STRING",
+            "value": "&&"
+          },
+          {
+            "type": "FIELD",
+            "name": "right",
+            "content": {
+              "type": "SYMBOL",
+              "name": "_expression"
+            }
+          }
+        ]
+      }
+    },
+    "or": {
+      "type": "PREC_LEFT",
+      "value": 1,
+      "content": {
+        "type": "SEQ",
+        "members": [
+          {
+            "type": "FIELD",
+            "name": "left",
+            "content": {
+              "type": "SYMBOL",
+              "name": "_expression"
+            }
+          },
+          {
+            "type": "STRING",
+            "value": "||"
+          },
+          {
+            "type": "FIELD",
+            "name": "right",
+            "content": {
+              "type": "SYMBOL",
+              "name": "_expression"
+            }
+          }
+        ]
+      }
+    },
+    "equal": {
+      "type": "SEQ",
+      "members": [
+        {
+          "type": "FIELD",
+          "name": "left",
+          "content": {
+            "type": "SYMBOL",
+            "name": "identifier"
+          }
+        },
+        {
+          "type": "STRING",
+          "value": "=="
+        },
+        {
+          "type": "FIELD",
+          "name": "right",
+          "content": {
+            "type": "SYMBOL",
+            "name": "identifier"
+          }
+        }
+      ]
+    },
+    "not_equal": {
+      "type": "SEQ",
+      "members": [
+        {
+          "type": "FIELD",
+          "name": "left",
+          "content": {
+            "type": "SYMBOL",
+            "name": "identifier"
+          }
+        },
+        {
+          "type": "STRING",
+          "value": "!="
+        },
+        {
+          "type": "FIELD",
+          "name": "right",
+          "content": {
+            "type": "SYMBOL",
+            "name": "identifier"
+          }
+        }
+      ]
+    },
+    "parenthesized": {
+      "type": "SEQ",
+      "members": [
+        {
+          "type": "STRING",
+          "value": "("
+        },
+        {
+          "type": "FIELD",
+          "name": "expression",
+          "content": {
+            "type": "SYMBOL",
+            "name": "_expression"
+          }
+        },
+        {
+          "type": "STRING",
+          "value": ")"
+        }
+      ]
+    }
+  },
+  "extras": [
+    {
+      "type": "PATTERN",
+      "value": "\\s"
+    }
+  ],
+  "conflicts": [],
+  "precedences": [],
+  "externals": [],
+  "inline": [],
+  "supertypes": []
+}
+

gpui/grammars/context-predicate/src/node-types.json 🔗

@@ -0,0 +1,353 @@
+[
+  {
+    "type": "and",
+    "named": true,
+    "fields": {
+      "left": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      },
+      "right": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "equal",
+    "named": true,
+    "fields": {
+      "left": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "identifier",
+            "named": true
+          }
+        ]
+      },
+      "right": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "identifier",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "not",
+    "named": true,
+    "fields": {
+      "expression": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "not_equal",
+    "named": true,
+    "fields": {
+      "left": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "identifier",
+            "named": true
+          }
+        ]
+      },
+      "right": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "identifier",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "or",
+    "named": true,
+    "fields": {
+      "left": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      },
+      "right": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "parenthesized",
+    "named": true,
+    "fields": {
+      "expression": {
+        "multiple": false,
+        "required": true,
+        "types": [
+          {
+            "type": "and",
+            "named": true
+          },
+          {
+            "type": "equal",
+            "named": true
+          },
+          {
+            "type": "identifier",
+            "named": true
+          },
+          {
+            "type": "not",
+            "named": true
+          },
+          {
+            "type": "not_equal",
+            "named": true
+          },
+          {
+            "type": "or",
+            "named": true
+          },
+          {
+            "type": "parenthesized",
+            "named": true
+          }
+        ]
+      }
+    }
+  },
+  {
+    "type": "source",
+    "named": true,
+    "fields": {},
+    "children": {
+      "multiple": false,
+      "required": true,
+      "types": [
+        {
+          "type": "and",
+          "named": true
+        },
+        {
+          "type": "equal",
+          "named": true
+        },
+        {
+          "type": "identifier",
+          "named": true
+        },
+        {
+          "type": "not",
+          "named": true
+        },
+        {
+          "type": "not_equal",
+          "named": true
+        },
+        {
+          "type": "or",
+          "named": true
+        },
+        {
+          "type": "parenthesized",
+          "named": true
+        }
+      ]
+    }
+  },
+  {
+    "type": "!",
+    "named": false
+  },
+  {
+    "type": "!=",
+    "named": false
+  },
+  {
+    "type": "&&",
+    "named": false
+  },
+  {
+    "type": "(",
+    "named": false
+  },
+  {
+    "type": ")",
+    "named": false
+  },
+  {
+    "type": "==",
+    "named": false
+  },
+  {
+    "type": "identifier",
+    "named": true
+  },
+  {
+    "type": "||",
+    "named": false
+  }
+]

gpui/grammars/context-predicate/src/parser.c 🔗

@@ -0,0 +1,527 @@
+#include <tree_sitter/parser.h>
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+#define LANGUAGE_VERSION 12
+#define STATE_COUNT 18
+#define LARGE_STATE_COUNT 6
+#define SYMBOL_COUNT 17
+#define ALIAS_COUNT 0
+#define TOKEN_COUNT 9
+#define EXTERNAL_TOKEN_COUNT 0
+#define FIELD_COUNT 3
+#define MAX_ALIAS_SEQUENCE_LENGTH 3
+
+enum {
+  sym_identifier = 1,
+  anon_sym_BANG = 2,
+  anon_sym_AMP_AMP = 3,
+  anon_sym_PIPE_PIPE = 4,
+  anon_sym_EQ_EQ = 5,
+  anon_sym_BANG_EQ = 6,
+  anon_sym_LPAREN = 7,
+  anon_sym_RPAREN = 8,
+  sym_source = 9,
+  sym__expression = 10,
+  sym_not = 11,
+  sym_and = 12,
+  sym_or = 13,
+  sym_equal = 14,
+  sym_not_equal = 15,
+  sym_parenthesized = 16,
+};
+
+static const char *ts_symbol_names[] = {
+  [ts_builtin_sym_end] = "end",
+  [sym_identifier] = "identifier",
+  [anon_sym_BANG] = "!",
+  [anon_sym_AMP_AMP] = "&&",
+  [anon_sym_PIPE_PIPE] = "||",
+  [anon_sym_EQ_EQ] = "==",
+  [anon_sym_BANG_EQ] = "!=",
+  [anon_sym_LPAREN] = "(",
+  [anon_sym_RPAREN] = ")",
+  [sym_source] = "source",
+  [sym__expression] = "_expression",
+  [sym_not] = "not",
+  [sym_and] = "and",
+  [sym_or] = "or",
+  [sym_equal] = "equal",
+  [sym_not_equal] = "not_equal",
+  [sym_parenthesized] = "parenthesized",
+};
+
+static TSSymbol ts_symbol_map[] = {
+  [ts_builtin_sym_end] = ts_builtin_sym_end,
+  [sym_identifier] = sym_identifier,
+  [anon_sym_BANG] = anon_sym_BANG,
+  [anon_sym_AMP_AMP] = anon_sym_AMP_AMP,
+  [anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE,
+  [anon_sym_EQ_EQ] = anon_sym_EQ_EQ,
+  [anon_sym_BANG_EQ] = anon_sym_BANG_EQ,
+  [anon_sym_LPAREN] = anon_sym_LPAREN,
+  [anon_sym_RPAREN] = anon_sym_RPAREN,
+  [sym_source] = sym_source,
+  [sym__expression] = sym__expression,
+  [sym_not] = sym_not,
+  [sym_and] = sym_and,
+  [sym_or] = sym_or,
+  [sym_equal] = sym_equal,
+  [sym_not_equal] = sym_not_equal,
+  [sym_parenthesized] = sym_parenthesized,
+};
+
+static const TSSymbolMetadata ts_symbol_metadata[] = {
+  [ts_builtin_sym_end] = {
+    .visible = false,
+    .named = true,
+  },
+  [sym_identifier] = {
+    .visible = true,
+    .named = true,
+  },
+  [anon_sym_BANG] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_AMP_AMP] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_PIPE_PIPE] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_EQ_EQ] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_BANG_EQ] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_LPAREN] = {
+    .visible = true,
+    .named = false,
+  },
+  [anon_sym_RPAREN] = {
+    .visible = true,
+    .named = false,
+  },
+  [sym_source] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym__expression] = {
+    .visible = false,
+    .named = true,
+  },
+  [sym_not] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym_and] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym_or] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym_equal] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym_not_equal] = {
+    .visible = true,
+    .named = true,
+  },
+  [sym_parenthesized] = {
+    .visible = true,
+    .named = true,
+  },
+};
+
+enum {
+  field_expression = 1,
+  field_left = 2,
+  field_right = 3,
+};
+
+static const char *ts_field_names[] = {
+  [0] = NULL,
+  [field_expression] = "expression",
+  [field_left] = "left",
+  [field_right] = "right",
+};
+
+static const TSFieldMapSlice ts_field_map_slices[3] = {
+  [1] = {.index = 0, .length = 1},
+  [2] = {.index = 1, .length = 2},
+};
+
+static const TSFieldMapEntry ts_field_map_entries[] = {
+  [0] =
+    {field_expression, 1},
+  [1] =
+    {field_left, 0},
+    {field_right, 2},
+};
+
+static TSSymbol ts_alias_sequences[3][MAX_ALIAS_SEQUENCE_LENGTH] = {
+  [0] = {0},
+};
+
+static uint16_t ts_non_terminal_alias_map[] = {
+  0,
+};
+
+static bool ts_lex(TSLexer *lexer, TSStateId state) {
+  START_LEXER();
+  eof = lexer->eof(lexer);
+  switch (state) {
+    case 0:
+      if (eof) ADVANCE(7);
+      if (lookahead == '!') ADVANCE(10);
+      if (lookahead == '&') ADVANCE(2);
+      if (lookahead == '(') ADVANCE(15);
+      if (lookahead == ')') ADVANCE(16);
+      if (lookahead == '=') ADVANCE(4);
+      if (lookahead == '|') ADVANCE(5);
+      if (lookahead == '\t' ||
+          lookahead == '\n' ||
+          lookahead == '\r' ||
+          lookahead == ' ') SKIP(0)
+      if (lookahead == '-' ||
+          ('0' <= lookahead && lookahead <= '9') ||
+          ('A' <= lookahead && lookahead <= 'Z') ||
+          lookahead == '_' ||
+          ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
+      END_STATE();
+    case 1:
+      if (lookahead == '!') ADVANCE(9);
+      if (lookahead == '(') ADVANCE(15);
+      if (lookahead == '\t' ||
+          lookahead == '\n' ||
+          lookahead == '\r' ||
+          lookahead == ' ') SKIP(1)
+      if (lookahead == '-' ||
+          ('0' <= lookahead && lookahead <= '9') ||
+          ('A' <= lookahead && lookahead <= 'Z') ||
+          lookahead == '_' ||
+          ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
+      END_STATE();
+    case 2:
+      if (lookahead == '&') ADVANCE(11);
+      END_STATE();
+    case 3:
+      if (lookahead == '=') ADVANCE(14);
+      END_STATE();
+    case 4:
+      if (lookahead == '=') ADVANCE(13);
+      END_STATE();
+    case 5:
+      if (lookahead == '|') ADVANCE(12);
+      END_STATE();
+    case 6:
+      if (eof) ADVANCE(7);
+      if (lookahead == '!') ADVANCE(3);
+      if (lookahead == '&') ADVANCE(2);
+      if (lookahead == ')') ADVANCE(16);
+      if (lookahead == '=') ADVANCE(4);
+      if (lookahead == '|') ADVANCE(5);
+      if (lookahead == '\t' ||
+          lookahead == '\n' ||
+          lookahead == '\r' ||
+          lookahead == ' ') SKIP(6)
+      END_STATE();
+    case 7:
+      ACCEPT_TOKEN(ts_builtin_sym_end);
+      END_STATE();
+    case 8:
+      ACCEPT_TOKEN(sym_identifier);
+      if (lookahead == '-' ||
+          ('0' <= lookahead && lookahead <= '9') ||
+          ('A' <= lookahead && lookahead <= 'Z') ||
+          lookahead == '_' ||
+          ('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
+      END_STATE();
+    case 9:
+      ACCEPT_TOKEN(anon_sym_BANG);
+      END_STATE();
+    case 10:
+      ACCEPT_TOKEN(anon_sym_BANG);
+      if (lookahead == '=') ADVANCE(14);
+      END_STATE();
+    case 11:
+      ACCEPT_TOKEN(anon_sym_AMP_AMP);
+      END_STATE();
+    case 12:
+      ACCEPT_TOKEN(anon_sym_PIPE_PIPE);
+      END_STATE();
+    case 13:
+      ACCEPT_TOKEN(anon_sym_EQ_EQ);
+      END_STATE();
+    case 14:
+      ACCEPT_TOKEN(anon_sym_BANG_EQ);
+      END_STATE();
+    case 15:
+      ACCEPT_TOKEN(anon_sym_LPAREN);
+      END_STATE();
+    case 16:
+      ACCEPT_TOKEN(anon_sym_RPAREN);
+      END_STATE();
+    default:
+      return false;
+  }
+}
+
+static TSLexMode ts_lex_modes[STATE_COUNT] = {
+  [0] = {.lex_state = 0},
+  [1] = {.lex_state = 1},
+  [2] = {.lex_state = 1},
+  [3] = {.lex_state = 1},
+  [4] = {.lex_state = 1},
+  [5] = {.lex_state = 1},
+  [6] = {.lex_state = 6},
+  [7] = {.lex_state = 0},
+  [8] = {.lex_state = 0},
+  [9] = {.lex_state = 0},
+  [10] = {.lex_state = 0},
+  [11] = {.lex_state = 0},
+  [12] = {.lex_state = 0},
+  [13] = {.lex_state = 0},
+  [14] = {.lex_state = 0},
+  [15] = {.lex_state = 0},
+  [16] = {.lex_state = 0},
+  [17] = {.lex_state = 0},
+};
+
+static uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
+  [0] = {
+    [ts_builtin_sym_end] = ACTIONS(1),
+    [sym_identifier] = ACTIONS(1),
+    [anon_sym_BANG] = ACTIONS(1),
+    [anon_sym_AMP_AMP] = ACTIONS(1),
+    [anon_sym_PIPE_PIPE] = ACTIONS(1),
+    [anon_sym_EQ_EQ] = ACTIONS(1),
+    [anon_sym_BANG_EQ] = ACTIONS(1),
+    [anon_sym_LPAREN] = ACTIONS(1),
+    [anon_sym_RPAREN] = ACTIONS(1),
+  },
+  [1] = {
+    [sym_source] = STATE(15),
+    [sym__expression] = STATE(13),
+    [sym_not] = STATE(13),
+    [sym_and] = STATE(13),
+    [sym_or] = STATE(13),
+    [sym_equal] = STATE(13),
+    [sym_not_equal] = STATE(13),
+    [sym_parenthesized] = STATE(13),
+    [sym_identifier] = ACTIONS(3),
+    [anon_sym_BANG] = ACTIONS(5),
+    [anon_sym_LPAREN] = ACTIONS(7),
+  },
+  [2] = {
+    [sym__expression] = STATE(7),
+    [sym_not] = STATE(7),
+    [sym_and] = STATE(7),
+    [sym_or] = STATE(7),
+    [sym_equal] = STATE(7),
+    [sym_not_equal] = STATE(7),
+    [sym_parenthesized] = STATE(7),
+    [sym_identifier] = ACTIONS(3),
+    [anon_sym_BANG] = ACTIONS(5),
+    [anon_sym_LPAREN] = ACTIONS(7),
+  },
+  [3] = {
+    [sym__expression] = STATE(14),
+    [sym_not] = STATE(14),
+    [sym_and] = STATE(14),
+    [sym_or] = STATE(14),
+    [sym_equal] = STATE(14),
+    [sym_not_equal] = STATE(14),
+    [sym_parenthesized] = STATE(14),
+    [sym_identifier] = ACTIONS(3),
+    [anon_sym_BANG] = ACTIONS(5),
+    [anon_sym_LPAREN] = ACTIONS(7),
+  },
+  [4] = {
+    [sym__expression] = STATE(11),
+    [sym_not] = STATE(11),
+    [sym_and] = STATE(11),
+    [sym_or] = STATE(11),
+    [sym_equal] = STATE(11),
+    [sym_not_equal] = STATE(11),
+    [sym_parenthesized] = STATE(11),
+    [sym_identifier] = ACTIONS(3),
+    [anon_sym_BANG] = ACTIONS(5),
+    [anon_sym_LPAREN] = ACTIONS(7),
+  },
+  [5] = {
+    [sym__expression] = STATE(12),
+    [sym_not] = STATE(12),
+    [sym_and] = STATE(12),
+    [sym_or] = STATE(12),
+    [sym_equal] = STATE(12),
+    [sym_not_equal] = STATE(12),
+    [sym_parenthesized] = STATE(12),
+    [sym_identifier] = ACTIONS(3),
+    [anon_sym_BANG] = ACTIONS(5),
+    [anon_sym_LPAREN] = ACTIONS(7),
+  },
+};
+
+static uint16_t ts_small_parse_table[] = {
+  [0] = 3,
+    ACTIONS(11), 1,
+      anon_sym_EQ_EQ,
+    ACTIONS(13), 1,
+      anon_sym_BANG_EQ,
+    ACTIONS(9), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [13] = 1,
+    ACTIONS(15), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [20] = 1,
+    ACTIONS(17), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [27] = 1,
+    ACTIONS(19), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [34] = 1,
+    ACTIONS(21), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [41] = 1,
+    ACTIONS(23), 4,
+      ts_builtin_sym_end,
+      anon_sym_AMP_AMP,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [48] = 2,
+    ACTIONS(27), 1,
+      anon_sym_AMP_AMP,
+    ACTIONS(25), 3,
+      ts_builtin_sym_end,
+      anon_sym_PIPE_PIPE,
+      anon_sym_RPAREN,
+  [57] = 3,
+    ACTIONS(27), 1,
+      anon_sym_AMP_AMP,
+    ACTIONS(29), 1,
+      ts_builtin_sym_end,
+    ACTIONS(31), 1,
+      anon_sym_PIPE_PIPE,
+  [67] = 3,
+    ACTIONS(27), 1,
+      anon_sym_AMP_AMP,
+    ACTIONS(31), 1,
+      anon_sym_PIPE_PIPE,
+    ACTIONS(33), 1,
+      anon_sym_RPAREN,
+  [77] = 1,
+    ACTIONS(35), 1,
+      ts_builtin_sym_end,
+  [81] = 1,
+    ACTIONS(37), 1,
+      sym_identifier,
+  [85] = 1,
+    ACTIONS(39), 1,
+      sym_identifier,
+};
+
+static uint32_t ts_small_parse_table_map[] = {
+  [SMALL_STATE(6)] = 0,
+  [SMALL_STATE(7)] = 13,
+  [SMALL_STATE(8)] = 20,
+  [SMALL_STATE(9)] = 27,
+  [SMALL_STATE(10)] = 34,
+  [SMALL_STATE(11)] = 41,
+  [SMALL_STATE(12)] = 48,
+  [SMALL_STATE(13)] = 57,
+  [SMALL_STATE(14)] = 67,
+  [SMALL_STATE(15)] = 77,
+  [SMALL_STATE(16)] = 81,
+  [SMALL_STATE(17)] = 85,
+};
+
+static TSParseActionEntry ts_parse_actions[] = {
+  [0] = {.entry = {.count = 0, .reusable = false}},
+  [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(),
+  [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6),
+  [5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2),
+  [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3),
+  [9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__expression, 1),
+  [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16),
+  [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17),
+  [15] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not, 2, .production_id = 1),
+  [17] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equal, 3, .production_id = 2),
+  [19] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not_equal, 3, .production_id = 2),
+  [21] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesized, 3, .production_id = 1),
+  [23] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_and, 3, .production_id = 2),
+  [25] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_or, 3, .production_id = 2),
+  [27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4),
+  [29] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source, 1),
+  [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5),
+  [33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10),
+  [35] = {.entry = {.count = 1, .reusable = true}},  ACCEPT_INPUT(),
+  [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8),
+  [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9),
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef _WIN32
+#define extern __declspec(dllexport)
+#endif
+
+extern const TSLanguage *tree_sitter_context_predicate(void) {
+  static TSLanguage language = {
+    .version = LANGUAGE_VERSION,
+    .symbol_count = SYMBOL_COUNT,
+    .alias_count = ALIAS_COUNT,
+    .token_count = TOKEN_COUNT,
+    .external_token_count = EXTERNAL_TOKEN_COUNT,
+    .symbol_names = ts_symbol_names,
+    .symbol_metadata = ts_symbol_metadata,
+    .parse_table = (const uint16_t *)ts_parse_table,
+    .parse_actions = ts_parse_actions,
+    .lex_modes = ts_lex_modes,
+    .alias_sequences = (const TSSymbol *)ts_alias_sequences,
+    .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH,
+    .lex_fn = ts_lex,
+    .field_count = FIELD_COUNT,
+    .field_map_slices = (const TSFieldMapSlice *)ts_field_map_slices,
+    .field_map_entries = (const TSFieldMapEntry *)ts_field_map_entries,
+    .field_names = ts_field_names,
+    .large_state_count = LARGE_STATE_COUNT,
+    .small_parse_table = (const uint16_t *)ts_small_parse_table,
+    .small_parse_table_map = (const uint32_t *)ts_small_parse_table_map,
+    .public_symbol_map = ts_symbol_map,
+    .alias_map = ts_non_terminal_alias_map,
+    .state_count = STATE_COUNT,
+  };
+  return &language;
+}
+#ifdef __cplusplus
+}
+#endif

gpui/grammars/context-predicate/src/tree_sitter/parser.h 🔗

@@ -0,0 +1,238 @@
+#ifndef TREE_SITTER_PARSER_H_
+#define TREE_SITTER_PARSER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define ts_builtin_sym_error ((TSSymbol)-1)
+#define ts_builtin_sym_end 0
+#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
+
+#ifndef TREE_SITTER_API_H_
+typedef uint16_t TSSymbol;
+typedef uint16_t TSFieldId;
+typedef struct TSLanguage TSLanguage;
+#endif
+
+typedef struct {
+  TSFieldId field_id;
+  uint8_t child_index;
+  bool inherited;
+} TSFieldMapEntry;
+
+typedef struct {
+  uint16_t index;
+  uint16_t length;
+} TSFieldMapSlice;
+
+typedef uint16_t TSStateId;
+
+typedef struct {
+  bool visible : 1;
+  bool named : 1;
+  bool supertype: 1;
+} TSSymbolMetadata;
+
+typedef struct TSLexer TSLexer;
+
+struct TSLexer {
+  int32_t lookahead;
+  TSSymbol result_symbol;
+  void (*advance)(TSLexer *, bool);
+  void (*mark_end)(TSLexer *);
+  uint32_t (*get_column)(TSLexer *);
+  bool (*is_at_included_range_start)(const TSLexer *);
+  bool (*eof)(const TSLexer *);
+};
+
+typedef enum {
+  TSParseActionTypeShift,
+  TSParseActionTypeReduce,
+  TSParseActionTypeAccept,
+  TSParseActionTypeRecover,
+} TSParseActionType;
+
+typedef struct {
+  union {
+    struct {
+      TSStateId state;
+      bool extra : 1;
+      bool repetition : 1;
+    } shift;
+    struct {
+      TSSymbol symbol;
+      int16_t dynamic_precedence;
+      uint8_t child_count;
+      uint8_t production_id;
+    } reduce;
+  } params;
+  TSParseActionType type : 4;
+} TSParseAction;
+
+typedef struct {
+  uint16_t lex_state;
+  uint16_t external_lex_state;
+} TSLexMode;
+
+typedef union {
+  TSParseAction action;
+  struct {
+    uint8_t count;
+    bool reusable : 1;
+  } entry;
+} TSParseActionEntry;
+
+struct TSLanguage {
+  uint32_t version;
+  uint32_t symbol_count;
+  uint32_t alias_count;
+  uint32_t token_count;
+  uint32_t external_token_count;
+  const char **symbol_names;
+  const TSSymbolMetadata *symbol_metadata;
+  const uint16_t *parse_table;
+  const TSParseActionEntry *parse_actions;
+  const TSLexMode *lex_modes;
+  const TSSymbol *alias_sequences;
+  uint16_t max_alias_sequence_length;
+  bool (*lex_fn)(TSLexer *, TSStateId);
+  bool (*keyword_lex_fn)(TSLexer *, TSStateId);
+  TSSymbol keyword_capture_token;
+  struct {
+    const bool *states;
+    const TSSymbol *symbol_map;
+    void *(*create)(void);
+    void (*destroy)(void *);
+    bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
+    unsigned (*serialize)(void *, char *);
+    void (*deserialize)(void *, const char *, unsigned);
+  } external_scanner;
+  uint32_t field_count;
+  const TSFieldMapSlice *field_map_slices;
+  const TSFieldMapEntry *field_map_entries;
+  const char **field_names;
+  uint32_t large_state_count;
+  const uint16_t *small_parse_table;
+  const uint32_t *small_parse_table_map;
+  const TSSymbol *public_symbol_map;
+  const uint16_t *alias_map;
+  uint32_t state_count;
+};
+
+/*
+ *  Lexer Macros
+ */
+
+#define START_LEXER()           \
+  bool result = false;          \
+  bool skip = false;            \
+  bool eof = false;             \
+  int32_t lookahead;            \
+  goto start;                   \
+  next_state:                   \
+  lexer->advance(lexer, skip);  \
+  start:                        \
+  skip = false;                 \
+  lookahead = lexer->lookahead;
+
+#define ADVANCE(state_value) \
+  {                          \
+    state = state_value;     \
+    goto next_state;         \
+  }
+
+#define SKIP(state_value) \
+  {                       \
+    skip = true;          \
+    state = state_value;  \
+    goto next_state;      \
+  }
+
+#define ACCEPT_TOKEN(symbol_value)     \
+  result = true;                       \
+  lexer->result_symbol = symbol_value; \
+  lexer->mark_end(lexer);
+
+#define END_STATE() return result;
+
+/*
+ *  Parse Table Macros
+ */
+
+#define SMALL_STATE(id) id - LARGE_STATE_COUNT
+
+#define STATE(id) id
+
+#define ACTIONS(id) id
+
+#define SHIFT(state_value)                \
+  {                                       \
+    {                                     \
+      .params = {                         \
+        .shift = {                        \
+          .state = state_value            \
+        }                                 \
+      },                                  \
+      .type = TSParseActionTypeShift      \
+    }                                     \
+  }
+
+#define SHIFT_REPEAT(state_value)     \
+  {                                   \
+    {                                 \
+      .params = {                     \
+        .shift = {                    \
+          .state = state_value,       \
+          .repetition = true          \
+        }                             \
+      },                              \
+      .type = TSParseActionTypeShift  \
+    }                                 \
+  }
+
+#define RECOVER()                        \
+  {                                      \
+    { .type = TSParseActionTypeRecover } \
+  }
+
+#define SHIFT_EXTRA()                 \
+  {                                   \
+    {                                 \
+      .params = {                     \
+        .shift = {                    \
+          .extra = true               \
+        }                             \
+      },                              \
+      .type = TSParseActionTypeShift  \
+    }                                 \
+  }
+
+#define REDUCE(symbol_val, child_count_val, ...) \
+  {                                              \
+    {                                            \
+      .params = {                                \
+        .reduce = {                              \
+          .symbol = symbol_val,                  \
+          .child_count = child_count_val,        \
+          __VA_ARGS__                            \
+        },                                       \
+      },                                         \
+      .type = TSParseActionTypeReduce            \
+    }                                            \
+  }
+
+#define ACCEPT_INPUT()                  \
+  {                                     \
+    { .type = TSParseActionTypeAccept } \
+  }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // TREE_SITTER_PARSER_H_

gpui/src/keymap.rs 🔗

@@ -6,7 +6,7 @@ use std::{
 use tree_sitter::{Language, Node, Parser};
 
 extern "C" {
-    fn tree_sitter_zed_context_predicate() -> Language;
+    fn tree_sitter_context_predicate() -> Language;
 }
 
 pub struct Matcher {
@@ -247,7 +247,7 @@ impl Context {
 impl ContextPredicate {
     fn parse(source: &str) -> anyhow::Result<Self> {
         let mut parser = Parser::new();
-        let language = unsafe { tree_sitter_zed_context_predicate() };
+        let language = unsafe { tree_sitter_context_predicate() };
         parser.set_language(language).unwrap();
         let source = source.as_bytes();
         let tree = parser.parse(source, None).unwrap();