plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


e832171 — Peter John 2022-11-07T01:04:41+05:30
intitial commit

Generated files not shown: src/parser.c

.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ /src/** linguist-vendored
2
+ /examples/* linguist-vendored
.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ Cargo.lock
2
+ package-lock.json
3
+ node_modules
4
+ build
5
+ *.log
6
+ /examples/*/
7
+ /target/
.npmignore ADDED
@@ -0,0 +1,6 @@
1
+ corpus
2
+ examples
3
+ build
4
+ script
5
+ target
6
+ bindings/rust
Cargo.toml ADDED
@@ -0,0 +1,26 @@
1
+ [package]
2
+ name = "tree-sitter-pine"
3
+ description = "pine grammar for the tree-sitter parsing library"
4
+ version = "0.0.1"
5
+ keywords = ["incremental", "parsing", "pine"]
6
+ categories = ["parsing", "text-editors"]
7
+ repository = "https://github.com/tree-sitter/tree-sitter-pine"
8
+ edition = "2018"
9
+ license = "MIT"
10
+
11
+ build = "bindings/rust/build.rs"
12
+ include = [
13
+ "bindings/rust/*",
14
+ "grammar.js",
15
+ "queries/*",
16
+ "src/*",
17
+ ]
18
+
19
+ [lib]
20
+ path = "bindings/rust/lib.rs"
21
+
22
+ [dependencies]
23
+ tree-sitter = "~0.20"
24
+
25
+ [build-dependencies]
26
+ cc = "1.0"
binding.gyp ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "tree_sitter_pine_binding",
5
+ "include_dirs": [
6
+ "<!(node -e \"require('nan')\")",
7
+ "src"
8
+ ],
9
+ "sources": [
10
+ "bindings/node/binding.cc",
11
+ "src/parser.c",
12
+ "src/scanner.cc",
13
+ ],
14
+ "cflags_c": [
15
+ "-std=c99",
16
+ ]
17
+ }
18
+ ]
19
+ }
bindings/node/binding.cc ADDED
@@ -0,0 +1,28 @@
1
+ #include "tree_sitter/parser.h"
2
+ #include <node.h>
3
+ #include "nan.h"
4
+
5
+ using namespace v8;
6
+
7
+ extern "C" TSLanguage * tree_sitter_pine();
8
+
9
+ namespace {
10
+
11
+ NAN_METHOD(New) {}
12
+
13
+ void Init(Local<Object> exports, Local<Object> module) {
14
+ Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
15
+ tpl->SetClassName(Nan::New("Language").ToLocalChecked());
16
+ tpl->InstanceTemplate()->SetInternalFieldCount(1);
17
+
18
+ Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
19
+ Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
20
+ Nan::SetInternalFieldPointer(instance, 0, tree_sitter_pine());
21
+
22
+ Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("pine").ToLocalChecked());
23
+ Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
24
+ }
25
+
26
+ NODE_MODULE(tree_sitter_pine_binding, Init)
27
+
28
+ } // namespace
bindings/node/index.js ADDED
@@ -0,0 +1,19 @@
1
+ try {
2
+ module.exports = require("../../build/Release/tree_sitter_pine_binding");
3
+ } catch (error1) {
4
+ if (error1.code !== 'MODULE_NOT_FOUND') {
5
+ throw error1;
6
+ }
7
+ try {
8
+ module.exports = require("../../build/Debug/tree_sitter_pine_binding");
9
+ } catch (error2) {
10
+ if (error2.code !== 'MODULE_NOT_FOUND') {
11
+ throw error2;
12
+ }
13
+ throw error1
14
+ }
15
+ }
16
+
17
+ try {
18
+ module.exports.nodeTypeInfo = require("../../src/node-types.json");
19
+ } catch (_) {}
bindings/rust/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # tree-sitter-python
2
+
3
+ This crate provides a Python grammar for the [tree-sitter][] parsing library.
4
+ To use this crate, add it to the `[dependencies]` section of your `Cargo.toml`
5
+ file. (Note that you will probably also need to depend on the
6
+ [`tree-sitter`][tree-sitter crate] crate to use the parsed result in any useful
7
+ way.)
8
+
9
+ ``` toml
10
+ [dependencies]
11
+ tree-sitter = "0.17"
12
+ tree-sitter-python = "0.17"
13
+ ```
14
+
15
+ Typically, you will use the [language][language func] function to add this
16
+ grammar to a tree-sitter [Parser][], and then use the parser to parse some code:
17
+
18
+ ``` rust
19
+ let code = r#"
20
+ def double(x):
21
+ return x * 2
22
+ "#;
23
+ let mut parser = Parser::new();
24
+ parser.set_language(tree_sitter_python::language()).expect("Error loading Python grammar");
25
+ let parsed = parser.parse(code, None);
26
+ ```
27
+
28
+ If you have any questions, please reach out to us in the [tree-sitter
29
+ discussions] page.
30
+
31
+ [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
32
+ [language func]: https://docs.rs/tree-sitter-python/*/tree_sitter_python/fn.language.html
33
+ [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
34
+ [tree-sitter]: https://tree-sitter.github.io/
35
+ [tree-sitter crate]: https://crates.io/crates/tree-sitter
36
+ [tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions
bindings/rust/build.rs ADDED
@@ -0,0 +1,28 @@
1
+ use std::path::Path;
2
+ extern crate cc;
3
+
4
+ fn main() {
5
+ let src_dir = Path::new("src");
6
+
7
+ let mut c_config = cc::Build::new();
8
+ c_config.include(&src_dir);
9
+ c_config
10
+ .flag_if_supported("-Wno-unused-parameter")
11
+ .flag_if_supported("-Wno-unused-but-set-variable")
12
+ .flag_if_supported("-Wno-trigraphs");
13
+ let parser_path = src_dir.join("parser.c");
14
+ c_config.file(&parser_path);
15
+ println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
16
+ c_config.compile("parser");
17
+
18
+ let mut cpp_config = cc::Build::new();
19
+ cpp_config.cpp(true);
20
+ cpp_config.include(&src_dir);
21
+ cpp_config
22
+ .flag_if_supported("-Wno-unused-parameter")
23
+ .flag_if_supported("-Wno-unused-but-set-variable");
24
+ let scanner_path = src_dir.join("scanner.cc");
25
+ cpp_config.file(&scanner_path);
26
+ println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
27
+ cpp_config.compile("scanner");
28
+ }
bindings/rust/lib.rs ADDED
@@ -0,0 +1,68 @@
1
+ // -*- coding: utf-8 -*-
2
+ // ------------------------------------------------------------------------------------------------
3
+ // Copyright © 2020, tree-sitter-python authors.
4
+ // See the LICENSE file in this repo for license details.
5
+ // ------------------------------------------------------------------------------------------------
6
+
7
+ //! This crate provides a Python grammar for the [tree-sitter][] parsing library.
8
+ //!
9
+ //! Typically, you will use the [language][language func] function to add this grammar to a
10
+ //! tree-sitter [Parser][], and then use the parser to parse some code:
11
+ //!
12
+ //! ```
13
+ //! use tree_sitter::Parser;
14
+ //!
15
+ //! let code = r#"
16
+ //! def double(x):
17
+ //! return x * 2
18
+ //! "#;
19
+ //! let mut parser = Parser::new();
20
+ //! parser.set_language(tree_sitter_python::language()).expect("Error loading Python grammar");
21
+ //! let parsed = parser.parse(code, None);
22
+ //! # let parsed = parsed.unwrap();
23
+ //! # let root = parsed.root_node();
24
+ //! # assert!(!root.has_error());
25
+ //! ```
26
+ //!
27
+ //! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
28
+ //! [language func]: fn.language.html
29
+ //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
30
+ //! [tree-sitter]: https://tree-sitter.github.io/
31
+
32
+ use tree_sitter::Language;
33
+
34
+ extern "C" {
35
+ fn tree_sitter_python() -> Language;
36
+ }
37
+
38
+ /// Returns the tree-sitter [Language][] for this grammar.
39
+ ///
40
+ /// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
41
+ pub fn language() -> Language {
42
+ unsafe { tree_sitter_python() }
43
+ }
44
+
45
+ /// The source of the Python tree-sitter grammar description.
46
+ pub const GRAMMAR: &'static str = include_str!("../../grammar.js");
47
+
48
+ /// The syntax highlighting query for this language.
49
+ pub const HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights.scm");
50
+
51
+ /// The content of the [`node-types.json`][] file for this grammar.
52
+ ///
53
+ /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
54
+ pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
55
+
56
+ /// The symbol tagging query for this language.
57
+ pub const TAGGING_QUERY: &'static str = include_str!("../../queries/tags.scm");
58
+
59
+ #[cfg(test)]
60
+ mod tests {
61
+ #[test]
62
+ fn can_load_grammar() {
63
+ let mut parser = tree_sitter::Parser::new();
64
+ parser
65
+ .set_language(super::language())
66
+ .expect("Error loading Python grammar");
67
+ }
68
+ }
grammar.js ADDED
@@ -0,0 +1,77 @@
1
+ module.exports = grammar({
2
+ name: 'pine',
3
+ externals: $ => [
4
+ $._newline,
5
+ $._indent,
6
+ $._dedent,
7
+ $._string_start,
8
+ $._string_content,
9
+ $._string_end,
10
+
11
+ // Mark comments as external tokens so that the external scanner is always
12
+ // invoked, even if no external token is expected. This allows for better
13
+ // error recovery, because the external scanner can maintain the overall
14
+ // structure by returning dedent tokens whenever a dedent occurs, even
15
+ // if no dedent is expected.
16
+ $.comment,
17
+
18
+ // Allow the external scanner to check for the validity of closing brackets
19
+ // so that it can avoid returning dedent tokens between brackets.
20
+ ']',
21
+ ')',
22
+ '}',
23
+ ],
24
+ rules: {
25
+ module: $ => repeat($._definitions),
26
+
27
+ _definitions: $ => choice(
28
+ $.import_statement,
29
+ $.class_definition,
30
+ ),
31
+
32
+ import_statement: $ => seq(
33
+ 'import',
34
+ commaSep1(field('name', sep1($.identifier, '/')))
35
+ ),
36
+
37
+ class_definition: $ => seq(
38
+ 'class',
39
+ field('name', $.identifier),
40
+ field('generics', optional($.generic_list)),
41
+ field('traits', optional($.trait_list)),
42
+ ':',
43
+ field('fields', seq($._indent, seq(
44
+ repeat($.type_pair),
45
+ $._dedent
46
+ ))),
47
+ ),
48
+
49
+ trait_list: $ => seq(
50
+ '(',
51
+ commaSep1($.identifier),
52
+ ')'
53
+ ),
54
+
55
+ generic_list: $ => seq(
56
+ '<',
57
+ commaSep1($.identifier),
58
+ '>'
59
+ ),
60
+
61
+ type_pair: $ => seq(
62
+ field('key', $.identifier),
63
+ ':',
64
+ field('value', $.identifier)
65
+ ),
66
+
67
+ identifier: $ => /[_\p{XID_Start}][_\p{XID_Continue}]*/,
68
+ }
69
+ });
70
+
71
+ function commaSep1(rule) {
72
+ return sep1(rule, ',')
73
+ }
74
+
75
+ function sep1(rule, separator) {
76
+ return seq(rule, repeat(seq(separator, rule)))
77
+ }
package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "tree-sitter-pine",
3
+ "version": "1.0.0",
4
+ "main": "bindings/node",
5
+ "description": "Pine grammar for tree-sitter",
6
+ "scripts": {
7
+ "build": "tree-sitter generate && node-gyp build",
8
+ "test": "tree-sitter test && script/parse-examples",
9
+ "parse": "tree-sitter parse",
10
+ "test-windows": "tree-sitter test"
11
+ },
12
+ "author": "pyrossh",
13
+ "license": "MIT",
14
+ "keywords": [
15
+ "parser",
16
+ "lexer",
17
+ "pine"
18
+ ],
19
+ "dependencies": {
20
+ "nan": "^2.17.0"
21
+ },
22
+ "devDependencies": {
23
+ "tree-sitter-cli": "^0.20.7"
24
+ },
25
+ "repository": "https://github.com/pyrossh/tree-sitter-pine",
26
+ "tree-sitter": [
27
+ {
28
+ "scope": "source.pine",
29
+ "file-types": [
30
+ "pi"
31
+ ]
32
+ }
33
+ ]
34
+ }
src/grammar.json ADDED
@@ -0,0 +1,349 @@
1
+ {
2
+ "name": "pine",
3
+ "rules": {
4
+ "module": {
5
+ "type": "REPEAT",
6
+ "content": {
7
+ "type": "SYMBOL",
8
+ "name": "_definitions"
9
+ }
10
+ },
11
+ "_definitions": {
12
+ "type": "CHOICE",
13
+ "members": [
14
+ {
15
+ "type": "SYMBOL",
16
+ "name": "import_statement"
17
+ },
18
+ {
19
+ "type": "SYMBOL",
20
+ "name": "class_definition"
21
+ }
22
+ ]
23
+ },
24
+ "import_statement": {
25
+ "type": "SEQ",
26
+ "members": [
27
+ {
28
+ "type": "STRING",
29
+ "value": "import"
30
+ },
31
+ {
32
+ "type": "SEQ",
33
+ "members": [
34
+ {
35
+ "type": "FIELD",
36
+ "name": "name",
37
+ "content": {
38
+ "type": "SEQ",
39
+ "members": [
40
+ {
41
+ "type": "SYMBOL",
42
+ "name": "identifier"
43
+ },
44
+ {
45
+ "type": "REPEAT",
46
+ "content": {
47
+ "type": "SEQ",
48
+ "members": [
49
+ {
50
+ "type": "STRING",
51
+ "value": "/"
52
+ },
53
+ {
54
+ "type": "SYMBOL",
55
+ "name": "identifier"
56
+ }
57
+ ]
58
+ }
59
+ }
60
+ ]
61
+ }
62
+ },
63
+ {
64
+ "type": "REPEAT",
65
+ "content": {
66
+ "type": "SEQ",
67
+ "members": [
68
+ {
69
+ "type": "STRING",
70
+ "value": ","
71
+ },
72
+ {
73
+ "type": "FIELD",
74
+ "name": "name",
75
+ "content": {
76
+ "type": "SEQ",
77
+ "members": [
78
+ {
79
+ "type": "SYMBOL",
80
+ "name": "identifier"
81
+ },
82
+ {
83
+ "type": "REPEAT",
84
+ "content": {
85
+ "type": "SEQ",
86
+ "members": [
87
+ {
88
+ "type": "STRING",
89
+ "value": "/"
90
+ },
91
+ {
92
+ "type": "SYMBOL",
93
+ "name": "identifier"
94
+ }
95
+ ]
96
+ }
97
+ }
98
+ ]
99
+ }
100
+ }
101
+ ]
102
+ }
103
+ }
104
+ ]
105
+ }
106
+ ]
107
+ },
108
+ "class_definition": {
109
+ "type": "SEQ",
110
+ "members": [
111
+ {
112
+ "type": "STRING",
113
+ "value": "class"
114
+ },
115
+ {
116
+ "type": "FIELD",
117
+ "name": "name",
118
+ "content": {
119
+ "type": "SYMBOL",
120
+ "name": "identifier"
121
+ }
122
+ },
123
+ {
124
+ "type": "FIELD",
125
+ "name": "generics",
126
+ "content": {
127
+ "type": "CHOICE",
128
+ "members": [
129
+ {
130
+ "type": "SYMBOL",
131
+ "name": "generic_list"
132
+ },
133
+ {
134
+ "type": "BLANK"
135
+ }
136
+ ]
137
+ }
138
+ },
139
+ {
140
+ "type": "FIELD",
141
+ "name": "traits",
142
+ "content": {
143
+ "type": "CHOICE",
144
+ "members": [
145
+ {
146
+ "type": "SYMBOL",
147
+ "name": "trait_list"
148
+ },
149
+ {
150
+ "type": "BLANK"
151
+ }
152
+ ]
153
+ }
154
+ },
155
+ {
156
+ "type": "STRING",
157
+ "value": ":"
158
+ },
159
+ {
160
+ "type": "FIELD",
161
+ "name": "fields",
162
+ "content": {
163
+ "type": "SEQ",
164
+ "members": [
165
+ {
166
+ "type": "SYMBOL",
167
+ "name": "_indent"
168
+ },
169
+ {
170
+ "type": "SEQ",
171
+ "members": [
172
+ {
173
+ "type": "REPEAT",
174
+ "content": {
175
+ "type": "SYMBOL",
176
+ "name": "type_pair"
177
+ }
178
+ },
179
+ {
180
+ "type": "SYMBOL",
181
+ "name": "_dedent"
182
+ }
183
+ ]
184
+ }
185
+ ]
186
+ }
187
+ }
188
+ ]
189
+ },
190
+ "trait_list": {
191
+ "type": "SEQ",
192
+ "members": [
193
+ {
194
+ "type": "STRING",
195
+ "value": "("
196
+ },
197
+ {
198
+ "type": "SEQ",
199
+ "members": [
200
+ {
201
+ "type": "SYMBOL",
202
+ "name": "identifier"
203
+ },
204
+ {
205
+ "type": "REPEAT",
206
+ "content": {
207
+ "type": "SEQ",
208
+ "members": [
209
+ {
210
+ "type": "STRING",
211
+ "value": ","
212
+ },
213
+ {
214
+ "type": "SYMBOL",
215
+ "name": "identifier"
216
+ }
217
+ ]
218
+ }
219
+ }
220
+ ]
221
+ },
222
+ {
223
+ "type": "STRING",
224
+ "value": ")"
225
+ }
226
+ ]
227
+ },
228
+ "generic_list": {
229
+ "type": "SEQ",
230
+ "members": [
231
+ {
232
+ "type": "STRING",
233
+ "value": "<"
234
+ },
235
+ {
236
+ "type": "SEQ",
237
+ "members": [
238
+ {
239
+ "type": "SYMBOL",
240
+ "name": "identifier"
241
+ },
242
+ {
243
+ "type": "REPEAT",
244
+ "content": {
245
+ "type": "SEQ",
246
+ "members": [
247
+ {
248
+ "type": "STRING",
249
+ "value": ","
250
+ },
251
+ {
252
+ "type": "SYMBOL",
253
+ "name": "identifier"
254
+ }
255
+ ]
256
+ }
257
+ }
258
+ ]
259
+ },
260
+ {
261
+ "type": "STRING",
262
+ "value": ">"
263
+ }
264
+ ]
265
+ },
266
+ "type_pair": {
267
+ "type": "SEQ",
268
+ "members": [
269
+ {
270
+ "type": "FIELD",
271
+ "name": "key",
272
+ "content": {
273
+ "type": "SYMBOL",
274
+ "name": "identifier"
275
+ }
276
+ },
277
+ {
278
+ "type": "STRING",
279
+ "value": ":"
280
+ },
281
+ {
282
+ "type": "FIELD",
283
+ "name": "value",
284
+ "content": {
285
+ "type": "SYMBOL",
286
+ "name": "identifier"
287
+ }
288
+ }
289
+ ]
290
+ },
291
+ "identifier": {
292
+ "type": "PATTERN",
293
+ "value": "[_\\p{XID_Start}][_\\p{XID_Continue}]*"
294
+ }
295
+ },
296
+ "extras": [
297
+ {
298
+ "type": "PATTERN",
299
+ "value": "\\s"
300
+ }
301
+ ],
302
+ "conflicts": [],
303
+ "precedences": [],
304
+ "externals": [
305
+ {
306
+ "type": "SYMBOL",
307
+ "name": "_newline"
308
+ },
309
+ {
310
+ "type": "SYMBOL",
311
+ "name": "_indent"
312
+ },
313
+ {
314
+ "type": "SYMBOL",
315
+ "name": "_dedent"
316
+ },
317
+ {
318
+ "type": "SYMBOL",
319
+ "name": "_string_start"
320
+ },
321
+ {
322
+ "type": "SYMBOL",
323
+ "name": "_string_content"
324
+ },
325
+ {
326
+ "type": "SYMBOL",
327
+ "name": "_string_end"
328
+ },
329
+ {
330
+ "type": "SYMBOL",
331
+ "name": "comment"
332
+ },
333
+ {
334
+ "type": "STRING",
335
+ "value": "]"
336
+ },
337
+ {
338
+ "type": "STRING",
339
+ "value": ")"
340
+ },
341
+ {
342
+ "type": "STRING",
343
+ "value": "}"
344
+ }
345
+ ],
346
+ "inline": [],
347
+ "supertypes": []
348
+ }
349
+
src/node-types.json ADDED
@@ -0,0 +1,183 @@
1
+ [
2
+ {
3
+ "type": "class_definition",
4
+ "named": true,
5
+ "fields": {
6
+ "fields": {
7
+ "multiple": true,
8
+ "required": true,
9
+ "types": [
10
+ {
11
+ "type": "type_pair",
12
+ "named": true
13
+ }
14
+ ]
15
+ },
16
+ "generics": {
17
+ "multiple": false,
18
+ "required": false,
19
+ "types": [
20
+ {
21
+ "type": "generic_list",
22
+ "named": true
23
+ }
24
+ ]
25
+ },
26
+ "name": {
27
+ "multiple": false,
28
+ "required": true,
29
+ "types": [
30
+ {
31
+ "type": "identifier",
32
+ "named": true
33
+ }
34
+ ]
35
+ },
36
+ "traits": {
37
+ "multiple": false,
38
+ "required": false,
39
+ "types": [
40
+ {
41
+ "type": "trait_list",
42
+ "named": true
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ },
48
+ {
49
+ "type": "generic_list",
50
+ "named": true,
51
+ "fields": {},
52
+ "children": {
53
+ "multiple": true,
54
+ "required": true,
55
+ "types": [
56
+ {
57
+ "type": "identifier",
58
+ "named": true
59
+ }
60
+ ]
61
+ }
62
+ },
63
+ {
64
+ "type": "import_statement",
65
+ "named": true,
66
+ "fields": {
67
+ "name": {
68
+ "multiple": true,
69
+ "required": true,
70
+ "types": [
71
+ {
72
+ "type": "/",
73
+ "named": false
74
+ },
75
+ {
76
+ "type": "identifier",
77
+ "named": true
78
+ }
79
+ ]
80
+ }
81
+ }
82
+ },
83
+ {
84
+ "type": "module",
85
+ "named": true,
86
+ "fields": {},
87
+ "children": {
88
+ "multiple": true,
89
+ "required": false,
90
+ "types": [
91
+ {
92
+ "type": "class_definition",
93
+ "named": true
94
+ },
95
+ {
96
+ "type": "import_statement",
97
+ "named": true
98
+ }
99
+ ]
100
+ }
101
+ },
102
+ {
103
+ "type": "trait_list",
104
+ "named": true,
105
+ "fields": {},
106
+ "children": {
107
+ "multiple": true,
108
+ "required": true,
109
+ "types": [
110
+ {
111
+ "type": "identifier",
112
+ "named": true
113
+ }
114
+ ]
115
+ }
116
+ },
117
+ {
118
+ "type": "type_pair",
119
+ "named": true,
120
+ "fields": {
121
+ "key": {
122
+ "multiple": false,
123
+ "required": true,
124
+ "types": [
125
+ {
126
+ "type": "identifier",
127
+ "named": true
128
+ }
129
+ ]
130
+ },
131
+ "value": {
132
+ "multiple": false,
133
+ "required": true,
134
+ "types": [
135
+ {
136
+ "type": "identifier",
137
+ "named": true
138
+ }
139
+ ]
140
+ }
141
+ }
142
+ },
143
+ {
144
+ "type": "(",
145
+ "named": false
146
+ },
147
+ {
148
+ "type": ")",
149
+ "named": false
150
+ },
151
+ {
152
+ "type": ",",
153
+ "named": false
154
+ },
155
+ {
156
+ "type": "/",
157
+ "named": false
158
+ },
159
+ {
160
+ "type": ":",
161
+ "named": false
162
+ },
163
+ {
164
+ "type": "<",
165
+ "named": false
166
+ },
167
+ {
168
+ "type": ">",
169
+ "named": false
170
+ },
171
+ {
172
+ "type": "class",
173
+ "named": false
174
+ },
175
+ {
176
+ "type": "identifier",
177
+ "named": true
178
+ },
179
+ {
180
+ "type": "import",
181
+ "named": false
182
+ }
183
+ ]
src/scanner.cc ADDED
@@ -0,0 +1,408 @@
1
+ #include <tree_sitter/parser.h>
2
+ #include <vector>
3
+ #include <cwctype>
4
+ #include <cstring>
5
+ #include <cassert>
6
+ #include <stdio.h>
7
+ namespace {
8
+
9
+ using std::vector;
10
+ using std::iswspace;
11
+ using std::memcpy;
12
+
13
+ enum TokenType {
14
+ NEWLINE,
15
+ INDENT,
16
+ DEDENT,
17
+ STRING_START,
18
+ STRING_CONTENT,
19
+ STRING_END,
20
+ COMMENT,
21
+ CLOSE_PAREN,
22
+ CLOSE_BRACKET,
23
+ CLOSE_BRACE,
24
+ };
25
+
26
+ struct Delimiter {
27
+ enum {
28
+ SingleQuote = 1 << 0,
29
+ DoubleQuote = 1 << 1,
30
+ BackQuote = 1 << 2,
31
+ Raw = 1 << 3,
32
+ Format = 1 << 4,
33
+ Triple = 1 << 5,
34
+ Bytes = 1 << 6,
35
+ };
36
+
37
+ Delimiter() : flags(0) {}
38
+
39
+ bool is_format() const {
40
+ return flags & Format;
41
+ }
42
+
43
+ bool is_raw() const {
44
+ return flags & Raw;
45
+ }
46
+
47
+ bool is_triple() const {
48
+ return flags & Triple;
49
+ }
50
+
51
+ bool is_bytes() const {
52
+ return flags & Bytes;
53
+ }
54
+
55
+ int32_t end_character() const {
56
+ if (flags & SingleQuote) return '\'';
57
+ if (flags & DoubleQuote) return '"';
58
+ if (flags & BackQuote) return '`';
59
+ return 0;
60
+ }
61
+
62
+ void set_format() {
63
+ flags |= Format;
64
+ }
65
+
66
+ void set_raw() {
67
+ flags |= Raw;
68
+ }
69
+
70
+ void set_triple() {
71
+ flags |= Triple;
72
+ }
73
+
74
+ void set_bytes() {
75
+ flags |= Bytes;
76
+ }
77
+
78
+ void set_end_character(int32_t character) {
79
+ switch (character) {
80
+ case '\'':
81
+ flags |= SingleQuote;
82
+ break;
83
+ case '"':
84
+ flags |= DoubleQuote;
85
+ break;
86
+ case '`':
87
+ flags |= BackQuote;
88
+ break;
89
+ default:
90
+ assert(false);
91
+ }
92
+ }
93
+
94
+ char flags;
95
+ };
96
+
97
+ struct Scanner {
98
+ Scanner() {
99
+ assert(sizeof(Delimiter) == sizeof(char));
100
+ deserialize(NULL, 0);
101
+ }
102
+
103
+ unsigned serialize(char *buffer) {
104
+ size_t i = 0;
105
+
106
+ size_t delimiter_count = delimiter_stack.size();
107
+ if (delimiter_count > UINT8_MAX) delimiter_count = UINT8_MAX;
108
+ buffer[i++] = delimiter_count;
109
+
110
+ if (delimiter_count > 0) {
111
+ memcpy(&buffer[i], delimiter_stack.data(), delimiter_count);
112
+ }
113
+ i += delimiter_count;
114
+
115
+ vector<uint16_t>::iterator
116
+ iter = indent_length_stack.begin() + 1,
117
+ end = indent_length_stack.end();
118
+
119
+ for (; iter != end && i < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; ++iter) {
120
+ buffer[i++] = *iter;
121
+ }
122
+
123
+ return i;
124
+ }
125
+
126
+ void deserialize(const char *buffer, unsigned length) {
127
+ delimiter_stack.clear();
128
+ indent_length_stack.clear();
129
+ indent_length_stack.push_back(0);
130
+
131
+ if (length > 0) {
132
+ size_t i = 0;
133
+
134
+ size_t delimiter_count = (uint8_t)buffer[i++];
135
+ delimiter_stack.resize(delimiter_count);
136
+ if (delimiter_count > 0) {
137
+ memcpy(delimiter_stack.data(), &buffer[i], delimiter_count);
138
+ }
139
+ i += delimiter_count;
140
+
141
+ for (; i < length; i++) {
142
+ indent_length_stack.push_back(buffer[i]);
143
+ }
144
+ }
145
+ }
146
+
147
+ void advance(TSLexer *lexer) {
148
+ lexer->advance(lexer, false);
149
+ }
150
+
151
+ void skip(TSLexer *lexer) {
152
+ lexer->advance(lexer, true);
153
+ }
154
+
155
+ bool scan(TSLexer *lexer, const bool *valid_symbols) {
156
+ bool error_recovery_mode = valid_symbols[STRING_CONTENT] && valid_symbols[INDENT];
157
+ bool within_brackets = valid_symbols[CLOSE_BRACE] || valid_symbols[CLOSE_PAREN] || valid_symbols[CLOSE_BRACKET];
158
+
159
+ if (valid_symbols[STRING_CONTENT] && !delimiter_stack.empty() && !error_recovery_mode) {
160
+ Delimiter delimiter = delimiter_stack.back();
161
+ int32_t end_character = delimiter.end_character();
162
+ bool has_content = false;
163
+ while (lexer->lookahead) {
164
+ if ((lexer->lookahead == '{' || lexer->lookahead == '}') && delimiter.is_format()) {
165
+ lexer->mark_end(lexer);
166
+ lexer->result_symbol = STRING_CONTENT;
167
+ return has_content;
168
+ } else if (lexer->lookahead == '\\') {
169
+ if (delimiter.is_raw()) {
170
+ lexer->advance(lexer, false);
171
+ } else if (delimiter.is_bytes()) {
172
+ lexer->mark_end(lexer);
173
+ lexer->advance(lexer, false);
174
+ if (lexer->lookahead == 'N' || lexer->lookahead == 'u' || lexer->lookahead == 'U') {
175
+ // In bytes string, \N{...}, \uXXXX and \UXXXXXXXX are not escape sequences
176
+ // https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
177
+ lexer->advance(lexer, false);
178
+ } else {
179
+ lexer->result_symbol = STRING_CONTENT;
180
+ return has_content;
181
+ }
182
+ } else {
183
+ lexer->mark_end(lexer);
184
+ lexer->result_symbol = STRING_CONTENT;
185
+ return has_content;
186
+ }
187
+ } else if (lexer->lookahead == end_character) {
188
+ if (delimiter.is_triple()) {
189
+ lexer->mark_end(lexer);
190
+ lexer->advance(lexer, false);
191
+ if (lexer->lookahead == end_character) {
192
+ lexer->advance(lexer, false);
193
+ if (lexer->lookahead == end_character) {
194
+ if (has_content) {
195
+ lexer->result_symbol = STRING_CONTENT;
196
+ } else {
197
+ lexer->advance(lexer, false);
198
+ lexer->mark_end(lexer);
199
+ delimiter_stack.pop_back();
200
+ lexer->result_symbol = STRING_END;
201
+ }
202
+ return true;
203
+ } else {
204
+ lexer->mark_end(lexer);
205
+ lexer->result_symbol = STRING_CONTENT;
206
+ return true;
207
+ }
208
+ } else {
209
+ lexer->mark_end(lexer);
210
+ lexer->result_symbol = STRING_CONTENT;
211
+ return true;
212
+ }
213
+ } else {
214
+ if (has_content) {
215
+ lexer->result_symbol = STRING_CONTENT;
216
+ } else {
217
+ lexer->advance(lexer, false);
218
+ delimiter_stack.pop_back();
219
+ lexer->result_symbol = STRING_END;
220
+ }
221
+ lexer->mark_end(lexer);
222
+ return true;
223
+ }
224
+ } else if (lexer->lookahead == '\n' && has_content && !delimiter.is_triple()) {
225
+ return false;
226
+ }
227
+ advance(lexer);
228
+ has_content = true;
229
+ }
230
+ }
231
+
232
+ lexer->mark_end(lexer);
233
+
234
+ bool found_end_of_line = false;
235
+ uint32_t indent_length = 0;
236
+ int32_t first_comment_indent_length = -1;
237
+ for (;;) {
238
+ if (lexer->lookahead == '\n') {
239
+ found_end_of_line = true;
240
+ indent_length = 0;
241
+ skip(lexer);
242
+ } else if (lexer->lookahead == ' ') {
243
+ indent_length++;
244
+ skip(lexer);
245
+ } else if (lexer->lookahead == '\r') {
246
+ indent_length = 0;
247
+ skip(lexer);
248
+ } else if (lexer->lookahead == '\t') {
249
+ indent_length += 8;
250
+ skip(lexer);
251
+ } else if (lexer->lookahead == '#') {
252
+ if (first_comment_indent_length == -1) {
253
+ first_comment_indent_length = (int32_t)indent_length;
254
+ }
255
+ while (lexer->lookahead && lexer->lookahead != '\n') {
256
+ skip(lexer);
257
+ }
258
+ skip(lexer);
259
+ indent_length = 0;
260
+ } else if (lexer->lookahead == '\\') {
261
+ skip(lexer);
262
+ if (lexer->lookahead == '\r') {
263
+ skip(lexer);
264
+ }
265
+ if (lexer->lookahead == '\n') {
266
+ skip(lexer);
267
+ } else {
268
+ return false;
269
+ }
270
+ } else if (lexer->lookahead == '\f') {
271
+ indent_length = 0;
272
+ skip(lexer);
273
+ } else if (lexer->lookahead == 0) {
274
+ indent_length = 0;
275
+ found_end_of_line = true;
276
+ break;
277
+ } else {
278
+ break;
279
+ }
280
+ }
281
+
282
+ if (found_end_of_line) {
283
+ if (!indent_length_stack.empty()) {
284
+ uint16_t current_indent_length = indent_length_stack.back();
285
+
286
+ if (
287
+ valid_symbols[INDENT] &&
288
+ indent_length > current_indent_length
289
+ ) {
290
+ indent_length_stack.push_back(indent_length);
291
+ lexer->result_symbol = INDENT;
292
+ return true;
293
+ }
294
+
295
+ if (
296
+ (valid_symbols[DEDENT] || (!valid_symbols[NEWLINE] && !within_brackets)) &&
297
+ indent_length < current_indent_length &&
298
+
299
+ // Wait to create a dedent token until we've consumed any comments
300
+ // whose indentation matches the current block.
301
+ first_comment_indent_length < (int32_t)current_indent_length
302
+ ) {
303
+ indent_length_stack.pop_back();
304
+ lexer->result_symbol = DEDENT;
305
+ return true;
306
+ }
307
+ }
308
+
309
+ if (valid_symbols[NEWLINE] && !error_recovery_mode) {
310
+ lexer->result_symbol = NEWLINE;
311
+ return true;
312
+ }
313
+ }
314
+
315
+ if (first_comment_indent_length == -1 && valid_symbols[STRING_START]) {
316
+ Delimiter delimiter;
317
+
318
+ bool has_flags = false;
319
+ while (lexer->lookahead) {
320
+ if (lexer->lookahead == 'f' || lexer->lookahead == 'F') {
321
+ delimiter.set_format();
322
+ } else if (lexer->lookahead == 'r' || lexer->lookahead == 'R') {
323
+ delimiter.set_raw();
324
+ } else if (lexer->lookahead == 'b' || lexer->lookahead == 'B') {
325
+ delimiter.set_bytes();
326
+ } else if (lexer->lookahead != 'u' && lexer->lookahead != 'U') {
327
+ break;
328
+ }
329
+ has_flags = true;
330
+ advance(lexer);
331
+ }
332
+
333
+ if (lexer->lookahead == '`') {
334
+ delimiter.set_end_character('`');
335
+ advance(lexer);
336
+ lexer->mark_end(lexer);
337
+ } else if (lexer->lookahead == '\'') {
338
+ delimiter.set_end_character('\'');
339
+ advance(lexer);
340
+ lexer->mark_end(lexer);
341
+ if (lexer->lookahead == '\'') {
342
+ advance(lexer);
343
+ if (lexer->lookahead == '\'') {
344
+ advance(lexer);
345
+ lexer->mark_end(lexer);
346
+ delimiter.set_triple();
347
+ }
348
+ }
349
+ } else if (lexer->lookahead == '"') {
350
+ delimiter.set_end_character('"');
351
+ advance(lexer);
352
+ lexer->mark_end(lexer);
353
+ if (lexer->lookahead == '"') {
354
+ advance(lexer);
355
+ if (lexer->lookahead == '"') {
356
+ advance(lexer);
357
+ lexer->mark_end(lexer);
358
+ delimiter.set_triple();
359
+ }
360
+ }
361
+ }
362
+
363
+ if (delimiter.end_character()) {
364
+ delimiter_stack.push_back(delimiter);
365
+ lexer->result_symbol = STRING_START;
366
+ return true;
367
+ } else if (has_flags) {
368
+ return false;
369
+ }
370
+ }
371
+
372
+ return false;
373
+ }
374
+
375
+ vector<uint16_t> indent_length_stack;
376
+ vector<Delimiter> delimiter_stack;
377
+ };
378
+
379
+ }
380
+
381
+ extern "C" {
382
+
383
+ void *tree_sitter_pine_external_scanner_create() {
384
+ return new Scanner();
385
+ }
386
+
387
+ bool tree_sitter_pine_external_scanner_scan(void *payload, TSLexer *lexer,
388
+ const bool *valid_symbols) {
389
+ Scanner *scanner = static_cast<Scanner *>(payload);
390
+ return scanner->scan(lexer, valid_symbols);
391
+ }
392
+
393
+ unsigned tree_sitter_pine_external_scanner_serialize(void *payload, char *buffer) {
394
+ Scanner *scanner = static_cast<Scanner *>(payload);
395
+ return scanner->serialize(buffer);
396
+ }
397
+
398
+ void tree_sitter_pine_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
399
+ Scanner *scanner = static_cast<Scanner *>(payload);
400
+ scanner->deserialize(buffer, length);
401
+ }
402
+
403
+ void tree_sitter_pine_external_scanner_destroy(void *payload) {
404
+ Scanner *scanner = static_cast<Scanner *>(payload);
405
+ delete scanner;
406
+ }
407
+
408
+ }
src/tree_sitter/parser.h ADDED
@@ -0,0 +1,224 @@
1
+ #ifndef TREE_SITTER_PARSER_H_
2
+ #define TREE_SITTER_PARSER_H_
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include <stdbool.h>
9
+ #include <stdint.h>
10
+ #include <stdlib.h>
11
+
12
+ #define ts_builtin_sym_error ((TSSymbol)-1)
13
+ #define ts_builtin_sym_end 0
14
+ #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
15
+
16
+ typedef uint16_t TSStateId;
17
+
18
+ #ifndef TREE_SITTER_API_H_
19
+ typedef uint16_t TSSymbol;
20
+ typedef uint16_t TSFieldId;
21
+ typedef struct TSLanguage TSLanguage;
22
+ #endif
23
+
24
+ typedef struct {
25
+ TSFieldId field_id;
26
+ uint8_t child_index;
27
+ bool inherited;
28
+ } TSFieldMapEntry;
29
+
30
+ typedef struct {
31
+ uint16_t index;
32
+ uint16_t length;
33
+ } TSFieldMapSlice;
34
+
35
+ typedef struct {
36
+ bool visible;
37
+ bool named;
38
+ bool supertype;
39
+ } TSSymbolMetadata;
40
+
41
+ typedef struct TSLexer TSLexer;
42
+
43
+ struct TSLexer {
44
+ int32_t lookahead;
45
+ TSSymbol result_symbol;
46
+ void (*advance)(TSLexer *, bool);
47
+ void (*mark_end)(TSLexer *);
48
+ uint32_t (*get_column)(TSLexer *);
49
+ bool (*is_at_included_range_start)(const TSLexer *);
50
+ bool (*eof)(const TSLexer *);
51
+ };
52
+
53
+ typedef enum {
54
+ TSParseActionTypeShift,
55
+ TSParseActionTypeReduce,
56
+ TSParseActionTypeAccept,
57
+ TSParseActionTypeRecover,
58
+ } TSParseActionType;
59
+
60
+ typedef union {
61
+ struct {
62
+ uint8_t type;
63
+ TSStateId state;
64
+ bool extra;
65
+ bool repetition;
66
+ } shift;
67
+ struct {
68
+ uint8_t type;
69
+ uint8_t child_count;
70
+ TSSymbol symbol;
71
+ int16_t dynamic_precedence;
72
+ uint16_t production_id;
73
+ } reduce;
74
+ uint8_t type;
75
+ } TSParseAction;
76
+
77
+ typedef struct {
78
+ uint16_t lex_state;
79
+ uint16_t external_lex_state;
80
+ } TSLexMode;
81
+
82
+ typedef union {
83
+ TSParseAction action;
84
+ struct {
85
+ uint8_t count;
86
+ bool reusable;
87
+ } entry;
88
+ } TSParseActionEntry;
89
+
90
+ struct TSLanguage {
91
+ uint32_t version;
92
+ uint32_t symbol_count;
93
+ uint32_t alias_count;
94
+ uint32_t token_count;
95
+ uint32_t external_token_count;
96
+ uint32_t state_count;
97
+ uint32_t large_state_count;
98
+ uint32_t production_id_count;
99
+ uint32_t field_count;
100
+ uint16_t max_alias_sequence_length;
101
+ const uint16_t *parse_table;
102
+ const uint16_t *small_parse_table;
103
+ const uint32_t *small_parse_table_map;
104
+ const TSParseActionEntry *parse_actions;
105
+ const char * const *symbol_names;
106
+ const char * const *field_names;
107
+ const TSFieldMapSlice *field_map_slices;
108
+ const TSFieldMapEntry *field_map_entries;
109
+ const TSSymbolMetadata *symbol_metadata;
110
+ const TSSymbol *public_symbol_map;
111
+ const uint16_t *alias_map;
112
+ const TSSymbol *alias_sequences;
113
+ const TSLexMode *lex_modes;
114
+ bool (*lex_fn)(TSLexer *, TSStateId);
115
+ bool (*keyword_lex_fn)(TSLexer *, TSStateId);
116
+ TSSymbol keyword_capture_token;
117
+ struct {
118
+ const bool *states;
119
+ const TSSymbol *symbol_map;
120
+ void *(*create)(void);
121
+ void (*destroy)(void *);
122
+ bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
123
+ unsigned (*serialize)(void *, char *);
124
+ void (*deserialize)(void *, const char *, unsigned);
125
+ } external_scanner;
126
+ const TSStateId *primary_state_ids;
127
+ };
128
+
129
+ /*
130
+ * Lexer Macros
131
+ */
132
+
133
+ #define START_LEXER() \
134
+ bool result = false; \
135
+ bool skip = false; \
136
+ bool eof = false; \
137
+ int32_t lookahead; \
138
+ goto start; \
139
+ next_state: \
140
+ lexer->advance(lexer, skip); \
141
+ start: \
142
+ skip = false; \
143
+ lookahead = lexer->lookahead;
144
+
145
+ #define ADVANCE(state_value) \
146
+ { \
147
+ state = state_value; \
148
+ goto next_state; \
149
+ }
150
+
151
+ #define SKIP(state_value) \
152
+ { \
153
+ skip = true; \
154
+ state = state_value; \
155
+ goto next_state; \
156
+ }
157
+
158
+ #define ACCEPT_TOKEN(symbol_value) \
159
+ result = true; \
160
+ lexer->result_symbol = symbol_value; \
161
+ lexer->mark_end(lexer);
162
+
163
+ #define END_STATE() return result;
164
+
165
+ /*
166
+ * Parse Table Macros
167
+ */
168
+
169
+ #define SMALL_STATE(id) id - LARGE_STATE_COUNT
170
+
171
+ #define STATE(id) id
172
+
173
+ #define ACTIONS(id) id
174
+
175
+ #define SHIFT(state_value) \
176
+ {{ \
177
+ .shift = { \
178
+ .type = TSParseActionTypeShift, \
179
+ .state = state_value \
180
+ } \
181
+ }}
182
+
183
+ #define SHIFT_REPEAT(state_value) \
184
+ {{ \
185
+ .shift = { \
186
+ .type = TSParseActionTypeShift, \
187
+ .state = state_value, \
188
+ .repetition = true \
189
+ } \
190
+ }}
191
+
192
+ #define SHIFT_EXTRA() \
193
+ {{ \
194
+ .shift = { \
195
+ .type = TSParseActionTypeShift, \
196
+ .extra = true \
197
+ } \
198
+ }}
199
+
200
+ #define REDUCE(symbol_val, child_count_val, ...) \
201
+ {{ \
202
+ .reduce = { \
203
+ .type = TSParseActionTypeReduce, \
204
+ .symbol = symbol_val, \
205
+ .child_count = child_count_val, \
206
+ __VA_ARGS__ \
207
+ }, \
208
+ }}
209
+
210
+ #define RECOVER() \
211
+ {{ \
212
+ .type = TSParseActionTypeRecover \
213
+ }}
214
+
215
+ #define ACCEPT_INPUT() \
216
+ {{ \
217
+ .type = TSParseActionTypeAccept \
218
+ }}
219
+
220
+ #ifdef __cplusplus
221
+ }
222
+ #endif
223
+
224
+ #endif // TREE_SITTER_PARSER_H_
test/corpus/class_definitions.txt ADDED
@@ -0,0 +1,67 @@
1
+ ================================================================================
2
+ Class definitions
3
+ ================================================================================
4
+
5
+ class A:
6
+ a: String
7
+ b: Int
8
+
9
+ class B<S, T>:
10
+ a: S
11
+ b: T
12
+
13
+ class A(B, C):
14
+ a: String
15
+ b: Float
16
+
17
+ class A<S, T>(B, C):
18
+ a: S
19
+ b: T
20
+
21
+ --------------------------------------------------------------------------------
22
+
23
+ (module
24
+ (class_definition
25
+ (identifier)
26
+ (type_pair
27
+ (identifier)
28
+ (identifier))
29
+ (type_pair
30
+ (identifier)
31
+ (identifier)))
32
+ (class_definition
33
+ (identifier)
34
+ (generic_list
35
+ (identifier)
36
+ (identifier))
37
+ (type_pair
38
+ (identifier)
39
+ (identifier))
40
+ (type_pair
41
+ (identifier)
42
+ (identifier)))
43
+ (class_definition
44
+ (identifier)
45
+ (trait_list
46
+ (identifier)
47
+ (identifier))
48
+ (type_pair
49
+ (identifier)
50
+ (identifier))
51
+ (type_pair
52
+ (identifier)
53
+ (identifier)))
54
+ (class_definition
55
+ (identifier)
56
+ (generic_list
57
+ (identifier)
58
+ (identifier))
59
+ (trait_list
60
+ (identifier)
61
+ (identifier))
62
+ (type_pair
63
+ (identifier)
64
+ (identifier))
65
+ (type_pair
66
+ (identifier)
67
+ (identifier))))
test/corpus/import_statements.txt ADDED
@@ -0,0 +1,13 @@
1
+ ================================================================================
2
+ Import statements
3
+ ================================================================================
4
+
5
+ import github/pyros2097/std
6
+
7
+ --------------------------------------------------------------------------------
8
+
9
+ (module
10
+ (import_statement
11
+ (identifier)
12
+ (identifier)
13
+ (identifier)))