tree-sitter-bynk 0.243.0 → 0.290.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # tree-sitter-bynk
2
+
3
+ [![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)
4
+
5
+ The [tree-sitter](https://tree-sitter.github.io/tree-sitter/) grammar for the
6
+ [Bynk](https://github.com/accuser/bynk) DSL — the source of truth for editor
7
+ syntax highlighting (`queries/highlights.scm`, `injections.scm`) and the
8
+ structural shape [`vscode-bynk`](https://github.com/accuser/bynk/tree/main/vscode-bynk)
9
+ builds on.
10
+
11
+ This directory is **two things**:
12
+
13
+ - **The grammar** (`grammar.js`), published to npm as
14
+ [`tree-sitter-bynk`](https://www.npmjs.com/package/tree-sitter-bynk), with
15
+ generated Node and Rust bindings (`bindings/`). This is what editors and
16
+ `vscode-bynk` actually consume.
17
+ - **A Rust crate** (this `Cargo.toml`, wrapping `bindings/rust/`) that exists
18
+ for exactly one purpose: the cross-parser conformance test
19
+ (`tests/conformance.rs`), which parses Bynk source with this grammar and
20
+ diffs the accept/reject decision against the hand-written
21
+ [`bynk-syntax`](https://crates.io/crates/bynk-syntax) recursive-descent
22
+ parser — the only guard tying the editor grammar to the compiler's own.
23
+
24
+ > **Not a published Rust crate.** The Rust binding is `publish = false` and
25
+ > kept off the release workflows' crate list; only the grammar itself ships
26
+ > to npm.
27
+
28
+ The grammar deliberately stays **permissive** in the places where Bynk's type
29
+ checker would reject a program — semantic rules (type checking,
30
+ exhaustiveness, effect propagation, `given` matching) are left entirely to
31
+ the LSP (`bynk-lsp`), not encoded here.
32
+
33
+ ## Building
34
+
35
+ ```sh
36
+ npm install
37
+ npx tree-sitter generate
38
+ npx tree-sitter test
39
+ ```
40
+
41
+ The Rust binding builds as an ordinary workspace member (`cargo build -p
42
+ tree-sitter-bynk`); `bynk-syntax` does not depend on it, so the conformance
43
+ test's dev-dependency edge is cycle-free.
44
+
45
+ ## License
46
+
47
+ Licensed under either of [Apache-2.0](https://github.com/accuser/bynk/blob/main/LICENSE-APACHE) or
48
+ [MIT](https://github.com/accuser/bynk/blob/main/LICENSE-MIT) at your option.
package/grammar.js CHANGED
@@ -74,6 +74,13 @@ module.exports = grammar({
74
74
  // whether a matcher (`called`/`never`/`before`) or an ordinary continuation
75
75
  // (`(`, an operator, …) follows.
76
76
  [$.observation_expr, $._primary],
77
+ // v0.140: inside `agent_decl`, a `store` field's own trailing
78
+ // `@annotation`s are the same rule as the handler-position annotation
79
+ // prefix that can immediately follow the last store field — one token of
80
+ // `@` lookahead can't tell which one a run of annotations belongs to.
81
+ // Both parses are equivalent once the next `on`/`store`/handler-body
82
+ // token is seen, so GLR resolves it rather than the grammar needing to.
83
+ [$.store_field],
77
84
  ],
78
85
 
79
86
  rules: {
@@ -435,7 +442,16 @@ module.exports = grammar({
435
442
  "Positive",
436
443
  "NonEmpty",
437
444
  ),
438
- _pred_arg: ($) => choice($.number_literal, $.float_literal, $.string_literal),
445
+ // v0.21/v0.142 (ADR 0166): a refinement-bound number may be negated —
446
+ // `InRange(-1_000, 1_000_000)` — mirroring `parse_signed_num_literal`'s
447
+ // optional leading `-` (a string argument, `Matches`'s only shape, is
448
+ // never signed).
449
+ _pred_arg: ($) =>
450
+ choice(
451
+ seq(optional("-"), $.number_literal),
452
+ seq(optional("-"), $.float_literal),
453
+ $.string_literal,
454
+ ),
439
455
 
440
456
  _base_type: ($) => $.base_type,
441
457
  base_type: () =>
@@ -681,7 +697,10 @@ module.exports = grammar({
681
697
  // v0.142 (ADR 0166): the optional `limits { }` policy, likewise a
682
698
  // header-position `from http` concern restricted by the checker.
683
699
  optional(field("limits", $.limits_policy)),
684
- repeat($.handler),
700
+ // v0.140 (ADR 0163): a handler may carry one or more `@name(args)`
701
+ // annotations (`@cache(maxAge: 5.minutes)`, `@limit(maxBody: …)`) —
702
+ // the same shape `store_annotation` already gives store fields.
703
+ repeat(seq(repeat(field("annotation", $.store_annotation)), $.handler)),
685
704
  "}",
686
705
  ),
687
706
  // v0.131: `cors { <name>: <value>, … }`. `cors` is a contextual keyword (like
@@ -757,6 +776,7 @@ module.exports = grammar({
757
776
  field("event_type", $._type_ref),
758
777
  optional(field("pattern", $.event_pattern)),
759
778
  ")",
779
+ optional(field("schema_dispatch", $.schema_dispatch_clause)),
760
780
  ),
761
781
  ),
762
782
  ),
@@ -773,6 +793,22 @@ module.exports = grammar({
773
793
  "..",
774
794
  "}",
775
795
  ),
796
+ // Events track, slice 4 (spine #936): dispatch by the envelope's
797
+ // `schemaVersion`, parallel to the payload pattern above but written
798
+ // after the closing `)` (matching the design notes' own form) rather
799
+ // than nested inside it. Nested inside the `Events` choice arm, not a
800
+ // free-standing clause any protocol could carry — `via` on `http`/
801
+ // `cron`/`queue`/`websocket` is a syntax error, not a checker
802
+ // diagnostic. Literal only (v1 of this clause); a range pattern
803
+ // (`via schema(2..)`) is unbuilt grammar, left to a future slice.
804
+ schema_dispatch_clause: ($) =>
805
+ seq(
806
+ "via",
807
+ "schema",
808
+ "(",
809
+ field("version", seq(optional("-"), $.number_literal)),
810
+ ")",
811
+ ),
776
812
  event_pattern_field: ($) =>
777
813
  seq(
778
814
  field("name", $.identifier),
@@ -804,7 +840,13 @@ module.exports = grammar({
804
840
  // v0.81 (storage track): the agent's `store` fields (ADR 0108).
805
841
  repeat($.store_field),
806
842
  repeat(choice($.invariant_decl, $.transition_decl)),
807
- repeat($.handler),
843
+ // v0.140 (ADR 0163): handler-position annotations parse uniformly on
844
+ // agent handlers too; the checker (not the grammar) restricts which
845
+ // annotations apply to a non-HTTP handler. Only `on call` is a valid
846
+ // agent handler (`bynk.parse.handler_in_agent` rejects the rest) —
847
+ // protocol handlers (HTTP routes, cron, queue, WebSocket, events)
848
+ // belong on a `service`.
849
+ repeat(seq(repeat(field("annotation", $.store_annotation)), $.call_handler)),
808
850
  "}",
809
851
  ),
810
852
  // v0.80: an agent invariant — `invariant <name>: <predicate>`. Sits between
@@ -1333,8 +1375,12 @@ module.exports = grammar({
1333
1375
  optional(","),
1334
1376
  ),
1335
1377
  ),
1378
+ // v1 (#472) admits only a wildcard `_` as the refined inner form —
1379
+ // `parse_pattern_where_suffix` rejects anything else with
1380
+ // `bynk.parse.refined_pattern_inner` ("a refined pattern's inner form
1381
+ // must be `_` in this version"); binding a refined value is unbuilt.
1336
1382
  refined_pattern: ($) =>
1337
- seq(field("inner", $._pattern), "where", field("predicate", $.refinement)),
1383
+ seq(field("inner", $.wildcard_pattern), "where", field("predicate", $.refinement)),
1338
1384
 
1339
1385
  _pattern: ($) =>
1340
1386
  choice(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-bynk",
3
- "version": "0.243.0",
3
+ "version": "0.290.0",
4
4
  "description": "Tree-sitter grammar for the Bynk DSL (v0–v0.16).",
5
5
  "main": "bindings/node",
6
6
  "types": "bindings/node",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "prebuildify": "^6.0.0",
42
- "tree-sitter-cli": "^0.26.9"
42
+ "tree-sitter-cli": "^0.27.0"
43
43
  },
44
44
  "tree-sitter": [
45
45
  {
package/src/grammar.json CHANGED
@@ -1661,12 +1661,46 @@
1661
1661
  "type": "CHOICE",
1662
1662
  "members": [
1663
1663
  {
1664
- "type": "SYMBOL",
1665
- "name": "number_literal"
1664
+ "type": "SEQ",
1665
+ "members": [
1666
+ {
1667
+ "type": "CHOICE",
1668
+ "members": [
1669
+ {
1670
+ "type": "STRING",
1671
+ "value": "-"
1672
+ },
1673
+ {
1674
+ "type": "BLANK"
1675
+ }
1676
+ ]
1677
+ },
1678
+ {
1679
+ "type": "SYMBOL",
1680
+ "name": "number_literal"
1681
+ }
1682
+ ]
1666
1683
  },
1667
1684
  {
1668
- "type": "SYMBOL",
1669
- "name": "float_literal"
1685
+ "type": "SEQ",
1686
+ "members": [
1687
+ {
1688
+ "type": "CHOICE",
1689
+ "members": [
1690
+ {
1691
+ "type": "STRING",
1692
+ "value": "-"
1693
+ },
1694
+ {
1695
+ "type": "BLANK"
1696
+ }
1697
+ ]
1698
+ },
1699
+ {
1700
+ "type": "SYMBOL",
1701
+ "name": "float_literal"
1702
+ }
1703
+ ]
1670
1704
  },
1671
1705
  {
1672
1706
  "type": "SYMBOL",
@@ -2907,8 +2941,24 @@
2907
2941
  {
2908
2942
  "type": "REPEAT",
2909
2943
  "content": {
2910
- "type": "SYMBOL",
2911
- "name": "handler"
2944
+ "type": "SEQ",
2945
+ "members": [
2946
+ {
2947
+ "type": "REPEAT",
2948
+ "content": {
2949
+ "type": "FIELD",
2950
+ "name": "annotation",
2951
+ "content": {
2952
+ "type": "SYMBOL",
2953
+ "name": "store_annotation"
2954
+ }
2955
+ }
2956
+ },
2957
+ {
2958
+ "type": "SYMBOL",
2959
+ "name": "handler"
2960
+ }
2961
+ ]
2912
2962
  }
2913
2963
  },
2914
2964
  {
@@ -3261,6 +3311,22 @@
3261
3311
  {
3262
3312
  "type": "STRING",
3263
3313
  "value": ")"
3314
+ },
3315
+ {
3316
+ "type": "CHOICE",
3317
+ "members": [
3318
+ {
3319
+ "type": "FIELD",
3320
+ "name": "schema_dispatch",
3321
+ "content": {
3322
+ "type": "SYMBOL",
3323
+ "name": "schema_dispatch_clause"
3324
+ }
3325
+ },
3326
+ {
3327
+ "type": "BLANK"
3328
+ }
3329
+ ]
3264
3330
  }
3265
3331
  ]
3266
3332
  }
@@ -3305,6 +3371,52 @@
3305
3371
  }
3306
3372
  ]
3307
3373
  },
3374
+ "schema_dispatch_clause": {
3375
+ "type": "SEQ",
3376
+ "members": [
3377
+ {
3378
+ "type": "STRING",
3379
+ "value": "via"
3380
+ },
3381
+ {
3382
+ "type": "STRING",
3383
+ "value": "schema"
3384
+ },
3385
+ {
3386
+ "type": "STRING",
3387
+ "value": "("
3388
+ },
3389
+ {
3390
+ "type": "FIELD",
3391
+ "name": "version",
3392
+ "content": {
3393
+ "type": "SEQ",
3394
+ "members": [
3395
+ {
3396
+ "type": "CHOICE",
3397
+ "members": [
3398
+ {
3399
+ "type": "STRING",
3400
+ "value": "-"
3401
+ },
3402
+ {
3403
+ "type": "BLANK"
3404
+ }
3405
+ ]
3406
+ },
3407
+ {
3408
+ "type": "SYMBOL",
3409
+ "name": "number_literal"
3410
+ }
3411
+ ]
3412
+ }
3413
+ },
3414
+ {
3415
+ "type": "STRING",
3416
+ "value": ")"
3417
+ }
3418
+ ]
3419
+ },
3308
3420
  "event_pattern_field": {
3309
3421
  "type": "SEQ",
3310
3422
  "members": [
@@ -3455,8 +3567,24 @@
3455
3567
  {
3456
3568
  "type": "REPEAT",
3457
3569
  "content": {
3458
- "type": "SYMBOL",
3459
- "name": "handler"
3570
+ "type": "SEQ",
3571
+ "members": [
3572
+ {
3573
+ "type": "REPEAT",
3574
+ "content": {
3575
+ "type": "FIELD",
3576
+ "name": "annotation",
3577
+ "content": {
3578
+ "type": "SYMBOL",
3579
+ "name": "store_annotation"
3580
+ }
3581
+ }
3582
+ },
3583
+ {
3584
+ "type": "SYMBOL",
3585
+ "name": "call_handler"
3586
+ }
3587
+ ]
3460
3588
  }
3461
3589
  },
3462
3590
  {
@@ -6264,7 +6392,7 @@
6264
6392
  "name": "inner",
6265
6393
  "content": {
6266
6394
  "type": "SYMBOL",
6267
- "name": "_pattern"
6395
+ "name": "wildcard_pattern"
6268
6396
  }
6269
6397
  },
6270
6398
  {
@@ -8064,6 +8192,9 @@
8064
8192
  [
8065
8193
  "observation_expr",
8066
8194
  "_primary"
8195
+ ],
8196
+ [
8197
+ "store_field"
8067
8198
  ]
8068
8199
  ],
8069
8200
  "precedences": [],
@@ -287,6 +287,16 @@
287
287
  "type": "agent_decl",
288
288
  "named": true,
289
289
  "fields": {
290
+ "annotation": {
291
+ "multiple": true,
292
+ "required": false,
293
+ "types": [
294
+ {
295
+ "type": "store_annotation",
296
+ "named": true
297
+ }
298
+ ]
299
+ },
290
300
  "key": {
291
301
  "multiple": false,
292
302
  "required": true,
@@ -313,7 +323,7 @@
313
323
  "required": false,
314
324
  "types": [
315
325
  {
316
- "type": "handler",
326
+ "type": "call_handler",
317
327
  "named": true
318
328
  },
319
329
  {
@@ -7837,22 +7847,6 @@
7837
7847
  "multiple": false,
7838
7848
  "required": true,
7839
7849
  "types": [
7840
- {
7841
- "type": "literal_pattern",
7842
- "named": true
7843
- },
7844
- {
7845
- "type": "or_pattern",
7846
- "named": true
7847
- },
7848
- {
7849
- "type": "paren_pattern",
7850
- "named": true
7851
- },
7852
- {
7853
- "type": "variant_pattern",
7854
- "named": true
7855
- },
7856
7850
  {
7857
7851
  "type": "wildcard_pattern",
7858
7852
  "named": true
@@ -8062,6 +8056,26 @@
8062
8056
  }
8063
8057
  }
8064
8058
  },
8059
+ {
8060
+ "type": "schema_dispatch_clause",
8061
+ "named": true,
8062
+ "fields": {
8063
+ "version": {
8064
+ "multiple": true,
8065
+ "required": true,
8066
+ "types": [
8067
+ {
8068
+ "type": "-",
8069
+ "named": false
8070
+ },
8071
+ {
8072
+ "type": "number_literal",
8073
+ "named": true
8074
+ }
8075
+ ]
8076
+ }
8077
+ }
8078
+ },
8065
8079
  {
8066
8080
  "type": "scheme",
8067
8081
  "named": true,
@@ -8287,6 +8301,16 @@
8287
8301
  "type": "service_decl",
8288
8302
  "named": true,
8289
8303
  "fields": {
8304
+ "annotation": {
8305
+ "multiple": true,
8306
+ "required": false,
8307
+ "types": [
8308
+ {
8309
+ "type": "store_annotation",
8310
+ "named": true
8311
+ }
8312
+ ]
8313
+ },
8290
8314
  "cors": {
8291
8315
  "multiple": false,
8292
8316
  "required": false,
@@ -8494,6 +8518,16 @@
8494
8518
  "named": true
8495
8519
  }
8496
8520
  ]
8521
+ },
8522
+ "schema_dispatch": {
8523
+ "multiple": false,
8524
+ "required": false,
8525
+ "types": [
8526
+ {
8527
+ "type": "schema_dispatch_clause",
8528
+ "named": true
8529
+ }
8530
+ ]
8497
8531
  }
8498
8532
  }
8499
8533
  },
@@ -11351,6 +11385,10 @@
11351
11385
  "type": "schedule",
11352
11386
  "named": false
11353
11387
  },
11388
+ {
11389
+ "type": "schema",
11390
+ "named": false
11391
+ },
11354
11392
  {
11355
11393
  "type": "security",
11356
11394
  "named": false
@@ -11415,6 +11453,10 @@
11415
11453
  "type": "validation_error_type",
11416
11454
  "named": true
11417
11455
  },
11456
+ {
11457
+ "type": "via",
11458
+ "named": false
11459
+ },
11418
11460
  {
11419
11461
  "type": "websocket",
11420
11462
  "named": false