You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/advanced/custom-language.md
+4-4Lines changed: 4 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -100,9 +100,9 @@ You need to add a new entry under the `customLanguages` key with the name of you
100
100
ruleDirs: ["./rules"]
101
101
customLanguages:
102
102
mojo:
103
-
libraryPath: mojo.so# path to dynamic library
104
-
extensions: [mojo, 🔥]# file extensions for this language
105
-
expandoChar: _# optional char to replace $ in your pattern
103
+
libraryPath: mojo.so # path to dynamic library
104
+
extensions: [mojo, 🔥] # file extensions for this language
105
+
expandoChar: _ # optional char to replace $ in your pattern
106
106
```
107
107
108
108
The `libraryPath` property specifies the path to the dynamic library relative to the `sgconfig.yml` file or an absolute path. The `extensions` property specifies a list of file extensions for this language.
@@ -130,7 +130,7 @@ Or you can write a rule in yaml like this:
In this case, the `has` rule matches first and captures `$F` as `foo` since `foo()` is the first function call matching the pattern `$F()`. The later rule `function $F() { $$$ }` will only find the `foo` declaration instead of `recurse`.
@@ -208,8 +208,8 @@ For example, to match class field in JavaScript, a kind + pattern rule [will not
208
208
209
209
```yaml
210
210
# these are two separate rules
211
-
pattern: a = 123 # rule 1
212
-
kind: field_definition # rule 2
211
+
pattern: a = 123 # rule 1
212
+
kind: field_definition # rule 2
213
213
```
214
214
215
215
This is because pattern `a = 123` is parsed as [`assignment_expression`](/playground.html#eyJtb2RlIjoiUGF0Y2giLCJsYW5nIjoiamF2YXNjcmlwdCIsInF1ZXJ5IjoiYSA9IDEyMyIsInJld3JpdGUiOiIiLCJzdHJpY3RuZXNzIjoic21hcnQiLCJzZWxlY3RvciI6IiIsImNvbmZpZyI6IiIsInNvdXJjZSI6IiJ9). Pattern and kind are two separate rules. And using them together will match nothing because no AST will have both `assignment_expression` and `field_definition` kind at once.
@@ -219,8 +219,8 @@ Instead, you need to use pattern object to provide enough context code for the p
219
219
```yaml
220
220
# this is one single pattern rule!
221
221
pattern:
222
-
context: 'class A { a = 123 }' # provide full context code
223
-
selector: field_definition # select the effective pattern
222
+
context: "class A { a = 123 }" # provide full context code
223
+
selector: field_definition # select the effective pattern
224
224
```
225
225
226
226
Note the rule above is one single pattern rule, instead of two. The `context` field provides the full unambiguous code snippet of `class`. So the `a = 123` will be parsed as `field_definition`. The `selector` field then selects the `field_definition` node as the [effective pattern](/advanced/pattern-parse.html#steps-to-create-a-pattern) matcher.
Copy file name to clipboardExpand all lines: website/advanced/pattern-parse.md
+8-8Lines changed: 8 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,7 @@ Without other hints, ast-grep will parse it as labeled statement by default. To
103
103
104
104
```yaml
105
105
pattern:
106
-
context: '{ a: 123 }'
106
+
context: "{ a: 123 }"
107
107
selector: pair
108
108
```
109
109
@@ -155,8 +155,8 @@ Examples:
155
155
156
156
```yaml
157
157
program
158
-
expression_statement
159
-
number <--- effective node
158
+
expression_statement
159
+
number <--- effective node
160
160
```
161
161
162
162
See [Playground](/playground.html#eyJtb2RlIjoiUGF0Y2giLCJsYW5nIjoiamF2YXNjcmlwdCIsInF1ZXJ5IjoiMTIzIiwicmV3cml0ZSI6IiIsInN0cmljdG5lc3MiOiJzbWFydCIsInNlbGVjdG9yIjoiIiwiY29uZmlnIjoiIiwic291cmNlIjoiIn0=).
@@ -165,11 +165,11 @@ See [Playground](/playground.html#eyJtb2RlIjoiUGF0Y2giLCJsYW5nIjoiamF2YXNjcmlwdC
165
165
166
166
```yaml
167
167
program
168
-
expression_statement
169
-
call_expression <--- effective node
170
-
identifier
171
-
arguments
172
-
identifier
168
+
expression_statement
169
+
call_expression <--- effective node
170
+
identifier
171
+
arguments
172
+
identifier
173
173
```
174
174
175
175
See [Playground](/playground.html#eyJtb2RlIjoiUGF0Y2giLCJsYW5nIjoiamF2YXNjcmlwdCIsInF1ZXJ5IjoiZm9vKGJhcikiLCJyZXdyaXRlIjoiIiwic3RyaWN0bmVzcyI6InNtYXJ0Iiwic2VsZWN0b3IiOiJjYWxsX2V4cHJlc3Npb24iLCJjb25maWciOiIiLCJzb3VyY2UiOiIifQ==).
Copy file name to clipboardExpand all lines: website/blog/yaml-vs-dsl.md
+19-22Lines changed: 19 additions & 22 deletions
Original file line number
Diff line number
Diff line change
@@ -16,15 +16,13 @@ head:
16
16
- - meta
17
17
- property: og:description
18
18
content: YAML and DSL are two different approaches to configure rule in structural search. The question "which is better" is largely subjective.
19
-
20
19
---
21
20
22
21
# YAML vs DSL: comparison is subjective
23
22
24
23
As stated in the [tool comparison](/advanced/tool-comparison.html#gritql), YAML configuration and DSL (Domain Specific Language) are two different approaches to configure rules in structural search. The question "which is better" is largely subjective.
25
24
26
-
However, recently I have received some feedback that YAML is __objectively__ not as good as DSL, and I would like to clarify some points.
27
-
25
+
However, recently I have received some feedback that YAML is **objectively** not as good as DSL, and I would like to clarify some points.
28
26
29
27
The original argument is quoted as follows:
30
28
@@ -56,7 +54,6 @@ This argument is a [slippery slope fallacy](https://en.wikipedia.org/wiki/Slippe
56
54
57
55
Using one concept in your library, framework or tool does not imply that you have to design a whole new syntax for it. The similar comparison will be frontend frameworks. Some frameworks like React and Vue use [hook](https://react.dev/reference/react/hooks) or [signals](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob) to represent state changes. But using these building blocks does not grant the verdict to design a new language for your frontend framework. Even the most avant-garde company only introduces [new syntax](https://flow.org/en/docs/react/hook-syntax/) in JavaScript, not inventing a new language.
58
56
59
-
60
57
### Subjective opinion is not objective fact
61
58
62
59
> I think GritQL queries are significantly easier to read than ast-grep's mix of DSL of YAML.
@@ -88,9 +85,9 @@ Biome's DSL is a mix of several different paradigms: declarative, logic, and imp
88
85
}
89
86
```
90
87
91
-
*`$method('$message')` is a declarative pattern matching syntax.
92
-
*`where` and `<:` are related to [logic programming](https://en.wikipedia.org/wiki/Logic_programming#:~:text=Logic%20programming%20is%20a%20programming,solve%20problems%20in%20the%20domain.) paradigm, say, [Prolog](https://en.wikipedia.org/wiki/Prolog) or SQL.
93
-
*`if` is a typical imperative programming paradigm
88
+
-`$method('$message')` is a declarative pattern matching syntax.
89
+
-`where` and `<:` are related to [logic programming](https://en.wikipedia.org/wiki/Logic_programming#:~:text=Logic%20programming%20is%20a%20programming,solve%20problems%20in%20the%20domain.) paradigm, say, [Prolog](https://en.wikipedia.org/wiki/Prolog) or SQL.
90
+
-`if` is a typical imperative programming paradigm
94
91
95
92
The mixture of paradigms does not blend well. At least, in the eye of a programming language veteran, it is too messy for a DSL for linting or structural search. We are not designing a next-era programming language.
96
93
@@ -159,9 +156,9 @@ They all look like function calls, but they are not. See explanation below for t
159
156
160
157
These three concepts are very similar, but they have slightly different usage in the DSL.
161
158
162
-
*`pattern` is used in `<:` or somewhere else, I dunno, the doc does not explain it well.
163
-
*`predicate` is used in `where` condition.
164
-
*`function` is used in `assignment`, `insertion` or `rewrite`.
159
+
-`pattern` is used in `<:` or somewhere else, I dunno, the doc does not explain it well.
160
+
-`predicate` is used in `where` condition.
161
+
-`function` is used in `assignment`, `insertion` or `rewrite`.
165
162
166
163
Example:
167
164
@@ -189,19 +186,19 @@ If you still have patience, you need one last thing to learn: variable scope.
189
186
190
187
I have no better explanation for it since I don't understand it well, so I will quote the [official documentation](https://docs.grit.io/language/bubble):
191
188
192
-
> Once a metavariable is bound to a value, it retains this value throughout the target code. Therefore, the scope of the metavariable spans the entire target file.
189
+
> Once a metavariable is bound to a value, it retains this value throughout the target code. Therefore, the scope of the metavariable spans the entire target file.
193
190
194
191
To fully understand it, you also need to know `bubble`, `bubble($argument)` and pattern auto wrap.
195
192
196
193
## What can go even more wrong?
197
194
198
195
Integrating a custom linting rule from another parser ecosystem to your own has several more decisions to make. Making bad decisions can lead to even more confusion.
199
196
200
-
* Your pattern syntax includes non standard syntax, like `$...`. You need to [change your parser](https://github.com/biomejs/biome/blob/31e439674493da76e0ce213e5660be3d903efbef/crates/biome_js_parser/src/syntax/jsx/mod.rs#L321) to support it.
201
-
* You need to make a decision if you want to support existing pattern libraries. But these patterns are built upon [tree-sitter](https://tree-sitter.github.io/tree-sitter/). So you have to [map tree-sitter AST to your own](https://github.com/biomejs/biome/blob/7bf9a608e1592fd595f658f5f800e12d51835d34/crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs#L42-L55)
202
-
* Even worse, if you chose to support existing pattern libraries, you also need to work on a general algorithm to handle incompatibility between different ASTs. For example, different AST structures, different node names, different node properties, etc.
203
-
* If you only supports part of it, how can you teach your users what is supported and what is not, without [reading the source](https://github.com/biomejs/biome/blob/7bf9a608e1592fd595f658f5f800e12d51835d34/crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs#L48-L50)?
204
-
* You also need to update your playground or editor plugins to support mapping between tree-sitter AST and your own AST. And teach users to use it.
197
+
- Your pattern syntax includes non standard syntax, like `$...`. You need to [change your parser](https://github.com/biomejs/biome/blob/31e439674493da76e0ce213e5660be3d903efbef/crates/biome_js_parser/src/syntax/jsx/mod.rs#L321) to support it.
198
+
- You need to make a decision if you want to support existing pattern libraries. But these patterns are built upon [tree-sitter](https://tree-sitter.github.io/tree-sitter/). So you have to [map tree-sitter AST to your own](https://github.com/biomejs/biome/blob/7bf9a608e1592fd595f658f5f800e12d51835d34/crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs#L42-L55)
199
+
- Even worse, if you chose to support existing pattern libraries, you also need to work on a general algorithm to handle incompatibility between different ASTs. For example, different AST structures, different node names, different node properties, etc.
200
+
- If you only supports part of it, how can you teach your users what is supported and what is not, without [reading the source](https://github.com/biomejs/biome/blob/7bf9a608e1592fd595f658f5f800e12d51835d34/crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs#L48-L50)?
201
+
- You also need to update your playground or editor plugins to support mapping between tree-sitter AST and your own AST. And teach users to use it.
205
202
206
203
## Conclusion
207
204
@@ -213,11 +210,11 @@ If you are a library or framework author, you can make decision based on your ow
213
210
214
211
Consider these points when you want to have objective comparison:
215
212
216
-
* Documentation?
217
-
* User Education? Howe you teach users to write your DSL?
218
-
* Tooling support like [playground](/playground.html).
219
-
* Editor support beyong syntax highlighting. Say LSP.
220
-
* Integration with API, how you bring type-safe DSL into your general purpose programming language, like [graphql](https://github.com/Quramy/ts-graphql-plugin) and [styled component](https://github.com/styled-components/typescript-styled-plugin).
221
-
* Broader ecosystem support, such as GitHub language detection, AI support, etc.
213
+
- Documentation?
214
+
- User Education? Howe you teach users to write your DSL?
215
+
- Tooling support like [playground](/playground.html).
216
+
- Editor support beyong syntax highlighting. Say LSP.
217
+
- Integration with API, how you bring type-safe DSL into your general purpose programming language, like [graphql](https://github.com/Quramy/ts-graphql-plugin) and [styled component](https://github.com/styled-components/typescript-styled-plugin).
218
+
- Broader ecosystem support, such as GitHub language detection, AI support, etc.
222
219
223
220
If you are going to use native tooling in your JavaScript/TypeScript project, I recommend you to use [oxlint](https://oxc.rs/) and, if you need simple custom rules, [ast-grep](https://ast-grep.github.io/).
0 commit comments