@coana-tech/cli 14.12.76 → 14.12.78
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/cli.mjs +1 -1
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +1 -2
- package/repos/coana-tech/alucard/alucard.jar +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/cli.mjs +24669 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/LICENSE.md +9 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/README.md +95 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/common.gypi +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/except.gypi +25 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/index.js +14 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/napi-inl.h +6941 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/napi.h +3295 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/node_api.gyp +9 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/nothing.c +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/package-support.json +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/package.json +480 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/tools/README.md +73 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/LICENSE +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/README.md +58 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/SECURITY.md +5 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/bin.js +84 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/build-test.js +19 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/index.js +6 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/node-gyp-build.js +207 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/optional.js +7 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/node-gyp-build/package.json +43 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/LICENSE +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/README.md +128 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/binding.gyp +80 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/index.js +919 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/node_modules/.bin/node-gyp-build +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/node_modules/.bin/node-gyp-build-optional +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/node_modules/.bin/node-gyp-build-test +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/package.json +76 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/linux-arm64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/win32-arm64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/binding.cc +35 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/conversions.h +22 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/language.cc +106 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/language.h +17 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/logger.cc +70 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/logger.h +19 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/node.cc +1088 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/node.h +30 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/parser.cc +306 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/parser.h +35 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/query.cc +397 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/query.h +40 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/tree.cc +316 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/tree.h +45 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/tree-sitter.d.ts +1042 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1318 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +291 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +223 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +297 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +435 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +12 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +920 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2165 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +266 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/portable/endian.h +206 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4187 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +130 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1066 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +399 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +170 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +712 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/ts_assert.h +11 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +83 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +24 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1302 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1859 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/LICENSE +22 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/README.md +21 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/binding.gyp +30 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/bindings/node/binding.cc +20 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/bindings/node/binding_test.js +9 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/bindings/node/index.d.ts +28 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/bindings/node/index.js +11 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/grammar.js +1281 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/node_modules/.bin/node-gyp-build +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/node_modules/.bin/node-gyp-build-optional +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/node_modules/.bin/node-gyp-build-test +16 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/package.json +77 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/darwin-arm64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/darwin-x64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/linux-arm64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/linux-x64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/win32-arm64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/prebuilds/win32-x64/tree-sitter-ruby.node +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/queries/highlights.scm +154 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/queries/locals.scm +27 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/queries/tags.scm +64 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/grammar.json +8364 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/node-types.json +4108 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/parser.c +471247 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/scanner.c +1107 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/tree_sitter/alloc.h +54 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/tree_sitter/array.h +290 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/tree_sitter/parser.h +266 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/tree-sitter-ruby.wasm +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/tree-sitter.json +46 -0
- package/repos/coana-tech/goana/bin/goana-darwin-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-darwin-arm64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-arm64.gz +0 -0
|
@@ -0,0 +1,2165 @@
|
|
|
1
|
+
#include <time.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <limits.h>
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <inttypes.h>
|
|
6
|
+
#include "tree_sitter/api.h"
|
|
7
|
+
#include "./alloc.h"
|
|
8
|
+
#include "./array.h"
|
|
9
|
+
#include "./atomic.h"
|
|
10
|
+
#include "./clock.h"
|
|
11
|
+
#include "./error_costs.h"
|
|
12
|
+
#include "./get_changed_ranges.h"
|
|
13
|
+
#include "./language.h"
|
|
14
|
+
#include "./length.h"
|
|
15
|
+
#include "./lexer.h"
|
|
16
|
+
#include "./reduce_action.h"
|
|
17
|
+
#include "./reusable_node.h"
|
|
18
|
+
#include "./stack.h"
|
|
19
|
+
#include "./subtree.h"
|
|
20
|
+
#include "./tree.h"
|
|
21
|
+
#include "./ts_assert.h"
|
|
22
|
+
#include "./wasm_store.h"
|
|
23
|
+
|
|
24
|
+
#define LOG(...) \
|
|
25
|
+
if (self->lexer.logger.log || self->dot_graph_file) { \
|
|
26
|
+
snprintf(self->lexer.debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, __VA_ARGS__); \
|
|
27
|
+
ts_parser__log(self); \
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#define LOG_LOOKAHEAD(symbol_name, size) \
|
|
31
|
+
if (self->lexer.logger.log || self->dot_graph_file) { \
|
|
32
|
+
char *buf = self->lexer.debug_buffer; \
|
|
33
|
+
const char *symbol = symbol_name; \
|
|
34
|
+
int off = snprintf( \
|
|
35
|
+
buf, \
|
|
36
|
+
TREE_SITTER_SERIALIZATION_BUFFER_SIZE, \
|
|
37
|
+
"lexed_lookahead sym:" \
|
|
38
|
+
); \
|
|
39
|
+
for ( \
|
|
40
|
+
int i = 0; \
|
|
41
|
+
symbol[i] != '\0' \
|
|
42
|
+
&& off < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; \
|
|
43
|
+
i++ \
|
|
44
|
+
) { \
|
|
45
|
+
switch (symbol[i]) { \
|
|
46
|
+
case '\t': buf[off++] = '\\'; buf[off++] = 't'; break; \
|
|
47
|
+
case '\n': buf[off++] = '\\'; buf[off++] = 'n'; break; \
|
|
48
|
+
case '\v': buf[off++] = '\\'; buf[off++] = 'v'; break; \
|
|
49
|
+
case '\f': buf[off++] = '\\'; buf[off++] = 'f'; break; \
|
|
50
|
+
case '\r': buf[off++] = '\\'; buf[off++] = 'r'; break; \
|
|
51
|
+
case '\\': buf[off++] = '\\'; buf[off++] = '\\'; break; \
|
|
52
|
+
default: buf[off++] = symbol[i]; break; \
|
|
53
|
+
} \
|
|
54
|
+
} \
|
|
55
|
+
snprintf( \
|
|
56
|
+
buf + off, \
|
|
57
|
+
TREE_SITTER_SERIALIZATION_BUFFER_SIZE - off, \
|
|
58
|
+
", size:%u", \
|
|
59
|
+
size \
|
|
60
|
+
); \
|
|
61
|
+
ts_parser__log(self); \
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#define LOG_STACK() \
|
|
65
|
+
if (self->dot_graph_file) { \
|
|
66
|
+
ts_stack_print_dot_graph(self->stack, self->language, self->dot_graph_file); \
|
|
67
|
+
fputs("\n\n", self->dot_graph_file); \
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#define LOG_TREE(tree) \
|
|
71
|
+
if (self->dot_graph_file) { \
|
|
72
|
+
ts_subtree_print_dot_graph(tree, self->language, self->dot_graph_file); \
|
|
73
|
+
fputs("\n", self->dot_graph_file); \
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#define SYM_NAME(symbol) ts_language_symbol_name(self->language, symbol)
|
|
77
|
+
|
|
78
|
+
#define TREE_NAME(tree) SYM_NAME(ts_subtree_symbol(tree))
|
|
79
|
+
|
|
80
|
+
static const unsigned MAX_VERSION_COUNT = 6;
|
|
81
|
+
static const unsigned MAX_VERSION_COUNT_OVERFLOW = 4;
|
|
82
|
+
static const unsigned MAX_SUMMARY_DEPTH = 16;
|
|
83
|
+
static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE;
|
|
84
|
+
static const unsigned OP_COUNT_PER_PARSER_TIMEOUT_CHECK = 100;
|
|
85
|
+
|
|
86
|
+
typedef struct {
|
|
87
|
+
Subtree token;
|
|
88
|
+
Subtree last_external_token;
|
|
89
|
+
uint32_t byte_index;
|
|
90
|
+
} TokenCache;
|
|
91
|
+
|
|
92
|
+
struct TSParser {
|
|
93
|
+
Lexer lexer;
|
|
94
|
+
Stack *stack;
|
|
95
|
+
SubtreePool tree_pool;
|
|
96
|
+
const TSLanguage *language;
|
|
97
|
+
TSWasmStore *wasm_store;
|
|
98
|
+
ReduceActionSet reduce_actions;
|
|
99
|
+
Subtree finished_tree;
|
|
100
|
+
SubtreeArray trailing_extras;
|
|
101
|
+
SubtreeArray trailing_extras2;
|
|
102
|
+
SubtreeArray scratch_trees;
|
|
103
|
+
TokenCache token_cache;
|
|
104
|
+
ReusableNode reusable_node;
|
|
105
|
+
void *external_scanner_payload;
|
|
106
|
+
FILE *dot_graph_file;
|
|
107
|
+
TSClock end_clock;
|
|
108
|
+
TSDuration timeout_duration;
|
|
109
|
+
unsigned accept_count;
|
|
110
|
+
unsigned operation_count;
|
|
111
|
+
const volatile size_t *cancellation_flag;
|
|
112
|
+
Subtree old_tree;
|
|
113
|
+
TSRangeArray included_range_differences;
|
|
114
|
+
unsigned included_range_difference_index;
|
|
115
|
+
bool has_scanner_error;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
typedef struct {
|
|
119
|
+
unsigned cost;
|
|
120
|
+
unsigned node_count;
|
|
121
|
+
int dynamic_precedence;
|
|
122
|
+
bool is_in_error;
|
|
123
|
+
} ErrorStatus;
|
|
124
|
+
|
|
125
|
+
typedef enum {
|
|
126
|
+
ErrorComparisonTakeLeft,
|
|
127
|
+
ErrorComparisonPreferLeft,
|
|
128
|
+
ErrorComparisonNone,
|
|
129
|
+
ErrorComparisonPreferRight,
|
|
130
|
+
ErrorComparisonTakeRight,
|
|
131
|
+
} ErrorComparison;
|
|
132
|
+
|
|
133
|
+
typedef struct {
|
|
134
|
+
const char *string;
|
|
135
|
+
uint32_t length;
|
|
136
|
+
} TSStringInput;
|
|
137
|
+
|
|
138
|
+
// StringInput
|
|
139
|
+
|
|
140
|
+
static const char *ts_string_input_read(
|
|
141
|
+
void *_self,
|
|
142
|
+
uint32_t byte,
|
|
143
|
+
TSPoint point,
|
|
144
|
+
uint32_t *length
|
|
145
|
+
) {
|
|
146
|
+
(void)point;
|
|
147
|
+
TSStringInput *self = (TSStringInput *)_self;
|
|
148
|
+
if (byte >= self->length) {
|
|
149
|
+
*length = 0;
|
|
150
|
+
return "";
|
|
151
|
+
} else {
|
|
152
|
+
*length = self->length - byte;
|
|
153
|
+
return self->string + byte;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Parser - Private
|
|
158
|
+
|
|
159
|
+
static void ts_parser__log(TSParser *self) {
|
|
160
|
+
if (self->lexer.logger.log) {
|
|
161
|
+
self->lexer.logger.log(
|
|
162
|
+
self->lexer.logger.payload,
|
|
163
|
+
TSLogTypeParse,
|
|
164
|
+
self->lexer.debug_buffer
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (self->dot_graph_file) {
|
|
169
|
+
fprintf(self->dot_graph_file, "graph {\nlabel=\"");
|
|
170
|
+
for (char *chr = &self->lexer.debug_buffer[0]; *chr != 0; chr++) {
|
|
171
|
+
if (*chr == '"' || *chr == '\\') fputc('\\', self->dot_graph_file);
|
|
172
|
+
fputc(*chr, self->dot_graph_file);
|
|
173
|
+
}
|
|
174
|
+
fprintf(self->dot_graph_file, "\"\n}\n\n");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
static bool ts_parser__breakdown_top_of_stack(
|
|
179
|
+
TSParser *self,
|
|
180
|
+
StackVersion version
|
|
181
|
+
) {
|
|
182
|
+
bool did_break_down = false;
|
|
183
|
+
bool pending = false;
|
|
184
|
+
|
|
185
|
+
do {
|
|
186
|
+
StackSliceArray pop = ts_stack_pop_pending(self->stack, version);
|
|
187
|
+
if (!pop.size) break;
|
|
188
|
+
|
|
189
|
+
did_break_down = true;
|
|
190
|
+
pending = false;
|
|
191
|
+
for (uint32_t i = 0; i < pop.size; i++) {
|
|
192
|
+
StackSlice slice = pop.contents[i];
|
|
193
|
+
TSStateId state = ts_stack_state(self->stack, slice.version);
|
|
194
|
+
Subtree parent = *array_front(&slice.subtrees);
|
|
195
|
+
|
|
196
|
+
for (uint32_t j = 0, n = ts_subtree_child_count(parent); j < n; j++) {
|
|
197
|
+
Subtree child = ts_subtree_children(parent)[j];
|
|
198
|
+
pending = ts_subtree_child_count(child) > 0;
|
|
199
|
+
|
|
200
|
+
if (ts_subtree_is_error(child)) {
|
|
201
|
+
state = ERROR_STATE;
|
|
202
|
+
} else if (!ts_subtree_extra(child)) {
|
|
203
|
+
state = ts_language_next_state(self->language, state, ts_subtree_symbol(child));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
ts_subtree_retain(child);
|
|
207
|
+
ts_stack_push(self->stack, slice.version, child, pending, state);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
for (uint32_t j = 1; j < slice.subtrees.size; j++) {
|
|
211
|
+
Subtree tree = slice.subtrees.contents[j];
|
|
212
|
+
ts_stack_push(self->stack, slice.version, tree, false, state);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
ts_subtree_release(&self->tree_pool, parent);
|
|
216
|
+
array_delete(&slice.subtrees);
|
|
217
|
+
|
|
218
|
+
LOG("breakdown_top_of_stack tree:%s", TREE_NAME(parent));
|
|
219
|
+
LOG_STACK();
|
|
220
|
+
}
|
|
221
|
+
} while (pending);
|
|
222
|
+
|
|
223
|
+
return did_break_down;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
static void ts_parser__breakdown_lookahead(
|
|
227
|
+
TSParser *self,
|
|
228
|
+
Subtree *lookahead,
|
|
229
|
+
TSStateId state,
|
|
230
|
+
ReusableNode *reusable_node
|
|
231
|
+
) {
|
|
232
|
+
bool did_descend = false;
|
|
233
|
+
Subtree tree = reusable_node_tree(reusable_node);
|
|
234
|
+
while (ts_subtree_child_count(tree) > 0 && ts_subtree_parse_state(tree) != state) {
|
|
235
|
+
LOG("state_mismatch sym:%s", TREE_NAME(tree));
|
|
236
|
+
reusable_node_descend(reusable_node);
|
|
237
|
+
tree = reusable_node_tree(reusable_node);
|
|
238
|
+
did_descend = true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (did_descend) {
|
|
242
|
+
ts_subtree_release(&self->tree_pool, *lookahead);
|
|
243
|
+
*lookahead = tree;
|
|
244
|
+
ts_subtree_retain(*lookahead);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static ErrorComparison ts_parser__compare_versions(
|
|
249
|
+
TSParser *self,
|
|
250
|
+
ErrorStatus a,
|
|
251
|
+
ErrorStatus b
|
|
252
|
+
) {
|
|
253
|
+
(void)self;
|
|
254
|
+
if (!a.is_in_error && b.is_in_error) {
|
|
255
|
+
if (a.cost < b.cost) {
|
|
256
|
+
return ErrorComparisonTakeLeft;
|
|
257
|
+
} else {
|
|
258
|
+
return ErrorComparisonPreferLeft;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (a.is_in_error && !b.is_in_error) {
|
|
263
|
+
if (b.cost < a.cost) {
|
|
264
|
+
return ErrorComparisonTakeRight;
|
|
265
|
+
} else {
|
|
266
|
+
return ErrorComparisonPreferRight;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (a.cost < b.cost) {
|
|
271
|
+
if ((b.cost - a.cost) * (1 + a.node_count) > MAX_COST_DIFFERENCE) {
|
|
272
|
+
return ErrorComparisonTakeLeft;
|
|
273
|
+
} else {
|
|
274
|
+
return ErrorComparisonPreferLeft;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (b.cost < a.cost) {
|
|
279
|
+
if ((a.cost - b.cost) * (1 + b.node_count) > MAX_COST_DIFFERENCE) {
|
|
280
|
+
return ErrorComparisonTakeRight;
|
|
281
|
+
} else {
|
|
282
|
+
return ErrorComparisonPreferRight;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (a.dynamic_precedence > b.dynamic_precedence) return ErrorComparisonPreferLeft;
|
|
287
|
+
if (b.dynamic_precedence > a.dynamic_precedence) return ErrorComparisonPreferRight;
|
|
288
|
+
return ErrorComparisonNone;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
static ErrorStatus ts_parser__version_status(
|
|
292
|
+
TSParser *self,
|
|
293
|
+
StackVersion version
|
|
294
|
+
) {
|
|
295
|
+
unsigned cost = ts_stack_error_cost(self->stack, version);
|
|
296
|
+
bool is_paused = ts_stack_is_paused(self->stack, version);
|
|
297
|
+
if (is_paused) cost += ERROR_COST_PER_SKIPPED_TREE;
|
|
298
|
+
return (ErrorStatus) {
|
|
299
|
+
.cost = cost,
|
|
300
|
+
.node_count = ts_stack_node_count_since_error(self->stack, version),
|
|
301
|
+
.dynamic_precedence = ts_stack_dynamic_precedence(self->stack, version),
|
|
302
|
+
.is_in_error = is_paused || ts_stack_state(self->stack, version) == ERROR_STATE
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
static bool ts_parser__better_version_exists(
|
|
307
|
+
TSParser *self,
|
|
308
|
+
StackVersion version,
|
|
309
|
+
bool is_in_error,
|
|
310
|
+
unsigned cost
|
|
311
|
+
) {
|
|
312
|
+
if (self->finished_tree.ptr && ts_subtree_error_cost(self->finished_tree) <= cost) {
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
Length position = ts_stack_position(self->stack, version);
|
|
317
|
+
ErrorStatus status = {
|
|
318
|
+
.cost = cost,
|
|
319
|
+
.is_in_error = is_in_error,
|
|
320
|
+
.dynamic_precedence = ts_stack_dynamic_precedence(self->stack, version),
|
|
321
|
+
.node_count = ts_stack_node_count_since_error(self->stack, version),
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) {
|
|
325
|
+
if (i == version ||
|
|
326
|
+
!ts_stack_is_active(self->stack, i) ||
|
|
327
|
+
ts_stack_position(self->stack, i).bytes < position.bytes) continue;
|
|
328
|
+
ErrorStatus status_i = ts_parser__version_status(self, i);
|
|
329
|
+
switch (ts_parser__compare_versions(self, status, status_i)) {
|
|
330
|
+
case ErrorComparisonTakeRight:
|
|
331
|
+
return true;
|
|
332
|
+
case ErrorComparisonPreferRight:
|
|
333
|
+
if (ts_stack_can_merge(self->stack, i, version)) return true;
|
|
334
|
+
break;
|
|
335
|
+
default:
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static bool ts_parser__call_main_lex_fn(TSParser *self, TSLexMode lex_mode) {
|
|
344
|
+
if (ts_language_is_wasm(self->language)) {
|
|
345
|
+
return ts_wasm_store_call_lex_main(self->wasm_store, lex_mode.lex_state);
|
|
346
|
+
} else {
|
|
347
|
+
return self->language->lex_fn(&self->lexer.data, lex_mode.lex_state);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
static bool ts_parser__call_keyword_lex_fn(TSParser *self) {
|
|
352
|
+
if (ts_language_is_wasm(self->language)) {
|
|
353
|
+
return ts_wasm_store_call_lex_keyword(self->wasm_store, 0);
|
|
354
|
+
} else {
|
|
355
|
+
return self->language->keyword_lex_fn(&self->lexer.data, 0);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static void ts_parser__external_scanner_create(
|
|
360
|
+
TSParser *self
|
|
361
|
+
) {
|
|
362
|
+
if (self->language && self->language->external_scanner.states) {
|
|
363
|
+
if (ts_language_is_wasm(self->language)) {
|
|
364
|
+
self->external_scanner_payload = (void *)(uintptr_t)ts_wasm_store_call_scanner_create(
|
|
365
|
+
self->wasm_store
|
|
366
|
+
);
|
|
367
|
+
if (ts_wasm_store_has_error(self->wasm_store)) {
|
|
368
|
+
self->has_scanner_error = true;
|
|
369
|
+
}
|
|
370
|
+
} else if (self->language->external_scanner.create) {
|
|
371
|
+
self->external_scanner_payload = self->language->external_scanner.create();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
static void ts_parser__external_scanner_destroy(
|
|
377
|
+
TSParser *self
|
|
378
|
+
) {
|
|
379
|
+
if (
|
|
380
|
+
self->language &&
|
|
381
|
+
self->external_scanner_payload &&
|
|
382
|
+
self->language->external_scanner.destroy &&
|
|
383
|
+
!ts_language_is_wasm(self->language)
|
|
384
|
+
) {
|
|
385
|
+
self->language->external_scanner.destroy(
|
|
386
|
+
self->external_scanner_payload
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
self->external_scanner_payload = NULL;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
static unsigned ts_parser__external_scanner_serialize(
|
|
393
|
+
TSParser *self
|
|
394
|
+
) {
|
|
395
|
+
if (ts_language_is_wasm(self->language)) {
|
|
396
|
+
return ts_wasm_store_call_scanner_serialize(
|
|
397
|
+
self->wasm_store,
|
|
398
|
+
(uintptr_t)self->external_scanner_payload,
|
|
399
|
+
self->lexer.debug_buffer
|
|
400
|
+
);
|
|
401
|
+
} else {
|
|
402
|
+
uint32_t length = self->language->external_scanner.serialize(
|
|
403
|
+
self->external_scanner_payload,
|
|
404
|
+
self->lexer.debug_buffer
|
|
405
|
+
);
|
|
406
|
+
ts_assert(length <= TREE_SITTER_SERIALIZATION_BUFFER_SIZE);
|
|
407
|
+
return length;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
static void ts_parser__external_scanner_deserialize(
|
|
412
|
+
TSParser *self,
|
|
413
|
+
Subtree external_token
|
|
414
|
+
) {
|
|
415
|
+
const char *data = NULL;
|
|
416
|
+
uint32_t length = 0;
|
|
417
|
+
if (external_token.ptr) {
|
|
418
|
+
data = ts_external_scanner_state_data(&external_token.ptr->external_scanner_state);
|
|
419
|
+
length = external_token.ptr->external_scanner_state.length;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (ts_language_is_wasm(self->language)) {
|
|
423
|
+
ts_wasm_store_call_scanner_deserialize(
|
|
424
|
+
self->wasm_store,
|
|
425
|
+
(uintptr_t)self->external_scanner_payload,
|
|
426
|
+
data,
|
|
427
|
+
length
|
|
428
|
+
);
|
|
429
|
+
if (ts_wasm_store_has_error(self->wasm_store)) {
|
|
430
|
+
self->has_scanner_error = true;
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
self->language->external_scanner.deserialize(
|
|
434
|
+
self->external_scanner_payload,
|
|
435
|
+
data,
|
|
436
|
+
length
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
static bool ts_parser__external_scanner_scan(
|
|
442
|
+
TSParser *self,
|
|
443
|
+
TSStateId external_lex_state
|
|
444
|
+
) {
|
|
445
|
+
if (ts_language_is_wasm(self->language)) {
|
|
446
|
+
bool result = ts_wasm_store_call_scanner_scan(
|
|
447
|
+
self->wasm_store,
|
|
448
|
+
(uintptr_t)self->external_scanner_payload,
|
|
449
|
+
external_lex_state * self->language->external_token_count
|
|
450
|
+
);
|
|
451
|
+
if (ts_wasm_store_has_error(self->wasm_store)) {
|
|
452
|
+
self->has_scanner_error = true;
|
|
453
|
+
}
|
|
454
|
+
return result;
|
|
455
|
+
} else {
|
|
456
|
+
const bool *valid_external_tokens = ts_language_enabled_external_tokens(
|
|
457
|
+
self->language,
|
|
458
|
+
external_lex_state
|
|
459
|
+
);
|
|
460
|
+
return self->language->external_scanner.scan(
|
|
461
|
+
self->external_scanner_payload,
|
|
462
|
+
&self->lexer.data,
|
|
463
|
+
valid_external_tokens
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
static bool ts_parser__can_reuse_first_leaf(
|
|
469
|
+
TSParser *self,
|
|
470
|
+
TSStateId state,
|
|
471
|
+
Subtree tree,
|
|
472
|
+
TableEntry *table_entry
|
|
473
|
+
) {
|
|
474
|
+
TSLexMode current_lex_mode = self->language->lex_modes[state];
|
|
475
|
+
TSSymbol leaf_symbol = ts_subtree_leaf_symbol(tree);
|
|
476
|
+
TSStateId leaf_state = ts_subtree_leaf_parse_state(tree);
|
|
477
|
+
TSLexMode leaf_lex_mode = self->language->lex_modes[leaf_state];
|
|
478
|
+
|
|
479
|
+
// At the end of a non-terminal extra node, the lexer normally returns
|
|
480
|
+
// NULL, which indicates that the parser should look for a reduce action
|
|
481
|
+
// at symbol `0`. Avoid reusing tokens in this situation to ensure that
|
|
482
|
+
// the same thing happens when incrementally reparsing.
|
|
483
|
+
if (current_lex_mode.lex_state == (uint16_t)(-1)) return false;
|
|
484
|
+
|
|
485
|
+
// If the token was created in a state with the same set of lookaheads, it is reusable.
|
|
486
|
+
if (
|
|
487
|
+
table_entry->action_count > 0 &&
|
|
488
|
+
memcmp(&leaf_lex_mode, ¤t_lex_mode, sizeof(TSLexMode)) == 0 &&
|
|
489
|
+
(
|
|
490
|
+
leaf_symbol != self->language->keyword_capture_token ||
|
|
491
|
+
(!ts_subtree_is_keyword(tree) && ts_subtree_parse_state(tree) == state)
|
|
492
|
+
)
|
|
493
|
+
) return true;
|
|
494
|
+
|
|
495
|
+
// Empty tokens are not reusable in states with different lookaheads.
|
|
496
|
+
if (ts_subtree_size(tree).bytes == 0 && leaf_symbol != ts_builtin_sym_end) return false;
|
|
497
|
+
|
|
498
|
+
// If the current state allows external tokens or other tokens that conflict with this
|
|
499
|
+
// token, this token is not reusable.
|
|
500
|
+
return current_lex_mode.external_lex_state == 0 && table_entry->is_reusable;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
static Subtree ts_parser__lex(
|
|
504
|
+
TSParser *self,
|
|
505
|
+
StackVersion version,
|
|
506
|
+
TSStateId parse_state
|
|
507
|
+
) {
|
|
508
|
+
TSLexMode lex_mode = self->language->lex_modes[parse_state];
|
|
509
|
+
if (lex_mode.lex_state == (uint16_t)-1) {
|
|
510
|
+
LOG("no_lookahead_after_non_terminal_extra");
|
|
511
|
+
return NULL_SUBTREE;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const Length start_position = ts_stack_position(self->stack, version);
|
|
515
|
+
const Subtree external_token = ts_stack_last_external_token(self->stack, version);
|
|
516
|
+
|
|
517
|
+
bool found_external_token = false;
|
|
518
|
+
bool error_mode = parse_state == ERROR_STATE;
|
|
519
|
+
bool skipped_error = false;
|
|
520
|
+
bool called_get_column = false;
|
|
521
|
+
int32_t first_error_character = 0;
|
|
522
|
+
Length error_start_position = length_zero();
|
|
523
|
+
Length error_end_position = length_zero();
|
|
524
|
+
uint32_t lookahead_end_byte = 0;
|
|
525
|
+
uint32_t external_scanner_state_len = 0;
|
|
526
|
+
bool external_scanner_state_changed = false;
|
|
527
|
+
ts_lexer_reset(&self->lexer, start_position);
|
|
528
|
+
|
|
529
|
+
for (;;) {
|
|
530
|
+
bool found_token = false;
|
|
531
|
+
Length current_position = self->lexer.current_position;
|
|
532
|
+
|
|
533
|
+
if (lex_mode.external_lex_state != 0) {
|
|
534
|
+
LOG(
|
|
535
|
+
"lex_external state:%d, row:%u, column:%u",
|
|
536
|
+
lex_mode.external_lex_state,
|
|
537
|
+
current_position.extent.row,
|
|
538
|
+
current_position.extent.column
|
|
539
|
+
);
|
|
540
|
+
ts_lexer_start(&self->lexer);
|
|
541
|
+
ts_parser__external_scanner_deserialize(self, external_token);
|
|
542
|
+
found_token = ts_parser__external_scanner_scan(self, lex_mode.external_lex_state);
|
|
543
|
+
if (self->has_scanner_error) return NULL_SUBTREE;
|
|
544
|
+
ts_lexer_finish(&self->lexer, &lookahead_end_byte);
|
|
545
|
+
|
|
546
|
+
if (found_token) {
|
|
547
|
+
external_scanner_state_len = ts_parser__external_scanner_serialize(self);
|
|
548
|
+
external_scanner_state_changed = !ts_external_scanner_state_eq(
|
|
549
|
+
ts_subtree_external_scanner_state(external_token),
|
|
550
|
+
self->lexer.debug_buffer,
|
|
551
|
+
external_scanner_state_len
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
// When recovering from an error, ignore any zero-length external tokens
|
|
555
|
+
// unless they have changed the external scanner's state. This helps to
|
|
556
|
+
// avoid infinite loops which could otherwise occur, because the lexer is
|
|
557
|
+
// looking for any possible token, instead of looking for the specific set of
|
|
558
|
+
// tokens that are valid in some parse state.
|
|
559
|
+
//
|
|
560
|
+
// Note that it's possible that the token end position may be *before* the
|
|
561
|
+
// original position of the lexer because of the way that tokens are positioned
|
|
562
|
+
// at included range boundaries: when a token is terminated at the start of
|
|
563
|
+
// an included range, it is marked as ending at the *end* of the preceding
|
|
564
|
+
// included range.
|
|
565
|
+
if (
|
|
566
|
+
self->lexer.token_end_position.bytes <= current_position.bytes &&
|
|
567
|
+
(error_mode || !ts_stack_has_advanced_since_error(self->stack, version)) &&
|
|
568
|
+
!external_scanner_state_changed
|
|
569
|
+
) {
|
|
570
|
+
LOG(
|
|
571
|
+
"ignore_empty_external_token symbol:%s",
|
|
572
|
+
SYM_NAME(self->language->external_scanner.symbol_map[self->lexer.data.result_symbol])
|
|
573
|
+
)
|
|
574
|
+
found_token = false;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (found_token) {
|
|
579
|
+
found_external_token = true;
|
|
580
|
+
called_get_column = self->lexer.did_get_column;
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
ts_lexer_reset(&self->lexer, current_position);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
LOG(
|
|
588
|
+
"lex_internal state:%d, row:%u, column:%u",
|
|
589
|
+
lex_mode.lex_state,
|
|
590
|
+
current_position.extent.row,
|
|
591
|
+
current_position.extent.column
|
|
592
|
+
);
|
|
593
|
+
ts_lexer_start(&self->lexer);
|
|
594
|
+
found_token = ts_parser__call_main_lex_fn(self, lex_mode);
|
|
595
|
+
ts_lexer_finish(&self->lexer, &lookahead_end_byte);
|
|
596
|
+
if (found_token) break;
|
|
597
|
+
|
|
598
|
+
if (!error_mode) {
|
|
599
|
+
error_mode = true;
|
|
600
|
+
lex_mode = self->language->lex_modes[ERROR_STATE];
|
|
601
|
+
ts_lexer_reset(&self->lexer, start_position);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (!skipped_error) {
|
|
606
|
+
LOG("skip_unrecognized_character");
|
|
607
|
+
skipped_error = true;
|
|
608
|
+
error_start_position = self->lexer.token_start_position;
|
|
609
|
+
error_end_position = self->lexer.token_start_position;
|
|
610
|
+
first_error_character = self->lexer.data.lookahead;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (self->lexer.current_position.bytes == error_end_position.bytes) {
|
|
614
|
+
if (self->lexer.data.eof(&self->lexer.data)) {
|
|
615
|
+
self->lexer.data.result_symbol = ts_builtin_sym_error;
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
self->lexer.data.advance(&self->lexer.data, false);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
error_end_position = self->lexer.current_position;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
Subtree result;
|
|
625
|
+
if (skipped_error) {
|
|
626
|
+
Length padding = length_sub(error_start_position, start_position);
|
|
627
|
+
Length size = length_sub(error_end_position, error_start_position);
|
|
628
|
+
uint32_t lookahead_bytes = lookahead_end_byte - error_end_position.bytes;
|
|
629
|
+
result = ts_subtree_new_error(
|
|
630
|
+
&self->tree_pool,
|
|
631
|
+
first_error_character,
|
|
632
|
+
padding,
|
|
633
|
+
size,
|
|
634
|
+
lookahead_bytes,
|
|
635
|
+
parse_state,
|
|
636
|
+
self->language
|
|
637
|
+
);
|
|
638
|
+
} else {
|
|
639
|
+
bool is_keyword = false;
|
|
640
|
+
TSSymbol symbol = self->lexer.data.result_symbol;
|
|
641
|
+
Length padding = length_sub(self->lexer.token_start_position, start_position);
|
|
642
|
+
Length size = length_sub(self->lexer.token_end_position, self->lexer.token_start_position);
|
|
643
|
+
uint32_t lookahead_bytes = lookahead_end_byte - self->lexer.token_end_position.bytes;
|
|
644
|
+
|
|
645
|
+
if (found_external_token) {
|
|
646
|
+
symbol = self->language->external_scanner.symbol_map[symbol];
|
|
647
|
+
} else if (symbol == self->language->keyword_capture_token && symbol != 0) {
|
|
648
|
+
uint32_t end_byte = self->lexer.token_end_position.bytes;
|
|
649
|
+
ts_lexer_reset(&self->lexer, self->lexer.token_start_position);
|
|
650
|
+
ts_lexer_start(&self->lexer);
|
|
651
|
+
|
|
652
|
+
is_keyword = ts_parser__call_keyword_lex_fn(self);
|
|
653
|
+
|
|
654
|
+
if (
|
|
655
|
+
is_keyword &&
|
|
656
|
+
self->lexer.token_end_position.bytes == end_byte &&
|
|
657
|
+
ts_language_has_actions(self->language, parse_state, self->lexer.data.result_symbol)
|
|
658
|
+
) {
|
|
659
|
+
symbol = self->lexer.data.result_symbol;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
result = ts_subtree_new_leaf(
|
|
664
|
+
&self->tree_pool,
|
|
665
|
+
symbol,
|
|
666
|
+
padding,
|
|
667
|
+
size,
|
|
668
|
+
lookahead_bytes,
|
|
669
|
+
parse_state,
|
|
670
|
+
found_external_token,
|
|
671
|
+
called_get_column,
|
|
672
|
+
is_keyword,
|
|
673
|
+
self->language
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
if (found_external_token) {
|
|
677
|
+
MutableSubtree mut_result = ts_subtree_to_mut_unsafe(result);
|
|
678
|
+
ts_external_scanner_state_init(
|
|
679
|
+
&mut_result.ptr->external_scanner_state,
|
|
680
|
+
self->lexer.debug_buffer,
|
|
681
|
+
external_scanner_state_len
|
|
682
|
+
);
|
|
683
|
+
mut_result.ptr->has_external_scanner_state_change = external_scanner_state_changed;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
LOG_LOOKAHEAD(
|
|
688
|
+
SYM_NAME(ts_subtree_symbol(result)),
|
|
689
|
+
ts_subtree_total_size(result).bytes
|
|
690
|
+
);
|
|
691
|
+
return result;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
static Subtree ts_parser__get_cached_token(
|
|
695
|
+
TSParser *self,
|
|
696
|
+
TSStateId state,
|
|
697
|
+
size_t position,
|
|
698
|
+
Subtree last_external_token,
|
|
699
|
+
TableEntry *table_entry
|
|
700
|
+
) {
|
|
701
|
+
TokenCache *cache = &self->token_cache;
|
|
702
|
+
if (
|
|
703
|
+
cache->token.ptr && cache->byte_index == position &&
|
|
704
|
+
ts_subtree_external_scanner_state_eq(cache->last_external_token, last_external_token)
|
|
705
|
+
) {
|
|
706
|
+
ts_language_table_entry(self->language, state, ts_subtree_symbol(cache->token), table_entry);
|
|
707
|
+
if (ts_parser__can_reuse_first_leaf(self, state, cache->token, table_entry)) {
|
|
708
|
+
ts_subtree_retain(cache->token);
|
|
709
|
+
return cache->token;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return NULL_SUBTREE;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
static void ts_parser__set_cached_token(
|
|
716
|
+
TSParser *self,
|
|
717
|
+
uint32_t byte_index,
|
|
718
|
+
Subtree last_external_token,
|
|
719
|
+
Subtree token
|
|
720
|
+
) {
|
|
721
|
+
TokenCache *cache = &self->token_cache;
|
|
722
|
+
if (token.ptr) ts_subtree_retain(token);
|
|
723
|
+
if (last_external_token.ptr) ts_subtree_retain(last_external_token);
|
|
724
|
+
if (cache->token.ptr) ts_subtree_release(&self->tree_pool, cache->token);
|
|
725
|
+
if (cache->last_external_token.ptr) ts_subtree_release(&self->tree_pool, cache->last_external_token);
|
|
726
|
+
cache->token = token;
|
|
727
|
+
cache->byte_index = byte_index;
|
|
728
|
+
cache->last_external_token = last_external_token;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
static bool ts_parser__has_included_range_difference(
|
|
732
|
+
const TSParser *self,
|
|
733
|
+
uint32_t start_position,
|
|
734
|
+
uint32_t end_position
|
|
735
|
+
) {
|
|
736
|
+
return ts_range_array_intersects(
|
|
737
|
+
&self->included_range_differences,
|
|
738
|
+
self->included_range_difference_index,
|
|
739
|
+
start_position,
|
|
740
|
+
end_position
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
static Subtree ts_parser__reuse_node(
|
|
745
|
+
TSParser *self,
|
|
746
|
+
StackVersion version,
|
|
747
|
+
TSStateId *state,
|
|
748
|
+
uint32_t position,
|
|
749
|
+
Subtree last_external_token,
|
|
750
|
+
TableEntry *table_entry
|
|
751
|
+
) {
|
|
752
|
+
Subtree result;
|
|
753
|
+
while ((result = reusable_node_tree(&self->reusable_node)).ptr) {
|
|
754
|
+
uint32_t byte_offset = reusable_node_byte_offset(&self->reusable_node);
|
|
755
|
+
uint32_t end_byte_offset = byte_offset + ts_subtree_total_bytes(result);
|
|
756
|
+
|
|
757
|
+
// Do not reuse an EOF node if the included ranges array has changes
|
|
758
|
+
// later on in the file.
|
|
759
|
+
if (ts_subtree_is_eof(result)) end_byte_offset = UINT32_MAX;
|
|
760
|
+
|
|
761
|
+
if (byte_offset > position) {
|
|
762
|
+
LOG("before_reusable_node symbol:%s", TREE_NAME(result));
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (byte_offset < position) {
|
|
767
|
+
LOG("past_reusable_node symbol:%s", TREE_NAME(result));
|
|
768
|
+
if (end_byte_offset <= position || !reusable_node_descend(&self->reusable_node)) {
|
|
769
|
+
reusable_node_advance(&self->reusable_node);
|
|
770
|
+
}
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (!ts_subtree_external_scanner_state_eq(self->reusable_node.last_external_token, last_external_token)) {
|
|
775
|
+
LOG("reusable_node_has_different_external_scanner_state symbol:%s", TREE_NAME(result));
|
|
776
|
+
reusable_node_advance(&self->reusable_node);
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
const char *reason = NULL;
|
|
781
|
+
if (ts_subtree_has_changes(result)) {
|
|
782
|
+
reason = "has_changes";
|
|
783
|
+
} else if (ts_subtree_is_error(result)) {
|
|
784
|
+
reason = "is_error";
|
|
785
|
+
} else if (ts_subtree_missing(result)) {
|
|
786
|
+
reason = "is_missing";
|
|
787
|
+
} else if (ts_subtree_is_fragile(result)) {
|
|
788
|
+
reason = "is_fragile";
|
|
789
|
+
} else if (ts_parser__has_included_range_difference(self, byte_offset, end_byte_offset)) {
|
|
790
|
+
reason = "contains_different_included_range";
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (reason) {
|
|
794
|
+
LOG("cant_reuse_node_%s tree:%s", reason, TREE_NAME(result));
|
|
795
|
+
if (!reusable_node_descend(&self->reusable_node)) {
|
|
796
|
+
reusable_node_advance(&self->reusable_node);
|
|
797
|
+
ts_parser__breakdown_top_of_stack(self, version);
|
|
798
|
+
*state = ts_stack_state(self->stack, version);
|
|
799
|
+
}
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
TSSymbol leaf_symbol = ts_subtree_leaf_symbol(result);
|
|
804
|
+
ts_language_table_entry(self->language, *state, leaf_symbol, table_entry);
|
|
805
|
+
if (!ts_parser__can_reuse_first_leaf(self, *state, result, table_entry)) {
|
|
806
|
+
LOG(
|
|
807
|
+
"cant_reuse_node symbol:%s, first_leaf_symbol:%s",
|
|
808
|
+
TREE_NAME(result),
|
|
809
|
+
SYM_NAME(leaf_symbol)
|
|
810
|
+
);
|
|
811
|
+
reusable_node_advance_past_leaf(&self->reusable_node);
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
LOG("reuse_node symbol:%s", TREE_NAME(result));
|
|
816
|
+
ts_subtree_retain(result);
|
|
817
|
+
return result;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return NULL_SUBTREE;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Determine if a given tree should be replaced by an alternative tree.
|
|
824
|
+
//
|
|
825
|
+
// The decision is based on the trees' error costs (if any), their dynamic precedence,
|
|
826
|
+
// and finally, as a default, by a recursive comparison of the trees' symbols.
|
|
827
|
+
static bool ts_parser__select_tree(TSParser *self, Subtree left, Subtree right) {
|
|
828
|
+
if (!left.ptr) return true;
|
|
829
|
+
if (!right.ptr) return false;
|
|
830
|
+
|
|
831
|
+
if (ts_subtree_error_cost(right) < ts_subtree_error_cost(left)) {
|
|
832
|
+
LOG("select_smaller_error symbol:%s, over_symbol:%s", TREE_NAME(right), TREE_NAME(left));
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (ts_subtree_error_cost(left) < ts_subtree_error_cost(right)) {
|
|
837
|
+
LOG("select_smaller_error symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right));
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (ts_subtree_dynamic_precedence(right) > ts_subtree_dynamic_precedence(left)) {
|
|
842
|
+
LOG("select_higher_precedence symbol:%s, prec:%" PRId32 ", over_symbol:%s, other_prec:%" PRId32,
|
|
843
|
+
TREE_NAME(right), ts_subtree_dynamic_precedence(right), TREE_NAME(left),
|
|
844
|
+
ts_subtree_dynamic_precedence(left));
|
|
845
|
+
return true;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
if (ts_subtree_dynamic_precedence(left) > ts_subtree_dynamic_precedence(right)) {
|
|
849
|
+
LOG("select_higher_precedence symbol:%s, prec:%" PRId32 ", over_symbol:%s, other_prec:%" PRId32,
|
|
850
|
+
TREE_NAME(left), ts_subtree_dynamic_precedence(left), TREE_NAME(right),
|
|
851
|
+
ts_subtree_dynamic_precedence(right));
|
|
852
|
+
return false;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (ts_subtree_error_cost(left) > 0) return true;
|
|
856
|
+
|
|
857
|
+
int comparison = ts_subtree_compare(left, right, &self->tree_pool);
|
|
858
|
+
switch (comparison) {
|
|
859
|
+
case -1:
|
|
860
|
+
LOG("select_earlier symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right));
|
|
861
|
+
return false;
|
|
862
|
+
break;
|
|
863
|
+
case 1:
|
|
864
|
+
LOG("select_earlier symbol:%s, over_symbol:%s", TREE_NAME(right), TREE_NAME(left));
|
|
865
|
+
return true;
|
|
866
|
+
default:
|
|
867
|
+
LOG("select_existing symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right));
|
|
868
|
+
return false;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// Determine if a given tree's children should be replaced by an alternative
|
|
873
|
+
// array of children.
|
|
874
|
+
static bool ts_parser__select_children(
|
|
875
|
+
TSParser *self,
|
|
876
|
+
Subtree left,
|
|
877
|
+
const SubtreeArray *children
|
|
878
|
+
) {
|
|
879
|
+
array_assign(&self->scratch_trees, children);
|
|
880
|
+
|
|
881
|
+
// Create a temporary subtree using the scratch trees array. This node does
|
|
882
|
+
// not perform any allocation except for possibly growing the array to make
|
|
883
|
+
// room for its own heap data. The scratch tree is never explicitly released,
|
|
884
|
+
// so the same 'scratch trees' array can be reused again later.
|
|
885
|
+
MutableSubtree scratch_tree = ts_subtree_new_node(
|
|
886
|
+
ts_subtree_symbol(left),
|
|
887
|
+
&self->scratch_trees,
|
|
888
|
+
0,
|
|
889
|
+
self->language
|
|
890
|
+
);
|
|
891
|
+
|
|
892
|
+
return ts_parser__select_tree(
|
|
893
|
+
self,
|
|
894
|
+
left,
|
|
895
|
+
ts_subtree_from_mut(scratch_tree)
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
static void ts_parser__shift(
|
|
900
|
+
TSParser *self,
|
|
901
|
+
StackVersion version,
|
|
902
|
+
TSStateId state,
|
|
903
|
+
Subtree lookahead,
|
|
904
|
+
bool extra
|
|
905
|
+
) {
|
|
906
|
+
bool is_leaf = ts_subtree_child_count(lookahead) == 0;
|
|
907
|
+
Subtree subtree_to_push = lookahead;
|
|
908
|
+
if (extra != ts_subtree_extra(lookahead) && is_leaf) {
|
|
909
|
+
MutableSubtree result = ts_subtree_make_mut(&self->tree_pool, lookahead);
|
|
910
|
+
ts_subtree_set_extra(&result, extra);
|
|
911
|
+
subtree_to_push = ts_subtree_from_mut(result);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
ts_stack_push(self->stack, version, subtree_to_push, !is_leaf, state);
|
|
915
|
+
if (ts_subtree_has_external_tokens(subtree_to_push)) {
|
|
916
|
+
ts_stack_set_last_external_token(
|
|
917
|
+
self->stack, version, ts_subtree_last_external_token(subtree_to_push)
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
static StackVersion ts_parser__reduce(
|
|
923
|
+
TSParser *self,
|
|
924
|
+
StackVersion version,
|
|
925
|
+
TSSymbol symbol,
|
|
926
|
+
uint32_t count,
|
|
927
|
+
int dynamic_precedence,
|
|
928
|
+
uint16_t production_id,
|
|
929
|
+
bool is_fragile,
|
|
930
|
+
bool end_of_non_terminal_extra
|
|
931
|
+
) {
|
|
932
|
+
uint32_t initial_version_count = ts_stack_version_count(self->stack);
|
|
933
|
+
|
|
934
|
+
// Pop the given number of nodes from the given version of the parse stack.
|
|
935
|
+
// If stack versions have previously merged, then there may be more than one
|
|
936
|
+
// path back through the stack. For each path, create a new parent node to
|
|
937
|
+
// contain the popped children, and push it onto the stack in place of the
|
|
938
|
+
// children.
|
|
939
|
+
StackSliceArray pop = ts_stack_pop_count(self->stack, version, count);
|
|
940
|
+
uint32_t removed_version_count = 0;
|
|
941
|
+
for (uint32_t i = 0; i < pop.size; i++) {
|
|
942
|
+
StackSlice slice = pop.contents[i];
|
|
943
|
+
StackVersion slice_version = slice.version - removed_version_count;
|
|
944
|
+
|
|
945
|
+
// This is where new versions are added to the parse stack. The versions
|
|
946
|
+
// will all be sorted and truncated at the end of the outer parsing loop.
|
|
947
|
+
// Allow the maximum version count to be temporarily exceeded, but only
|
|
948
|
+
// by a limited threshold.
|
|
949
|
+
if (slice_version > MAX_VERSION_COUNT + MAX_VERSION_COUNT_OVERFLOW) {
|
|
950
|
+
ts_stack_remove_version(self->stack, slice_version);
|
|
951
|
+
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
|
952
|
+
removed_version_count++;
|
|
953
|
+
while (i + 1 < pop.size) {
|
|
954
|
+
StackSlice next_slice = pop.contents[i + 1];
|
|
955
|
+
if (next_slice.version != slice.version) break;
|
|
956
|
+
ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees);
|
|
957
|
+
i++;
|
|
958
|
+
}
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// Extra tokens on top of the stack should not be included in this new parent
|
|
963
|
+
// node. They will be re-pushed onto the stack after the parent node is
|
|
964
|
+
// created and pushed.
|
|
965
|
+
SubtreeArray children = slice.subtrees;
|
|
966
|
+
ts_subtree_array_remove_trailing_extras(&children, &self->trailing_extras);
|
|
967
|
+
|
|
968
|
+
MutableSubtree parent = ts_subtree_new_node(
|
|
969
|
+
symbol, &children, production_id, self->language
|
|
970
|
+
);
|
|
971
|
+
|
|
972
|
+
// This pop operation may have caused multiple stack versions to collapse
|
|
973
|
+
// into one, because they all diverged from a common state. In that case,
|
|
974
|
+
// choose one of the arrays of trees to be the parent node's children, and
|
|
975
|
+
// delete the rest of the tree arrays.
|
|
976
|
+
while (i + 1 < pop.size) {
|
|
977
|
+
StackSlice next_slice = pop.contents[i + 1];
|
|
978
|
+
if (next_slice.version != slice.version) break;
|
|
979
|
+
i++;
|
|
980
|
+
|
|
981
|
+
SubtreeArray next_slice_children = next_slice.subtrees;
|
|
982
|
+
ts_subtree_array_remove_trailing_extras(&next_slice_children, &self->trailing_extras2);
|
|
983
|
+
|
|
984
|
+
if (ts_parser__select_children(
|
|
985
|
+
self,
|
|
986
|
+
ts_subtree_from_mut(parent),
|
|
987
|
+
&next_slice_children
|
|
988
|
+
)) {
|
|
989
|
+
ts_subtree_array_clear(&self->tree_pool, &self->trailing_extras);
|
|
990
|
+
ts_subtree_release(&self->tree_pool, ts_subtree_from_mut(parent));
|
|
991
|
+
array_swap(&self->trailing_extras, &self->trailing_extras2);
|
|
992
|
+
parent = ts_subtree_new_node(
|
|
993
|
+
symbol, &next_slice_children, production_id, self->language
|
|
994
|
+
);
|
|
995
|
+
} else {
|
|
996
|
+
array_clear(&self->trailing_extras2);
|
|
997
|
+
ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
TSStateId state = ts_stack_state(self->stack, slice_version);
|
|
1002
|
+
TSStateId next_state = ts_language_next_state(self->language, state, symbol);
|
|
1003
|
+
if (end_of_non_terminal_extra && next_state == state) {
|
|
1004
|
+
parent.ptr->extra = true;
|
|
1005
|
+
}
|
|
1006
|
+
if (is_fragile || pop.size > 1 || initial_version_count > 1) {
|
|
1007
|
+
parent.ptr->fragile_left = true;
|
|
1008
|
+
parent.ptr->fragile_right = true;
|
|
1009
|
+
parent.ptr->parse_state = TS_TREE_STATE_NONE;
|
|
1010
|
+
} else {
|
|
1011
|
+
parent.ptr->parse_state = state;
|
|
1012
|
+
}
|
|
1013
|
+
parent.ptr->dynamic_precedence += dynamic_precedence;
|
|
1014
|
+
|
|
1015
|
+
// Push the parent node onto the stack, along with any extra tokens that
|
|
1016
|
+
// were previously on top of the stack.
|
|
1017
|
+
ts_stack_push(self->stack, slice_version, ts_subtree_from_mut(parent), false, next_state);
|
|
1018
|
+
for (uint32_t j = 0; j < self->trailing_extras.size; j++) {
|
|
1019
|
+
ts_stack_push(self->stack, slice_version, self->trailing_extras.contents[j], false, next_state);
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
for (StackVersion j = 0; j < slice_version; j++) {
|
|
1023
|
+
if (j == version) continue;
|
|
1024
|
+
if (ts_stack_merge(self->stack, j, slice_version)) {
|
|
1025
|
+
removed_version_count++;
|
|
1026
|
+
break;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Return the first new stack version that was created.
|
|
1032
|
+
return ts_stack_version_count(self->stack) > initial_version_count
|
|
1033
|
+
? initial_version_count
|
|
1034
|
+
: STACK_VERSION_NONE;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
static void ts_parser__accept(
|
|
1038
|
+
TSParser *self,
|
|
1039
|
+
StackVersion version,
|
|
1040
|
+
Subtree lookahead
|
|
1041
|
+
) {
|
|
1042
|
+
ts_assert(ts_subtree_is_eof(lookahead));
|
|
1043
|
+
ts_stack_push(self->stack, version, lookahead, false, 1);
|
|
1044
|
+
|
|
1045
|
+
StackSliceArray pop = ts_stack_pop_all(self->stack, version);
|
|
1046
|
+
for (uint32_t i = 0; i < pop.size; i++) {
|
|
1047
|
+
SubtreeArray trees = pop.contents[i].subtrees;
|
|
1048
|
+
|
|
1049
|
+
Subtree root = NULL_SUBTREE;
|
|
1050
|
+
for (uint32_t j = trees.size - 1; j + 1 > 0; j--) {
|
|
1051
|
+
Subtree tree = trees.contents[j];
|
|
1052
|
+
if (!ts_subtree_extra(tree)) {
|
|
1053
|
+
ts_assert(!tree.data.is_inline);
|
|
1054
|
+
uint32_t child_count = ts_subtree_child_count(tree);
|
|
1055
|
+
const Subtree *children = ts_subtree_children(tree);
|
|
1056
|
+
for (uint32_t k = 0; k < child_count; k++) {
|
|
1057
|
+
ts_subtree_retain(children[k]);
|
|
1058
|
+
}
|
|
1059
|
+
array_splice(&trees, j, 1, child_count, children);
|
|
1060
|
+
root = ts_subtree_from_mut(ts_subtree_new_node(
|
|
1061
|
+
ts_subtree_symbol(tree),
|
|
1062
|
+
&trees,
|
|
1063
|
+
tree.ptr->production_id,
|
|
1064
|
+
self->language
|
|
1065
|
+
));
|
|
1066
|
+
ts_subtree_release(&self->tree_pool, tree);
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
ts_assert(root.ptr);
|
|
1072
|
+
self->accept_count++;
|
|
1073
|
+
|
|
1074
|
+
if (self->finished_tree.ptr) {
|
|
1075
|
+
if (ts_parser__select_tree(self, self->finished_tree, root)) {
|
|
1076
|
+
ts_subtree_release(&self->tree_pool, self->finished_tree);
|
|
1077
|
+
self->finished_tree = root;
|
|
1078
|
+
} else {
|
|
1079
|
+
ts_subtree_release(&self->tree_pool, root);
|
|
1080
|
+
}
|
|
1081
|
+
} else {
|
|
1082
|
+
self->finished_tree = root;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
ts_stack_remove_version(self->stack, pop.contents[0].version);
|
|
1087
|
+
ts_stack_halt(self->stack, version);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
static bool ts_parser__do_all_potential_reductions(
|
|
1091
|
+
TSParser *self,
|
|
1092
|
+
StackVersion starting_version,
|
|
1093
|
+
TSSymbol lookahead_symbol
|
|
1094
|
+
) {
|
|
1095
|
+
uint32_t initial_version_count = ts_stack_version_count(self->stack);
|
|
1096
|
+
|
|
1097
|
+
bool can_shift_lookahead_symbol = false;
|
|
1098
|
+
StackVersion version = starting_version;
|
|
1099
|
+
for (unsigned i = 0; true; i++) {
|
|
1100
|
+
uint32_t version_count = ts_stack_version_count(self->stack);
|
|
1101
|
+
if (version >= version_count) break;
|
|
1102
|
+
|
|
1103
|
+
bool merged = false;
|
|
1104
|
+
for (StackVersion j = initial_version_count; j < version; j++) {
|
|
1105
|
+
if (ts_stack_merge(self->stack, j, version)) {
|
|
1106
|
+
merged = true;
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
if (merged) continue;
|
|
1111
|
+
|
|
1112
|
+
TSStateId state = ts_stack_state(self->stack, version);
|
|
1113
|
+
bool has_shift_action = false;
|
|
1114
|
+
array_clear(&self->reduce_actions);
|
|
1115
|
+
|
|
1116
|
+
TSSymbol first_symbol, end_symbol;
|
|
1117
|
+
if (lookahead_symbol != 0) {
|
|
1118
|
+
first_symbol = lookahead_symbol;
|
|
1119
|
+
end_symbol = lookahead_symbol + 1;
|
|
1120
|
+
} else {
|
|
1121
|
+
first_symbol = 1;
|
|
1122
|
+
end_symbol = self->language->token_count;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
for (TSSymbol symbol = first_symbol; symbol < end_symbol; symbol++) {
|
|
1126
|
+
TableEntry entry;
|
|
1127
|
+
ts_language_table_entry(self->language, state, symbol, &entry);
|
|
1128
|
+
for (uint32_t j = 0; j < entry.action_count; j++) {
|
|
1129
|
+
TSParseAction action = entry.actions[j];
|
|
1130
|
+
switch (action.type) {
|
|
1131
|
+
case TSParseActionTypeShift:
|
|
1132
|
+
case TSParseActionTypeRecover:
|
|
1133
|
+
if (!action.shift.extra && !action.shift.repetition) has_shift_action = true;
|
|
1134
|
+
break;
|
|
1135
|
+
case TSParseActionTypeReduce:
|
|
1136
|
+
if (action.reduce.child_count > 0)
|
|
1137
|
+
ts_reduce_action_set_add(&self->reduce_actions, (ReduceAction) {
|
|
1138
|
+
.symbol = action.reduce.symbol,
|
|
1139
|
+
.count = action.reduce.child_count,
|
|
1140
|
+
.dynamic_precedence = action.reduce.dynamic_precedence,
|
|
1141
|
+
.production_id = action.reduce.production_id,
|
|
1142
|
+
});
|
|
1143
|
+
break;
|
|
1144
|
+
default:
|
|
1145
|
+
break;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
StackVersion reduction_version = STACK_VERSION_NONE;
|
|
1151
|
+
for (uint32_t j = 0; j < self->reduce_actions.size; j++) {
|
|
1152
|
+
ReduceAction action = self->reduce_actions.contents[j];
|
|
1153
|
+
|
|
1154
|
+
reduction_version = ts_parser__reduce(
|
|
1155
|
+
self, version, action.symbol, action.count,
|
|
1156
|
+
action.dynamic_precedence, action.production_id,
|
|
1157
|
+
true, false
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
if (has_shift_action) {
|
|
1162
|
+
can_shift_lookahead_symbol = true;
|
|
1163
|
+
} else if (reduction_version != STACK_VERSION_NONE && i < MAX_VERSION_COUNT) {
|
|
1164
|
+
ts_stack_renumber_version(self->stack, reduction_version, version);
|
|
1165
|
+
continue;
|
|
1166
|
+
} else if (lookahead_symbol != 0) {
|
|
1167
|
+
ts_stack_remove_version(self->stack, version);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
if (version == starting_version) {
|
|
1171
|
+
version = version_count;
|
|
1172
|
+
} else {
|
|
1173
|
+
version++;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
return can_shift_lookahead_symbol;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
static bool ts_parser__recover_to_state(
|
|
1181
|
+
TSParser *self,
|
|
1182
|
+
StackVersion version,
|
|
1183
|
+
unsigned depth,
|
|
1184
|
+
TSStateId goal_state
|
|
1185
|
+
) {
|
|
1186
|
+
StackSliceArray pop = ts_stack_pop_count(self->stack, version, depth);
|
|
1187
|
+
StackVersion previous_version = STACK_VERSION_NONE;
|
|
1188
|
+
|
|
1189
|
+
for (unsigned i = 0; i < pop.size; i++) {
|
|
1190
|
+
StackSlice slice = pop.contents[i];
|
|
1191
|
+
|
|
1192
|
+
if (slice.version == previous_version) {
|
|
1193
|
+
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
|
1194
|
+
array_erase(&pop, i--);
|
|
1195
|
+
continue;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
if (ts_stack_state(self->stack, slice.version) != goal_state) {
|
|
1199
|
+
ts_stack_halt(self->stack, slice.version);
|
|
1200
|
+
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
|
1201
|
+
array_erase(&pop, i--);
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
|
|
1206
|
+
if (error_trees.size > 0) {
|
|
1207
|
+
ts_assert(error_trees.size == 1);
|
|
1208
|
+
Subtree error_tree = error_trees.contents[0];
|
|
1209
|
+
uint32_t error_child_count = ts_subtree_child_count(error_tree);
|
|
1210
|
+
if (error_child_count > 0) {
|
|
1211
|
+
array_splice(&slice.subtrees, 0, 0, error_child_count, ts_subtree_children(error_tree));
|
|
1212
|
+
for (unsigned j = 0; j < error_child_count; j++) {
|
|
1213
|
+
ts_subtree_retain(slice.subtrees.contents[j]);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
ts_subtree_array_delete(&self->tree_pool, &error_trees);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
ts_subtree_array_remove_trailing_extras(&slice.subtrees, &self->trailing_extras);
|
|
1220
|
+
|
|
1221
|
+
if (slice.subtrees.size > 0) {
|
|
1222
|
+
Subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language);
|
|
1223
|
+
ts_stack_push(self->stack, slice.version, error, false, goal_state);
|
|
1224
|
+
} else {
|
|
1225
|
+
array_delete(&slice.subtrees);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
for (unsigned j = 0; j < self->trailing_extras.size; j++) {
|
|
1229
|
+
Subtree tree = self->trailing_extras.contents[j];
|
|
1230
|
+
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
previous_version = slice.version;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
return previous_version != STACK_VERSION_NONE;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
static void ts_parser__recover(
|
|
1240
|
+
TSParser *self,
|
|
1241
|
+
StackVersion version,
|
|
1242
|
+
Subtree lookahead
|
|
1243
|
+
) {
|
|
1244
|
+
bool did_recover = false;
|
|
1245
|
+
unsigned previous_version_count = ts_stack_version_count(self->stack);
|
|
1246
|
+
Length position = ts_stack_position(self->stack, version);
|
|
1247
|
+
StackSummary *summary = ts_stack_get_summary(self->stack, version);
|
|
1248
|
+
unsigned node_count_since_error = ts_stack_node_count_since_error(self->stack, version);
|
|
1249
|
+
unsigned current_error_cost = ts_stack_error_cost(self->stack, version);
|
|
1250
|
+
|
|
1251
|
+
// When the parser is in the error state, there are two strategies for recovering with a
|
|
1252
|
+
// given lookahead token:
|
|
1253
|
+
// 1. Find a previous state on the stack in which that lookahead token would be valid. Then,
|
|
1254
|
+
// create a new stack version that is in that state again. This entails popping all of the
|
|
1255
|
+
// subtrees that have been pushed onto the stack since that previous state, and wrapping
|
|
1256
|
+
// them in an ERROR node.
|
|
1257
|
+
// 2. Wrap the lookahead token in an ERROR node, push that ERROR node onto the stack, and
|
|
1258
|
+
// move on to the next lookahead token, remaining in the error state.
|
|
1259
|
+
//
|
|
1260
|
+
// First, try the strategy 1. Upon entering the error state, the parser recorded a summary
|
|
1261
|
+
// of the previous parse states and their depths. Look at each state in the summary, to see
|
|
1262
|
+
// if the current lookahead token would be valid in that state.
|
|
1263
|
+
if (summary && !ts_subtree_is_error(lookahead)) {
|
|
1264
|
+
for (unsigned i = 0; i < summary->size; i++) {
|
|
1265
|
+
StackSummaryEntry entry = summary->contents[i];
|
|
1266
|
+
|
|
1267
|
+
if (entry.state == ERROR_STATE) continue;
|
|
1268
|
+
if (entry.position.bytes == position.bytes) continue;
|
|
1269
|
+
unsigned depth = entry.depth;
|
|
1270
|
+
if (node_count_since_error > 0) depth++;
|
|
1271
|
+
|
|
1272
|
+
// Do not recover in ways that create redundant stack versions.
|
|
1273
|
+
bool would_merge = false;
|
|
1274
|
+
for (unsigned j = 0; j < previous_version_count; j++) {
|
|
1275
|
+
if (
|
|
1276
|
+
ts_stack_state(self->stack, j) == entry.state &&
|
|
1277
|
+
ts_stack_position(self->stack, j).bytes == position.bytes
|
|
1278
|
+
) {
|
|
1279
|
+
would_merge = true;
|
|
1280
|
+
break;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (would_merge) continue;
|
|
1284
|
+
|
|
1285
|
+
// Do not recover if the result would clearly be worse than some existing stack version.
|
|
1286
|
+
unsigned new_cost =
|
|
1287
|
+
current_error_cost +
|
|
1288
|
+
entry.depth * ERROR_COST_PER_SKIPPED_TREE +
|
|
1289
|
+
(position.bytes - entry.position.bytes) * ERROR_COST_PER_SKIPPED_CHAR +
|
|
1290
|
+
(position.extent.row - entry.position.extent.row) * ERROR_COST_PER_SKIPPED_LINE;
|
|
1291
|
+
if (ts_parser__better_version_exists(self, version, false, new_cost)) break;
|
|
1292
|
+
|
|
1293
|
+
// If the current lookahead token is valid in some previous state, recover to that state.
|
|
1294
|
+
// Then stop looking for further recoveries.
|
|
1295
|
+
if (ts_language_has_actions(self->language, entry.state, ts_subtree_symbol(lookahead))) {
|
|
1296
|
+
if (ts_parser__recover_to_state(self, version, depth, entry.state)) {
|
|
1297
|
+
did_recover = true;
|
|
1298
|
+
LOG("recover_to_previous state:%u, depth:%u", entry.state, depth);
|
|
1299
|
+
LOG_STACK();
|
|
1300
|
+
break;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// In the process of attempting to recover, some stack versions may have been created
|
|
1307
|
+
// and subsequently halted. Remove those versions.
|
|
1308
|
+
for (unsigned i = previous_version_count; i < ts_stack_version_count(self->stack); i++) {
|
|
1309
|
+
if (!ts_stack_is_active(self->stack, i)) {
|
|
1310
|
+
ts_stack_remove_version(self->stack, i--);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
// If strategy 1 succeeded, a new stack version will have been created which is able to handle
|
|
1315
|
+
// the current lookahead token. Now, in addition, try strategy 2 described above: skip the
|
|
1316
|
+
// current lookahead token by wrapping it in an ERROR node.
|
|
1317
|
+
|
|
1318
|
+
// Don't pursue this additional strategy if there are already too many stack versions.
|
|
1319
|
+
if (did_recover && ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) {
|
|
1320
|
+
ts_stack_halt(self->stack, version);
|
|
1321
|
+
ts_subtree_release(&self->tree_pool, lookahead);
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
if (
|
|
1326
|
+
did_recover &&
|
|
1327
|
+
ts_subtree_has_external_scanner_state_change(lookahead)
|
|
1328
|
+
) {
|
|
1329
|
+
ts_stack_halt(self->stack, version);
|
|
1330
|
+
ts_subtree_release(&self->tree_pool, lookahead);
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// If the parser is still in the error state at the end of the file, just wrap everything
|
|
1335
|
+
// in an ERROR node and terminate.
|
|
1336
|
+
if (ts_subtree_is_eof(lookahead)) {
|
|
1337
|
+
LOG("recover_eof");
|
|
1338
|
+
SubtreeArray children = array_new();
|
|
1339
|
+
Subtree parent = ts_subtree_new_error_node(&children, false, self->language);
|
|
1340
|
+
ts_stack_push(self->stack, version, parent, false, 1);
|
|
1341
|
+
ts_parser__accept(self, version, lookahead);
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// Do not recover if the result would clearly be worse than some existing stack version.
|
|
1346
|
+
unsigned new_cost =
|
|
1347
|
+
current_error_cost + ERROR_COST_PER_SKIPPED_TREE +
|
|
1348
|
+
ts_subtree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR +
|
|
1349
|
+
ts_subtree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE;
|
|
1350
|
+
if (ts_parser__better_version_exists(self, version, false, new_cost)) {
|
|
1351
|
+
ts_stack_halt(self->stack, version);
|
|
1352
|
+
ts_subtree_release(&self->tree_pool, lookahead);
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// If the current lookahead token is an extra token, mark it as extra. This means it won't
|
|
1357
|
+
// be counted in error cost calculations.
|
|
1358
|
+
unsigned n;
|
|
1359
|
+
const TSParseAction *actions = ts_language_actions(self->language, 1, ts_subtree_symbol(lookahead), &n);
|
|
1360
|
+
if (n > 0 && actions[n - 1].type == TSParseActionTypeShift && actions[n - 1].shift.extra) {
|
|
1361
|
+
MutableSubtree mutable_lookahead = ts_subtree_make_mut(&self->tree_pool, lookahead);
|
|
1362
|
+
ts_subtree_set_extra(&mutable_lookahead, true);
|
|
1363
|
+
lookahead = ts_subtree_from_mut(mutable_lookahead);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Wrap the lookahead token in an ERROR.
|
|
1367
|
+
LOG("skip_token symbol:%s", TREE_NAME(lookahead));
|
|
1368
|
+
SubtreeArray children = array_new();
|
|
1369
|
+
array_reserve(&children, 1);
|
|
1370
|
+
array_push(&children, lookahead);
|
|
1371
|
+
MutableSubtree error_repeat = ts_subtree_new_node(
|
|
1372
|
+
ts_builtin_sym_error_repeat,
|
|
1373
|
+
&children,
|
|
1374
|
+
0,
|
|
1375
|
+
self->language
|
|
1376
|
+
);
|
|
1377
|
+
|
|
1378
|
+
// If other tokens have already been skipped, so there is already an ERROR at the top of the
|
|
1379
|
+
// stack, then pop that ERROR off the stack and wrap the two ERRORs together into one larger
|
|
1380
|
+
// ERROR.
|
|
1381
|
+
if (node_count_since_error > 0) {
|
|
1382
|
+
StackSliceArray pop = ts_stack_pop_count(self->stack, version, 1);
|
|
1383
|
+
|
|
1384
|
+
// TODO: Figure out how to make this condition occur.
|
|
1385
|
+
// See https://github.com/atom/atom/issues/18450#issuecomment-439579778
|
|
1386
|
+
// If multiple stack versions have merged at this point, just pick one of the errors
|
|
1387
|
+
// arbitrarily and discard the rest.
|
|
1388
|
+
if (pop.size > 1) {
|
|
1389
|
+
for (unsigned i = 1; i < pop.size; i++) {
|
|
1390
|
+
ts_subtree_array_delete(&self->tree_pool, &pop.contents[i].subtrees);
|
|
1391
|
+
}
|
|
1392
|
+
while (ts_stack_version_count(self->stack) > pop.contents[0].version + 1) {
|
|
1393
|
+
ts_stack_remove_version(self->stack, pop.contents[0].version + 1);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
ts_stack_renumber_version(self->stack, pop.contents[0].version, version);
|
|
1398
|
+
array_push(&pop.contents[0].subtrees, ts_subtree_from_mut(error_repeat));
|
|
1399
|
+
error_repeat = ts_subtree_new_node(
|
|
1400
|
+
ts_builtin_sym_error_repeat,
|
|
1401
|
+
&pop.contents[0].subtrees,
|
|
1402
|
+
0,
|
|
1403
|
+
self->language
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
// Push the new ERROR onto the stack.
|
|
1408
|
+
ts_stack_push(self->stack, version, ts_subtree_from_mut(error_repeat), false, ERROR_STATE);
|
|
1409
|
+
if (ts_subtree_has_external_tokens(lookahead)) {
|
|
1410
|
+
ts_stack_set_last_external_token(
|
|
1411
|
+
self->stack, version, ts_subtree_last_external_token(lookahead)
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
static void ts_parser__handle_error(
|
|
1417
|
+
TSParser *self,
|
|
1418
|
+
StackVersion version,
|
|
1419
|
+
Subtree lookahead
|
|
1420
|
+
) {
|
|
1421
|
+
uint32_t previous_version_count = ts_stack_version_count(self->stack);
|
|
1422
|
+
|
|
1423
|
+
// Perform any reductions that can happen in this state, regardless of the lookahead. After
|
|
1424
|
+
// skipping one or more invalid tokens, the parser might find a token that would have allowed
|
|
1425
|
+
// a reduction to take place.
|
|
1426
|
+
ts_parser__do_all_potential_reductions(self, version, 0);
|
|
1427
|
+
uint32_t version_count = ts_stack_version_count(self->stack);
|
|
1428
|
+
Length position = ts_stack_position(self->stack, version);
|
|
1429
|
+
|
|
1430
|
+
// Push a discontinuity onto the stack. Merge all of the stack versions that
|
|
1431
|
+
// were created in the previous step.
|
|
1432
|
+
bool did_insert_missing_token = false;
|
|
1433
|
+
for (StackVersion v = version; v < version_count;) {
|
|
1434
|
+
if (!did_insert_missing_token) {
|
|
1435
|
+
TSStateId state = ts_stack_state(self->stack, v);
|
|
1436
|
+
for (
|
|
1437
|
+
TSSymbol missing_symbol = 1;
|
|
1438
|
+
missing_symbol < (uint16_t)self->language->token_count;
|
|
1439
|
+
missing_symbol++
|
|
1440
|
+
) {
|
|
1441
|
+
TSStateId state_after_missing_symbol = ts_language_next_state(
|
|
1442
|
+
self->language, state, missing_symbol
|
|
1443
|
+
);
|
|
1444
|
+
if (state_after_missing_symbol == 0 || state_after_missing_symbol == state) {
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
if (ts_language_has_reduce_action(
|
|
1449
|
+
self->language,
|
|
1450
|
+
state_after_missing_symbol,
|
|
1451
|
+
ts_subtree_leaf_symbol(lookahead)
|
|
1452
|
+
)) {
|
|
1453
|
+
// In case the parser is currently outside of any included range, the lexer will
|
|
1454
|
+
// snap to the beginning of the next included range. The missing token's padding
|
|
1455
|
+
// must be assigned to position it within the next included range.
|
|
1456
|
+
ts_lexer_reset(&self->lexer, position);
|
|
1457
|
+
ts_lexer_mark_end(&self->lexer);
|
|
1458
|
+
Length padding = length_sub(self->lexer.token_end_position, position);
|
|
1459
|
+
uint32_t lookahead_bytes = ts_subtree_total_bytes(lookahead) + ts_subtree_lookahead_bytes(lookahead);
|
|
1460
|
+
|
|
1461
|
+
StackVersion version_with_missing_tree = ts_stack_copy_version(self->stack, v);
|
|
1462
|
+
Subtree missing_tree = ts_subtree_new_missing_leaf(
|
|
1463
|
+
&self->tree_pool, missing_symbol,
|
|
1464
|
+
padding, lookahead_bytes,
|
|
1465
|
+
self->language
|
|
1466
|
+
);
|
|
1467
|
+
ts_stack_push(
|
|
1468
|
+
self->stack, version_with_missing_tree,
|
|
1469
|
+
missing_tree, false,
|
|
1470
|
+
state_after_missing_symbol
|
|
1471
|
+
);
|
|
1472
|
+
|
|
1473
|
+
if (ts_parser__do_all_potential_reductions(
|
|
1474
|
+
self, version_with_missing_tree,
|
|
1475
|
+
ts_subtree_leaf_symbol(lookahead)
|
|
1476
|
+
)) {
|
|
1477
|
+
LOG(
|
|
1478
|
+
"recover_with_missing symbol:%s, state:%u",
|
|
1479
|
+
SYM_NAME(missing_symbol),
|
|
1480
|
+
ts_stack_state(self->stack, version_with_missing_tree)
|
|
1481
|
+
);
|
|
1482
|
+
did_insert_missing_token = true;
|
|
1483
|
+
break;
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
ts_stack_push(self->stack, v, NULL_SUBTREE, false, ERROR_STATE);
|
|
1490
|
+
v = (v == version) ? previous_version_count : v + 1;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
for (unsigned i = previous_version_count; i < version_count; i++) {
|
|
1494
|
+
bool did_merge = ts_stack_merge(self->stack, version, previous_version_count);
|
|
1495
|
+
ts_assert(did_merge);
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
ts_stack_record_summary(self->stack, version, MAX_SUMMARY_DEPTH);
|
|
1499
|
+
|
|
1500
|
+
// Begin recovery with the current lookahead node, rather than waiting for the
|
|
1501
|
+
// next turn of the parse loop. This ensures that the tree accounts for the
|
|
1502
|
+
// current lookahead token's "lookahead bytes" value, which describes how far
|
|
1503
|
+
// the lexer needed to look ahead beyond the content of the token in order to
|
|
1504
|
+
// recognize it.
|
|
1505
|
+
if (ts_subtree_child_count(lookahead) > 0) {
|
|
1506
|
+
ts_parser__breakdown_lookahead(self, &lookahead, ERROR_STATE, &self->reusable_node);
|
|
1507
|
+
}
|
|
1508
|
+
ts_parser__recover(self, version, lookahead);
|
|
1509
|
+
|
|
1510
|
+
LOG_STACK();
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
static bool ts_parser__advance(
|
|
1514
|
+
TSParser *self,
|
|
1515
|
+
StackVersion version,
|
|
1516
|
+
bool allow_node_reuse
|
|
1517
|
+
) {
|
|
1518
|
+
TSStateId state = ts_stack_state(self->stack, version);
|
|
1519
|
+
uint32_t position = ts_stack_position(self->stack, version).bytes;
|
|
1520
|
+
Subtree last_external_token = ts_stack_last_external_token(self->stack, version);
|
|
1521
|
+
|
|
1522
|
+
bool did_reuse = true;
|
|
1523
|
+
Subtree lookahead = NULL_SUBTREE;
|
|
1524
|
+
TableEntry table_entry = {.action_count = 0};
|
|
1525
|
+
|
|
1526
|
+
// If possible, reuse a node from the previous syntax tree.
|
|
1527
|
+
if (allow_node_reuse) {
|
|
1528
|
+
lookahead = ts_parser__reuse_node(
|
|
1529
|
+
self, version, &state, position, last_external_token, &table_entry
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
// If no node from the previous syntax tree could be reused, then try to
|
|
1534
|
+
// reuse the token previously returned by the lexer.
|
|
1535
|
+
if (!lookahead.ptr) {
|
|
1536
|
+
did_reuse = false;
|
|
1537
|
+
lookahead = ts_parser__get_cached_token(
|
|
1538
|
+
self, state, position, last_external_token, &table_entry
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
bool needs_lex = !lookahead.ptr;
|
|
1543
|
+
for (;;) {
|
|
1544
|
+
// Otherwise, re-run the lexer.
|
|
1545
|
+
if (needs_lex) {
|
|
1546
|
+
needs_lex = false;
|
|
1547
|
+
lookahead = ts_parser__lex(self, version, state);
|
|
1548
|
+
if (self->has_scanner_error) return false;
|
|
1549
|
+
|
|
1550
|
+
if (lookahead.ptr) {
|
|
1551
|
+
ts_parser__set_cached_token(self, position, last_external_token, lookahead);
|
|
1552
|
+
ts_language_table_entry(self->language, state, ts_subtree_symbol(lookahead), &table_entry);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
// When parsing a non-terminal extra, a null lookahead indicates the
|
|
1556
|
+
// end of the rule. The reduction is stored in the EOF table entry.
|
|
1557
|
+
// After the reduction, the lexer needs to be run again.
|
|
1558
|
+
else {
|
|
1559
|
+
ts_language_table_entry(self->language, state, ts_builtin_sym_end, &table_entry);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
// If a cancellation flag or a timeout was provided, then check every
|
|
1564
|
+
// time a fixed number of parse actions has been processed.
|
|
1565
|
+
if (++self->operation_count == OP_COUNT_PER_PARSER_TIMEOUT_CHECK) {
|
|
1566
|
+
self->operation_count = 0;
|
|
1567
|
+
}
|
|
1568
|
+
if (
|
|
1569
|
+
self->operation_count == 0 &&
|
|
1570
|
+
((self->cancellation_flag && atomic_load(self->cancellation_flag)) ||
|
|
1571
|
+
(!clock_is_null(self->end_clock) && clock_is_gt(clock_now(), self->end_clock)))
|
|
1572
|
+
) {
|
|
1573
|
+
if (lookahead.ptr) {
|
|
1574
|
+
ts_subtree_release(&self->tree_pool, lookahead);
|
|
1575
|
+
}
|
|
1576
|
+
return false;
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// Process each parse action for the current lookahead token in
|
|
1580
|
+
// the current state. If there are multiple actions, then this is
|
|
1581
|
+
// an ambiguous state. REDUCE actions always create a new stack
|
|
1582
|
+
// version, whereas SHIFT actions update the existing stack version
|
|
1583
|
+
// and terminate this loop.
|
|
1584
|
+
StackVersion last_reduction_version = STACK_VERSION_NONE;
|
|
1585
|
+
for (uint32_t i = 0; i < table_entry.action_count; i++) {
|
|
1586
|
+
TSParseAction action = table_entry.actions[i];
|
|
1587
|
+
|
|
1588
|
+
switch (action.type) {
|
|
1589
|
+
case TSParseActionTypeShift: {
|
|
1590
|
+
if (action.shift.repetition) break;
|
|
1591
|
+
TSStateId next_state;
|
|
1592
|
+
if (action.shift.extra) {
|
|
1593
|
+
next_state = state;
|
|
1594
|
+
LOG("shift_extra");
|
|
1595
|
+
} else {
|
|
1596
|
+
next_state = action.shift.state;
|
|
1597
|
+
LOG("shift state:%u", next_state);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
if (ts_subtree_child_count(lookahead) > 0) {
|
|
1601
|
+
ts_parser__breakdown_lookahead(self, &lookahead, state, &self->reusable_node);
|
|
1602
|
+
next_state = ts_language_next_state(self->language, state, ts_subtree_symbol(lookahead));
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
ts_parser__shift(self, version, next_state, lookahead, action.shift.extra);
|
|
1606
|
+
if (did_reuse) reusable_node_advance(&self->reusable_node);
|
|
1607
|
+
return true;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
case TSParseActionTypeReduce: {
|
|
1611
|
+
bool is_fragile = table_entry.action_count > 1;
|
|
1612
|
+
bool end_of_non_terminal_extra = lookahead.ptr == NULL;
|
|
1613
|
+
LOG("reduce sym:%s, child_count:%u", SYM_NAME(action.reduce.symbol), action.reduce.child_count);
|
|
1614
|
+
StackVersion reduction_version = ts_parser__reduce(
|
|
1615
|
+
self, version, action.reduce.symbol, action.reduce.child_count,
|
|
1616
|
+
action.reduce.dynamic_precedence, action.reduce.production_id,
|
|
1617
|
+
is_fragile, end_of_non_terminal_extra
|
|
1618
|
+
);
|
|
1619
|
+
if (reduction_version != STACK_VERSION_NONE) {
|
|
1620
|
+
last_reduction_version = reduction_version;
|
|
1621
|
+
}
|
|
1622
|
+
break;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
case TSParseActionTypeAccept: {
|
|
1626
|
+
LOG("accept");
|
|
1627
|
+
ts_parser__accept(self, version, lookahead);
|
|
1628
|
+
return true;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
case TSParseActionTypeRecover: {
|
|
1632
|
+
if (ts_subtree_child_count(lookahead) > 0) {
|
|
1633
|
+
ts_parser__breakdown_lookahead(self, &lookahead, ERROR_STATE, &self->reusable_node);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
ts_parser__recover(self, version, lookahead);
|
|
1637
|
+
if (did_reuse) reusable_node_advance(&self->reusable_node);
|
|
1638
|
+
return true;
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
// If a reduction was performed, then replace the current stack version
|
|
1644
|
+
// with one of the stack versions created by a reduction, and continue
|
|
1645
|
+
// processing this version of the stack with the same lookahead symbol.
|
|
1646
|
+
if (last_reduction_version != STACK_VERSION_NONE) {
|
|
1647
|
+
ts_stack_renumber_version(self->stack, last_reduction_version, version);
|
|
1648
|
+
LOG_STACK();
|
|
1649
|
+
state = ts_stack_state(self->stack, version);
|
|
1650
|
+
|
|
1651
|
+
// At the end of a non-terminal extra rule, the lexer will return a
|
|
1652
|
+
// null subtree, because the parser needs to perform a fixed reduction
|
|
1653
|
+
// regardless of the lookahead node. After performing that reduction,
|
|
1654
|
+
// (and completing the non-terminal extra rule) run the lexer again based
|
|
1655
|
+
// on the current parse state.
|
|
1656
|
+
if (!lookahead.ptr) {
|
|
1657
|
+
needs_lex = true;
|
|
1658
|
+
} else {
|
|
1659
|
+
ts_language_table_entry(
|
|
1660
|
+
self->language,
|
|
1661
|
+
state,
|
|
1662
|
+
ts_subtree_leaf_symbol(lookahead),
|
|
1663
|
+
&table_entry
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// A non-terminal extra rule was reduced and merged into an existing
|
|
1671
|
+
// stack version. This version can be discarded.
|
|
1672
|
+
if (!lookahead.ptr) {
|
|
1673
|
+
ts_stack_halt(self->stack, version);
|
|
1674
|
+
return true;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
// If there were no parse actions for the current lookahead token, then
|
|
1678
|
+
// it is not valid in this state. If the current lookahead token is a
|
|
1679
|
+
// keyword, then switch to treating it as the normal word token if that
|
|
1680
|
+
// token is valid in this state.
|
|
1681
|
+
if (
|
|
1682
|
+
ts_subtree_is_keyword(lookahead) &&
|
|
1683
|
+
ts_subtree_symbol(lookahead) != self->language->keyword_capture_token
|
|
1684
|
+
) {
|
|
1685
|
+
ts_language_table_entry(self->language, state, self->language->keyword_capture_token, &table_entry);
|
|
1686
|
+
if (table_entry.action_count > 0) {
|
|
1687
|
+
LOG(
|
|
1688
|
+
"switch from_keyword:%s, to_word_token:%s",
|
|
1689
|
+
TREE_NAME(lookahead),
|
|
1690
|
+
SYM_NAME(self->language->keyword_capture_token)
|
|
1691
|
+
);
|
|
1692
|
+
|
|
1693
|
+
MutableSubtree mutable_lookahead = ts_subtree_make_mut(&self->tree_pool, lookahead);
|
|
1694
|
+
ts_subtree_set_symbol(&mutable_lookahead, self->language->keyword_capture_token, self->language);
|
|
1695
|
+
lookahead = ts_subtree_from_mut(mutable_lookahead);
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
// If the current lookahead token is not valid and the parser is
|
|
1701
|
+
// already in the error state, restart the error recovery process.
|
|
1702
|
+
// TODO - can this be unified with the other `RECOVER` case above?
|
|
1703
|
+
if (state == ERROR_STATE) {
|
|
1704
|
+
ts_parser__recover(self, version, lookahead);
|
|
1705
|
+
return true;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// If the current lookahead token is not valid and the previous
|
|
1709
|
+
// subtree on the stack was reused from an old tree, it isn't actually
|
|
1710
|
+
// valid to reuse it. Remove it from the stack, and in its place,
|
|
1711
|
+
// push each of its children. Then try again to process the current
|
|
1712
|
+
// lookahead.
|
|
1713
|
+
if (ts_parser__breakdown_top_of_stack(self, version)) {
|
|
1714
|
+
state = ts_stack_state(self->stack, version);
|
|
1715
|
+
ts_subtree_release(&self->tree_pool, lookahead);
|
|
1716
|
+
needs_lex = true;
|
|
1717
|
+
continue;
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
// At this point, the current lookahead token is definitely not valid
|
|
1721
|
+
// for this parse stack version. Mark this version as paused and continue
|
|
1722
|
+
// processing any other stack versions that might exist. If some other
|
|
1723
|
+
// version advances successfully, then this version can simply be removed.
|
|
1724
|
+
// But if all versions end up paused, then error recovery is needed.
|
|
1725
|
+
LOG("detect_error");
|
|
1726
|
+
ts_stack_pause(self->stack, version, lookahead);
|
|
1727
|
+
return true;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
static unsigned ts_parser__condense_stack(TSParser *self) {
|
|
1732
|
+
bool made_changes = false;
|
|
1733
|
+
unsigned min_error_cost = UINT_MAX;
|
|
1734
|
+
for (StackVersion i = 0; i < ts_stack_version_count(self->stack); i++) {
|
|
1735
|
+
// Prune any versions that have been marked for removal.
|
|
1736
|
+
if (ts_stack_is_halted(self->stack, i)) {
|
|
1737
|
+
ts_stack_remove_version(self->stack, i);
|
|
1738
|
+
i--;
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// Keep track of the minimum error cost of any stack version so
|
|
1743
|
+
// that it can be returned.
|
|
1744
|
+
ErrorStatus status_i = ts_parser__version_status(self, i);
|
|
1745
|
+
if (!status_i.is_in_error && status_i.cost < min_error_cost) {
|
|
1746
|
+
min_error_cost = status_i.cost;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// Examine each pair of stack versions, removing any versions that
|
|
1750
|
+
// are clearly worse than another version. Ensure that the versions
|
|
1751
|
+
// are ordered from most promising to least promising.
|
|
1752
|
+
for (StackVersion j = 0; j < i; j++) {
|
|
1753
|
+
ErrorStatus status_j = ts_parser__version_status(self, j);
|
|
1754
|
+
|
|
1755
|
+
switch (ts_parser__compare_versions(self, status_j, status_i)) {
|
|
1756
|
+
case ErrorComparisonTakeLeft:
|
|
1757
|
+
made_changes = true;
|
|
1758
|
+
ts_stack_remove_version(self->stack, i);
|
|
1759
|
+
i--;
|
|
1760
|
+
j = i;
|
|
1761
|
+
break;
|
|
1762
|
+
|
|
1763
|
+
case ErrorComparisonPreferLeft:
|
|
1764
|
+
case ErrorComparisonNone:
|
|
1765
|
+
if (ts_stack_merge(self->stack, j, i)) {
|
|
1766
|
+
made_changes = true;
|
|
1767
|
+
i--;
|
|
1768
|
+
j = i;
|
|
1769
|
+
}
|
|
1770
|
+
break;
|
|
1771
|
+
|
|
1772
|
+
case ErrorComparisonPreferRight:
|
|
1773
|
+
made_changes = true;
|
|
1774
|
+
if (ts_stack_merge(self->stack, j, i)) {
|
|
1775
|
+
i--;
|
|
1776
|
+
j = i;
|
|
1777
|
+
} else {
|
|
1778
|
+
ts_stack_swap_versions(self->stack, i, j);
|
|
1779
|
+
}
|
|
1780
|
+
break;
|
|
1781
|
+
|
|
1782
|
+
case ErrorComparisonTakeRight:
|
|
1783
|
+
made_changes = true;
|
|
1784
|
+
ts_stack_remove_version(self->stack, j);
|
|
1785
|
+
i--;
|
|
1786
|
+
j--;
|
|
1787
|
+
break;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
// Enforce a hard upper bound on the number of stack versions by
|
|
1793
|
+
// discarding the least promising versions.
|
|
1794
|
+
while (ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) {
|
|
1795
|
+
ts_stack_remove_version(self->stack, MAX_VERSION_COUNT);
|
|
1796
|
+
made_changes = true;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
// If the best-performing stack version is currently paused, or all
|
|
1800
|
+
// versions are paused, then resume the best paused version and begin
|
|
1801
|
+
// the error recovery process. Otherwise, remove the paused versions.
|
|
1802
|
+
if (ts_stack_version_count(self->stack) > 0) {
|
|
1803
|
+
bool has_unpaused_version = false;
|
|
1804
|
+
for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) {
|
|
1805
|
+
if (ts_stack_is_paused(self->stack, i)) {
|
|
1806
|
+
if (!has_unpaused_version && self->accept_count < MAX_VERSION_COUNT) {
|
|
1807
|
+
LOG("resume version:%u", i);
|
|
1808
|
+
min_error_cost = ts_stack_error_cost(self->stack, i);
|
|
1809
|
+
Subtree lookahead = ts_stack_resume(self->stack, i);
|
|
1810
|
+
ts_parser__handle_error(self, i, lookahead);
|
|
1811
|
+
has_unpaused_version = true;
|
|
1812
|
+
} else {
|
|
1813
|
+
ts_stack_remove_version(self->stack, i);
|
|
1814
|
+
i--;
|
|
1815
|
+
n--;
|
|
1816
|
+
}
|
|
1817
|
+
} else {
|
|
1818
|
+
has_unpaused_version = true;
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
if (made_changes) {
|
|
1824
|
+
LOG("condense");
|
|
1825
|
+
LOG_STACK();
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
return min_error_cost;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
static bool ts_parser_has_outstanding_parse(TSParser *self) {
|
|
1832
|
+
return (
|
|
1833
|
+
self->external_scanner_payload ||
|
|
1834
|
+
ts_stack_state(self->stack, 0) != 1 ||
|
|
1835
|
+
ts_stack_node_count_since_error(self->stack, 0) != 0
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
// Parser - Public
|
|
1840
|
+
|
|
1841
|
+
TSParser *ts_parser_new(void) {
|
|
1842
|
+
TSParser *self = ts_calloc(1, sizeof(TSParser));
|
|
1843
|
+
ts_lexer_init(&self->lexer);
|
|
1844
|
+
array_init(&self->reduce_actions);
|
|
1845
|
+
array_reserve(&self->reduce_actions, 4);
|
|
1846
|
+
self->tree_pool = ts_subtree_pool_new(32);
|
|
1847
|
+
self->stack = ts_stack_new(&self->tree_pool);
|
|
1848
|
+
self->finished_tree = NULL_SUBTREE;
|
|
1849
|
+
self->reusable_node = reusable_node_new();
|
|
1850
|
+
self->dot_graph_file = NULL;
|
|
1851
|
+
self->cancellation_flag = NULL;
|
|
1852
|
+
self->timeout_duration = 0;
|
|
1853
|
+
self->language = NULL;
|
|
1854
|
+
self->has_scanner_error = false;
|
|
1855
|
+
self->external_scanner_payload = NULL;
|
|
1856
|
+
self->end_clock = clock_null();
|
|
1857
|
+
self->operation_count = 0;
|
|
1858
|
+
self->old_tree = NULL_SUBTREE;
|
|
1859
|
+
self->included_range_differences = (TSRangeArray) array_new();
|
|
1860
|
+
self->included_range_difference_index = 0;
|
|
1861
|
+
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
|
1862
|
+
return self;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
void ts_parser_delete(TSParser *self) {
|
|
1866
|
+
if (!self) return;
|
|
1867
|
+
|
|
1868
|
+
ts_parser_set_language(self, NULL);
|
|
1869
|
+
ts_stack_delete(self->stack);
|
|
1870
|
+
if (self->reduce_actions.contents) {
|
|
1871
|
+
array_delete(&self->reduce_actions);
|
|
1872
|
+
}
|
|
1873
|
+
if (self->included_range_differences.contents) {
|
|
1874
|
+
array_delete(&self->included_range_differences);
|
|
1875
|
+
}
|
|
1876
|
+
if (self->old_tree.ptr) {
|
|
1877
|
+
ts_subtree_release(&self->tree_pool, self->old_tree);
|
|
1878
|
+
self->old_tree = NULL_SUBTREE;
|
|
1879
|
+
}
|
|
1880
|
+
ts_wasm_store_delete(self->wasm_store);
|
|
1881
|
+
ts_lexer_delete(&self->lexer);
|
|
1882
|
+
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
|
1883
|
+
ts_subtree_pool_delete(&self->tree_pool);
|
|
1884
|
+
reusable_node_delete(&self->reusable_node);
|
|
1885
|
+
array_delete(&self->trailing_extras);
|
|
1886
|
+
array_delete(&self->trailing_extras2);
|
|
1887
|
+
array_delete(&self->scratch_trees);
|
|
1888
|
+
ts_free(self);
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
const TSLanguage *ts_parser_language(const TSParser *self) {
|
|
1892
|
+
return self->language;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
bool ts_parser_set_language(TSParser *self, const TSLanguage *language) {
|
|
1896
|
+
ts_parser_reset(self);
|
|
1897
|
+
ts_language_delete(self->language);
|
|
1898
|
+
self->language = NULL;
|
|
1899
|
+
|
|
1900
|
+
if (language) {
|
|
1901
|
+
if (
|
|
1902
|
+
language->version > TREE_SITTER_LANGUAGE_VERSION ||
|
|
1903
|
+
language->version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION
|
|
1904
|
+
) return false;
|
|
1905
|
+
|
|
1906
|
+
if (ts_language_is_wasm(language)) {
|
|
1907
|
+
if (
|
|
1908
|
+
!self->wasm_store ||
|
|
1909
|
+
!ts_wasm_store_start(self->wasm_store, &self->lexer.data, language)
|
|
1910
|
+
) return false;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
self->language = ts_language_copy(language);
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
TSLogger ts_parser_logger(const TSParser *self) {
|
|
1919
|
+
return self->lexer.logger;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
void ts_parser_set_logger(TSParser *self, TSLogger logger) {
|
|
1923
|
+
self->lexer.logger = logger;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
void ts_parser_print_dot_graphs(TSParser *self, int fd) {
|
|
1927
|
+
if (self->dot_graph_file) {
|
|
1928
|
+
fclose(self->dot_graph_file);
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
if (fd >= 0) {
|
|
1932
|
+
#ifdef _WIN32
|
|
1933
|
+
self->dot_graph_file = _fdopen(fd, "a");
|
|
1934
|
+
#else
|
|
1935
|
+
self->dot_graph_file = fdopen(fd, "a");
|
|
1936
|
+
#endif
|
|
1937
|
+
} else {
|
|
1938
|
+
self->dot_graph_file = NULL;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
const size_t *ts_parser_cancellation_flag(const TSParser *self) {
|
|
1943
|
+
return (const size_t *)self->cancellation_flag;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag) {
|
|
1947
|
+
self->cancellation_flag = (const volatile size_t *)flag;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
uint64_t ts_parser_timeout_micros(const TSParser *self) {
|
|
1951
|
+
return duration_to_micros(self->timeout_duration);
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros) {
|
|
1955
|
+
self->timeout_duration = duration_from_micros(timeout_micros);
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
bool ts_parser_set_included_ranges(
|
|
1959
|
+
TSParser *self,
|
|
1960
|
+
const TSRange *ranges,
|
|
1961
|
+
uint32_t count
|
|
1962
|
+
) {
|
|
1963
|
+
return ts_lexer_set_included_ranges(&self->lexer, ranges, count);
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
const TSRange *ts_parser_included_ranges(const TSParser *self, uint32_t *count) {
|
|
1967
|
+
return ts_lexer_included_ranges(&self->lexer, count);
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
void ts_parser_reset(TSParser *self) {
|
|
1971
|
+
ts_parser__external_scanner_destroy(self);
|
|
1972
|
+
if (self->wasm_store) {
|
|
1973
|
+
ts_wasm_store_reset(self->wasm_store);
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
if (self->old_tree.ptr) {
|
|
1977
|
+
ts_subtree_release(&self->tree_pool, self->old_tree);
|
|
1978
|
+
self->old_tree = NULL_SUBTREE;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
reusable_node_clear(&self->reusable_node);
|
|
1982
|
+
ts_lexer_reset(&self->lexer, length_zero());
|
|
1983
|
+
ts_stack_clear(self->stack);
|
|
1984
|
+
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
|
1985
|
+
if (self->finished_tree.ptr) {
|
|
1986
|
+
ts_subtree_release(&self->tree_pool, self->finished_tree);
|
|
1987
|
+
self->finished_tree = NULL_SUBTREE;
|
|
1988
|
+
}
|
|
1989
|
+
self->accept_count = 0;
|
|
1990
|
+
self->has_scanner_error = false;
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
TSTree *ts_parser_parse(
|
|
1994
|
+
TSParser *self,
|
|
1995
|
+
const TSTree *old_tree,
|
|
1996
|
+
TSInput input
|
|
1997
|
+
) {
|
|
1998
|
+
TSTree *result = NULL;
|
|
1999
|
+
if (!self->language || !input.read) return NULL;
|
|
2000
|
+
|
|
2001
|
+
if (ts_language_is_wasm(self->language)) {
|
|
2002
|
+
if (!self->wasm_store) return NULL;
|
|
2003
|
+
ts_wasm_store_start(self->wasm_store, &self->lexer.data, self->language);
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
ts_lexer_set_input(&self->lexer, input);
|
|
2007
|
+
array_clear(&self->included_range_differences);
|
|
2008
|
+
self->included_range_difference_index = 0;
|
|
2009
|
+
|
|
2010
|
+
if (ts_parser_has_outstanding_parse(self)) {
|
|
2011
|
+
LOG("resume_parsing");
|
|
2012
|
+
} else {
|
|
2013
|
+
ts_parser__external_scanner_create(self);
|
|
2014
|
+
if (self->has_scanner_error) goto exit;
|
|
2015
|
+
|
|
2016
|
+
if (old_tree) {
|
|
2017
|
+
ts_subtree_retain(old_tree->root);
|
|
2018
|
+
self->old_tree = old_tree->root;
|
|
2019
|
+
ts_range_array_get_changed_ranges(
|
|
2020
|
+
old_tree->included_ranges, old_tree->included_range_count,
|
|
2021
|
+
self->lexer.included_ranges, self->lexer.included_range_count,
|
|
2022
|
+
&self->included_range_differences
|
|
2023
|
+
);
|
|
2024
|
+
reusable_node_reset(&self->reusable_node, old_tree->root);
|
|
2025
|
+
LOG("parse_after_edit");
|
|
2026
|
+
LOG_TREE(self->old_tree);
|
|
2027
|
+
for (unsigned i = 0; i < self->included_range_differences.size; i++) {
|
|
2028
|
+
TSRange *range = &self->included_range_differences.contents[i];
|
|
2029
|
+
LOG("different_included_range %u - %u", range->start_byte, range->end_byte);
|
|
2030
|
+
}
|
|
2031
|
+
} else {
|
|
2032
|
+
reusable_node_clear(&self->reusable_node);
|
|
2033
|
+
LOG("new_parse");
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
self->operation_count = 0;
|
|
2038
|
+
if (self->timeout_duration) {
|
|
2039
|
+
self->end_clock = clock_after(clock_now(), self->timeout_duration);
|
|
2040
|
+
} else {
|
|
2041
|
+
self->end_clock = clock_null();
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
uint32_t position = 0, last_position = 0, version_count = 0;
|
|
2045
|
+
do {
|
|
2046
|
+
for (
|
|
2047
|
+
StackVersion version = 0;
|
|
2048
|
+
version_count = ts_stack_version_count(self->stack),
|
|
2049
|
+
version < version_count;
|
|
2050
|
+
version++
|
|
2051
|
+
) {
|
|
2052
|
+
bool allow_node_reuse = version_count == 1;
|
|
2053
|
+
while (ts_stack_is_active(self->stack, version)) {
|
|
2054
|
+
LOG(
|
|
2055
|
+
"process version:%u, version_count:%u, state:%d, row:%u, col:%u",
|
|
2056
|
+
version,
|
|
2057
|
+
ts_stack_version_count(self->stack),
|
|
2058
|
+
ts_stack_state(self->stack, version),
|
|
2059
|
+
ts_stack_position(self->stack, version).extent.row,
|
|
2060
|
+
ts_stack_position(self->stack, version).extent.column
|
|
2061
|
+
);
|
|
2062
|
+
|
|
2063
|
+
if (!ts_parser__advance(self, version, allow_node_reuse)) {
|
|
2064
|
+
if (self->has_scanner_error) goto exit;
|
|
2065
|
+
return NULL;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
LOG_STACK();
|
|
2069
|
+
|
|
2070
|
+
position = ts_stack_position(self->stack, version).bytes;
|
|
2071
|
+
if (position > last_position || (version > 0 && position == last_position)) {
|
|
2072
|
+
last_position = position;
|
|
2073
|
+
break;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
// After advancing each version of the stack, re-sort the versions by their cost,
|
|
2079
|
+
// removing any versions that are no longer worth pursuing.
|
|
2080
|
+
unsigned min_error_cost = ts_parser__condense_stack(self);
|
|
2081
|
+
|
|
2082
|
+
// If there's already a finished parse tree that's better than any in-progress version,
|
|
2083
|
+
// then terminate parsing. Clear the parse stack to remove any extra references to subtrees
|
|
2084
|
+
// within the finished tree, ensuring that these subtrees can be safely mutated in-place
|
|
2085
|
+
// for rebalancing.
|
|
2086
|
+
if (self->finished_tree.ptr && ts_subtree_error_cost(self->finished_tree) < min_error_cost) {
|
|
2087
|
+
ts_stack_clear(self->stack);
|
|
2088
|
+
break;
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
while (self->included_range_difference_index < self->included_range_differences.size) {
|
|
2092
|
+
TSRange *range = &self->included_range_differences.contents[self->included_range_difference_index];
|
|
2093
|
+
if (range->end_byte <= position) {
|
|
2094
|
+
self->included_range_difference_index++;
|
|
2095
|
+
} else {
|
|
2096
|
+
break;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
} while (version_count != 0);
|
|
2100
|
+
|
|
2101
|
+
ts_assert(self->finished_tree.ptr);
|
|
2102
|
+
ts_subtree_balance(self->finished_tree, &self->tree_pool, self->language);
|
|
2103
|
+
LOG("done");
|
|
2104
|
+
LOG_TREE(self->finished_tree);
|
|
2105
|
+
|
|
2106
|
+
result = ts_tree_new(
|
|
2107
|
+
self->finished_tree,
|
|
2108
|
+
self->language,
|
|
2109
|
+
self->lexer.included_ranges,
|
|
2110
|
+
self->lexer.included_range_count
|
|
2111
|
+
);
|
|
2112
|
+
self->finished_tree = NULL_SUBTREE;
|
|
2113
|
+
|
|
2114
|
+
exit:
|
|
2115
|
+
ts_parser_reset(self);
|
|
2116
|
+
return result;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
TSTree *ts_parser_parse_string(
|
|
2120
|
+
TSParser *self,
|
|
2121
|
+
const TSTree *old_tree,
|
|
2122
|
+
const char *string,
|
|
2123
|
+
uint32_t length
|
|
2124
|
+
) {
|
|
2125
|
+
return ts_parser_parse_string_encoding(self, old_tree, string, length, TSInputEncodingUTF8);
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
TSTree *ts_parser_parse_string_encoding(
|
|
2129
|
+
TSParser *self,
|
|
2130
|
+
const TSTree *old_tree,
|
|
2131
|
+
const char *string,
|
|
2132
|
+
uint32_t length,
|
|
2133
|
+
TSInputEncoding encoding
|
|
2134
|
+
) {
|
|
2135
|
+
TSStringInput input = {string, length};
|
|
2136
|
+
return ts_parser_parse(self, old_tree, (TSInput) {
|
|
2137
|
+
&input,
|
|
2138
|
+
ts_string_input_read,
|
|
2139
|
+
encoding,
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
void ts_parser_set_wasm_store(TSParser *self, TSWasmStore *store) {
|
|
2144
|
+
if (self->language && ts_language_is_wasm(self->language)) {
|
|
2145
|
+
// Copy the assigned language into the new store.
|
|
2146
|
+
const TSLanguage *copy = ts_language_copy(self->language);
|
|
2147
|
+
ts_parser_set_language(self, copy);
|
|
2148
|
+
ts_language_delete(copy);
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
ts_wasm_store_delete(self->wasm_store);
|
|
2152
|
+
self->wasm_store = store;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
TSWasmStore *ts_parser_take_wasm_store(TSParser *self) {
|
|
2156
|
+
if (self->language && ts_language_is_wasm(self->language)) {
|
|
2157
|
+
ts_parser_set_language(self, NULL);
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
TSWasmStore *result = self->wasm_store;
|
|
2161
|
+
self->wasm_store = NULL;
|
|
2162
|
+
return result;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
#undef LOG
|