Skip to content

Commit 1642883

Browse files
committed
main
1 parent f5f7b6d commit 1642883

File tree

6 files changed

+266
-42
lines changed

6 files changed

+266
-42
lines changed

docs/document/Articles/docs/Duck Typing in CSharp.md

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Writing Treesitter Parser
2+
3+
## Treesitter CLI Util
4+
5+
## AST & CTS
6+
7+
- A tree only contains **named nodes** is a abstract syntax tree(AST)
8+
- A tree contains **both named and unnamed nodes** is a concrete syntax tree(CST)
9+
10+
## Grammar Structure
11+
12+
- `name`: name of that parser
13+
- `rules`: rules for generating nodes
14+
- see [doc](https://tree-sitter.github.io/tree-sitter/creating-parsers/2-the-grammar-dsl.html) for more properties of a grammar.
15+
16+
## Tree Structure
17+
18+
Treesitter syntax tree(and its query) is generally represented in scheme language, a lisp dialect.
19+
Each `()` initializes a new list, each element in the list is either presented as node type(named nodes) or string literal(unnamed nodes).
20+
The **node type** is name of rule that matched the section.
21+
22+
- **field** : Each element might have a *field name* such as `kind: "const"` to give the element(node) a **descriptive** name in context.
23+
- **token**: Each atomic node is considered as a token, such as `(number)` and `(comment)` in the example.
24+
25+
> [!NOTE]
26+
> A unnamed node could have *field name*, the field name is for node representation in tree, not the nominal identity of that node.
27+
28+
```query
29+
; generated tree for javascript code
30+
; const foo = 1 + 2 // this is foo
31+
(program ; [0, 0] - [1, 0]
32+
(lexical_declaration ; [0, 0] - [0, 18]
33+
kind: "const" ; [0, 0] - [0, 5]
34+
(variable_declarator ; [0, 6] - [0, 17]
35+
name: (identifier) ; [0, 6] - [0, 9]
36+
"=" ; [0, 10] - [0, 11]
37+
value: (binary_expression ; [0, 12] - [0, 17]
38+
left: (number) ; [0, 12] - [0, 13]
39+
operator: "+" ; [0, 14] - [0, 15]
40+
right: (number))) ; [0, 16] - [0, 17]
41+
";") ; [0, 17] - [0, 18]
42+
(comment)) ; [0, 19] - [0, 33]
43+
```
44+
45+
46+
47+
## Writing Rules
48+
49+
1. **The top level rule**: the most generic wrapper rule to cover all possible content to be parsed.
50+
- **top level rule MUST be the first rule property declared in `rules` field.**
51+
- the name of top level rule can be arbitrary, usually depend on language specification.
52+
- `C#` for example uses the `compilation_unit` as the name of top level rule.
53+
```js
54+
module.exports = grammar({
55+
name: 'c_sharp',
56+
rules: {
57+
/*...*/
58+
compilation_unit: $ => seq( // must be the first rule // [!code highlight]
59+
optional($.shebang_directive),
60+
repeat($._top_level_item),
61+
),
62+
_top_level_item: $ => prec(2, choice(
63+
$._top_level_item_no_statement,
64+
$.global_statement,
65+
)),
66+
/*...*/
67+
}
68+
});
69+
```
70+
71+
### Named & Unnamed Nodes
72+
73+
A node generated by a rule that was assigned to a property of `rules` is called a *named node*.
74+
A node generated by a rule that was written in literal string/regex is *unnamed nodes*.
75+
76+
```js
77+
module.exports = grammar({
78+
name: 'foo',
79+
rules: {
80+
if_statement: $ => seq("if", "(", $._expression, ")", $._statement);
81+
},
82+
});
83+
```
84+
85+
> [!NOTE]
86+
> Unnamed nodes are not visible from treesitter CST by default, but they does exist in the structure and can be inspected.
87+
> They just don't have a node type.
88+
89+
### Aliased Rule
90+
91+
92+
### Tokenized Rule
93+
94+
`token(rule)` made a complex rule as a **atomic** node, tree-sitter would only match but does not generate the concrete sub-tree for this node.
95+
The following rule would made comment as `(comment)` in concrete tree, it does not include the unnamed nodes match that pattern.
96+
97+
```js
98+
module.exports = grammar({
99+
name: 'foo',
100+
rules: {
101+
/* ... */
102+
comment: _ => token(choice(
103+
seq('//', /[^\n\r]*/),
104+
seq(
105+
'/*',
106+
/[^*]*\*+([^/*][^*]*\*+)*/,
107+
'/',
108+
),
109+
)),
110+
},
111+
});
112+
```
113+
114+
### Node Description
115+
116+
A field of node is a **descriptive name** for semantic of that node in certain context.
117+
118+
The following rule defines descriptive name for each node of that function node.
119+
120+
```js
121+
module.exports = grammar({
122+
name: 'foo',
123+
rules: {
124+
/* ... */
125+
function_definition: $ =>
126+
seq(
127+
"func",
128+
field("name", $.identifier),
129+
field("parameters", $.parameter_list),
130+
field("return_type", $._type),
131+
field("body", $.block),
132+
)
133+
},
134+
});
135+
```
136+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Duck Typing in CSharp
2+
3+
## **List Initializer**
4+
5+
Any type implemented `IEnumerable` and has a `Add(T item): void` method can use *list initializer* syntax.
6+
- `Add(T item): void` can be implemented as extension method
7+
- `ICollection` is more generally used to have *list initializer* enabled, because it's an extension of `IEnumerable` with `Add` method.
8+
9+
```cs
10+
_ = new FooCollection<int>() { 1, 2, 3 }; // [!code highlight]
11+
12+
class FooCollection<T> : IEnumerable<T> {
13+
public void Add(T item) { Console.WriteLine(item); } // [!code highlight]
14+
public IEnumerator<T> GetEnumerator() {
15+
throw new NotImplementedException();
16+
}
17+
IEnumerator IEnumerable.GetEnumerator() {
18+
return GetEnumerator();
19+
}
20+
}
21+
// or implement it as extension method
22+
static class Ext {
23+
public static void Add<T>(this FooCollection<T> self, T item) { } // [!code highlight]
24+
}
25+
```
26+
27+
## **Deconstruction**
28+
29+
```cs
30+
var (a, b) = new Foo(); // [!code highlight]
31+
32+
class Foo { };
33+
34+
static class FooExtension {
35+
public static void Deconstruct(this Foo self, out int a, out int b) { a = b = 1; } // [!code highlight]
36+
}
37+
```
38+
## **Iteration**
39+
40+
Any type with a `GetEnumerator` implementation can be iterated by `foreach` statement.
41+
- can be implemented as an extension method
42+
43+
```cs
44+
using System.Collections;
45+
46+
foreach (var _ in new FooIterable()) { } // [!code highlight]
47+
48+
class FooIterable { };
49+
50+
static class FooExtension {
51+
public static IEnumerator GetEnumerator(this FooIterable _) { // [!code highlight]
52+
for (int i = 0; i < 100; i++) // [!code highlight]
53+
yield return i; // [!code highlight]
54+
} // [!code highlight]
55+
}
56+
```

docs/document/Skill/PowerShell/docs/Language/Array.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Array
1+
# Collection
22

3-
## Creation
3+
## Array Creation
44

55
```ps1
66
$foo = 1,2,3
@@ -94,7 +94,7 @@ If the *end* is less than the *start*, the array counts down from *start* to *en
9494
5..-1 # 5 4 3 2 1 0 -1
9595
```
9696

97-
## Access Item
97+
## Item Accessor
9898

9999
Powershell allows indexer syntax to access one or more items at a time or use `Select-Object`.
100100

@@ -108,6 +108,24 @@ Powershell allows indexer syntax to access one or more items at a time or use `S
108108
> The default value of a array item is `$null`.
109109
> Since it's a dynamic language, there's no error raised when index is out of the range.
110110
111+
### Singular as Collection
112+
113+
Variables storing singular value are intrinsically collections in PowerShell, so you don't have to check on the length when an return might be singular or a collection.
114+
Value at index `0` is the value stored by variable itself, otherwise it returns `$null`.
115+
116+
```ps1
117+
$foo = 1
118+
$foo[0] # 1
119+
$foo[1] # $null
120+
121+
if (Get-Command foo -OutVariable exe) {
122+
# Get-Command might return one or more instances,
123+
# but we don't need to check on length.
124+
# everything is an collection!
125+
& $exe[0]
126+
}
127+
```
128+
111129
## Concatenation
112130

113131
Generates new array from two concatenated or with new item.

docs/document/Skill/PowerShell/docs/Language/Control Flow.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ gci `
2727
2828
> [!warning]
2929
> **A space is required before the backtick.**
30-
> **And no any chacracter is allowed after the backtick.**
30+
> **And no any character is allowed after the backtick.**
3131
3232
> [!TIP]
33-
> Stop using backticks! They're ugly! Use hashtable splatting instead.
33+
> Stop using backticks! They're ugly! Use HashTable splatting instead.
3434
>```ps1
3535
>$table = @{
3636
> Filter = '*.mp4';
@@ -43,7 +43,7 @@ gci `
4343
4444
### Trailing Piper
4545
46-
In multiple piping, we can use trailing `|` to indicate the new line, PowerShell regconizes these lines as a whole command piping.
46+
In multiple piping, we can use trailing `|` to indicate the new line, PowerShell recognizes these lines as a whole command piping.
4747
4848
```ps1
4949
gps |
@@ -53,7 +53,7 @@ gps |
5353
5454
### Leading Piper <Badge type="info" text="PowerShell 7+" />
5555

56-
Starting with PowerShell 7, `|` is allowed as the first non-space chacracter in a new line.
56+
Starting with PowerShell 7, `|` is allowed as the first non-space character in a new line.
5757

5858
```ps1
5959
gps | foreach CPU
@@ -127,17 +127,20 @@ It has a few different patterns available:
127127
- use `continue` to skip current enumeration
128128
```ps1
129129
switch (1, 2) {
130-
1 { continue } # I don't want to preceed with this value 1, next!
130+
1 { continue } # I don't want to proceed with this value 1, next!
131131
2 { "aha" }
132132
} # aha
133133
```
134134
135-
There's options available for `switch`(specifically for `string` macthing):
135+
There's options available for `switch`(specifically for `string` matching):
136136
- `-Exact`: the default option that matches the string by literal, can be elided
137137
- `-Regex`: match by regex condition
138138
- `-Wildcard`: match by wildcard condition
139139
- `-CaseSensetive`: case-sensitive matching, can be combined with any of other three options
140140
141+
> [!NOTE]
142+
> `-File` and `-Parallel` flag are not mentioned here because they're more specific to other topics.
143+
141144
### Constant Pattern
142145
143146
Constant pattern is specifically for numbers and strings.
@@ -277,3 +280,22 @@ if (Get-Command foo -ErrorAction SilentlyContinue -ErrorVariable err) {
277280
278281
> [!NOTE]
279282
> If you're not interested in error at all, you can use `-ErrorAction Ignore` which never even register err to variable.
283+
284+
## Named/Labeled Loop
285+
286+
Named loop allows you to break any parent level of loops including `for`, `foreach`, `while`, `do..until` and `switch`
287+
288+
```ps1
289+
:fileList foreach($path in $logs) {
290+
:logFile switch -Wildcard -File $path {
291+
'Error*' {
292+
break filelist # break the whole foreach loop labeled as fileList
293+
}
294+
'Warning*' {
295+
break logFile # redundant label break, simply use break
296+
}
297+
default {
298+
}
299+
}
300+
}
301+
```
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# File IO
2+
3+
## Line by Line
4+
5+
`Get-Content` is bad practice when the file is larger enough to process line by line, the memory might overflow during runtime.
6+
Using `.NET` class such as `FileStream` can be just fine but a little complicated. The most direct solution is using `switch -File` statement.
7+
A `switch` statement with `-File` flag enumerates the whole file line by line, each line was matched with given pattern, and such pattern can combine with other flags such as `-CaseSensitive`.
8+
You may use `break` to terminate the whole loop or `continue` to skip to next iteration.
9+
10+
```ps1
11+
switch -CaseSensitive -Wildcard -File ~/.local/state/nvim/lsp.log {
12+
'fsautocomplete' {
13+
if ($shouldSkip) { continue }
14+
$_ # current line
15+
}
16+
'ERROR' {
17+
break; # the whole switch is terminated
18+
}
19+
default {
20+
}
21+
}
22+
```
23+
24+
> [!NOTE]
25+
> There should not exist brackets around file name in `switch -File <filename>`

0 commit comments

Comments
 (0)