Skip to content

Commit

Permalink
doc: add match function call in C
Browse files Browse the repository at this point in the history
  • Loading branch information
HerringtonDarkholme committed Jul 1, 2024
1 parent 04f66a7 commit b0f38d0
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
1 change: 1 addition & 0 deletions website/catalog/c/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

This page curates a list of example ast-grep rules to check and to rewrite C code.

<!--@include: ./match-function-call.md-->
<!--@include: ./rewrite-method-to-function-call.md-->
<!--@include: ./yoda-condition.md-->
47 changes: 47 additions & 0 deletions website/catalog/c/match-function-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Match Function Call in C

* [Playground Link](/playground.html#eyJtb2RlIjoiQ29uZmlnIiwibGFuZyI6ImMiLCJxdWVyeSI6InRlc3QoJCQkKSIsInJld3JpdGUiOiIiLCJjb25maWciOiJydWxlOlxuICBwYXR0ZXJuOiBcbiAgICBjb250ZXh0OiAkTSgkJCQpO1xuICAgIHNlbGVjdG9yOiBjYWxsX2V4cHJlc3Npb24iLCJzb3VyY2UiOiIjZGVmaW5lIHRlc3QoeCkgKDIqeClcbmludCBhID0gdGVzdCgyKTtcbmludCBtYWluKCl7XG4gICAgaW50IGIgPSB0ZXN0KDIpO1xufSJ9)

### Description

One of the common questions of ast-grep is to match function calls in C.

A plain pattern like `test($A)` will not work. This is because [tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c)
parse the code snippet into `macro_type_specifier`, see the [pattern output](https://ast-grep.github.io/playground.html#eyJtb2RlIjoiUGF0Y2giLCJsYW5nIjoiYyIsInF1ZXJ5IjoidGVzdCgkJCQpIiwicmV3cml0ZSI6IiIsImNvbmZpZyI6InJ1bGU6XG4gIHBhdHRlcm46IFxuICAgIGNvbnRleHQ6ICRNKCQkJCk7XG4gICAgc2VsZWN0b3I6IGNhbGxfZXhwcmVzc2lvbiIsInNvdXJjZSI6IiNkZWZpbmUgdGVzdCh4KSAoMip4KVxuaW50IGEgPSB0ZXN0KDIpO1xuaW50IG1haW4oKXtcbiAgICBpbnQgYiA9IHRlc3QoMik7XG59In0=).

To avoid this ambiguity, ast-grep lets us write a [contextual pattern](/guide/rule-config/atomic-rule.html#pattern), which is a pattern inside a larger code snippet.
We can use `context` to write a pattern like this: `test($A);`. Then, we can use the selector `call_expression` to match only function calls.

### YAML

```yaml
id: match-function-call
language: c
rule:
pattern:
context: $M($$$);
selector: call_expression
```
### Example
<!-- highlight matched code in curly-brace {lineNum} -->
```c{2,4}
#define test(x) (2*x)
int a = test(2);
int main(){
int b = test(2);
}
```

### Caveat

Note, tree-sitter-c parses code differently when it receives code fragment. For example,

* `test(a)` is parsed as `macro_type_specifier`
* `test(a);` is parsed as `expression_statement -> call_expression`
* `int b = test(a)` is parsed as `declaration -> init_declarator -> call_expression`

The behavior is controlled by how the tree-sitter parser is written. And tree-sitter-c behaves differently from [tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp).

Please file issues on tree-sitter-c repo if you want to change the behavior. ast-grep will respect changes and decision from upstream authors.
1 change: 1 addition & 0 deletions website/catalog/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Explore the power of ast-grep with these rewriting rules that can transform your
Feel free to join our [Discord](https://discord.gg/4YZjf6htSQ) channel and ask @ast-grep-bot to explain the rules for you line by line!

* [C](/catalog/c/)
* [Match Function Call](/catalog/c/#match-function-call)
* [Rewrite Method to Function Call](/catalog/c/#rewrite-method-to-function-call)
* [Rewrite Check to Yoda Condition](/catalog/c/#rewrite-check-to-yoda-condition)
* [Go](/catalog/go/)
Expand Down

0 comments on commit b0f38d0

Please sign in to comment.