diff options
author | Nick Coutsos <[email protected]> | 2021-12-22 14:09:26 -0500 |
---|---|---|
committer | Nick Coutsos <[email protected]> | 2021-12-22 14:09:26 -0500 |
commit | 52f9f165b9678b2c8c06e0f467581b69a5002273 (patch) | |
tree | 0fee309a9ebd79031c242cb906cc53d81103a536 /test-tree-sitter.js | |
parent | 8c88c54221f6e34ac94800dab20776319e604381 (diff) | |
download | keymap-editor-devicetree-parser.tar.gz keymap-editor-devicetree-parser.zip |
wip devicetree parsing experimentdevicetree-parser
Diffstat (limited to 'test-tree-sitter.js')
-rw-r--r-- | test-tree-sitter.js | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/test-tree-sitter.js b/test-tree-sitter.js new file mode 100644 index 0000000..ad2055e --- /dev/null +++ b/test-tree-sitter.js @@ -0,0 +1,154 @@ +const { filter } = require('lodash') +const TreeSitter = require('web-tree-sitter') + +const keymapText = ` +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include <behaviors.dtsi> +#include <dt-bindings/zmk/keys.h> +#include <dt-bindings/zmk/outputs.h> +#include <dt-bindings/zmk/bt.h> + +#define DEF 0 +#define LWR 1 +#define RSE 2 +#define ADJ 3 + +< { quick_tap_ms = <200>; }; +&mt { quick_tap_ms = <200>; }; + +/ { + combos { + compatible = "zmk,combos"; + combo_btclr { + timeout-ms = <TIMEOUT>; + key-positions = <1 6>; + bindings = <&bt BT_CLR>; + }; + combo_reset { + timeout-ms = <TIMEOUT>; + key-positions = <1 3>; + bindings = <&reset>; + }; + }; + + sensors { + compatible = "zmk,keymap-sensors"; + sensors = <&encoder_1 &encoder_2>; + }; + + keymap { + compatible = "zmk,keymap"; + + default_layer { + label = "foo"; + bindings = <&kp TAB &kp Q &kp W &kp E &kp R &kp T>; + }; + + layer_fps { + bindings = <&trans &trans &kp Q &kp W &kp E &kp R>; + sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>; + }; + + layer_numpad { + bindings = <&trans &trans &kp GRAVE &kp MINUS &kp EQUAL &trans>; + }; + }; +}; +` + +function findNodeProperty(node, property) { + return node.children.find(node => ( + node.type === 'property' && + node.children[0].text === property + )) +} + +function findChildrenByIdentifier(node, nameOrMatch) { + const match = typeof nameOrMatch === 'string' + ? text => text === nameOrMatch + : nameOrMatch + + return node.namedChildren.filter(node => ( + node.type === 'node' && + node.children.find(sub => ( + sub.type === 'identifier' && + match(sub.text) + )) + )) +} + +function findChildByIdentifier(node, nameOrMatch) { + return findChildrenByIdentifier(node, nameOrMatch)[0] +} + +function parseLayer(node) { + const identifier = node.children[0].text + const labelNode = node.children.find(node => node.type === 'property' && node.children[0].text === 'label') + const bindingsNode = findNodeProperty(node, 'bindings') + const sensorBindingsNode = findNodeProperty(node, 'sensor-bindings') + + function parseBindings(node) { + return node.children[2].children.slice(1, -1) + .map(node => node.text) + .reduce((bindings, node) => { + if (node.startsWith('&')) { + bindings.push([node]) + } else { + const last = bindings[bindings.length - 1] + last.push(node) + } + + return bindings + }, []) + .map(binding => binding.join(' ')) + } + + return Object.assign( + { identifier }, + labelNode && { label: labelNode.children[2].text.slice(1, -1) }, + bindingsNode && { + bindings: parseBindings(bindingsNode) + }, + sensorBindingsNode && { + sensorBindings: parseBindings(sensorBindingsNode) + } + ) +} + +function listNodes(nodes, opts = {}) { + const { stripNewlines = true, limit = 50 } = opts + for (let node of nodes) { + value = node.text + if (stripNewlines) value = value.replace(/\n/g, '') + if (limit) value = value.slice(0, limit) + + console.log(node.id, `[${node.type}]`, '->', value) + } +} + +async function main() { + await TreeSitter.init() + const parser = new TreeSitter() + const deviceTree = await TreeSitter.Language.load('./tree-sitter-devicetree.wasm') + parser.setLanguage(deviceTree) + + const tree = parser.parse(keymapText) + const root = findChildByIdentifier(tree.rootNode, '/') + const keymap = findChildByIdentifier(root, 'keymap') + const layers = keymap.namedChildren + .filter(node => node.type === 'node') + .map(layer => parseLayer(layer)) + + const includes = filter(tree.rootNode.children, { type: 'preproc_include' }) + const behaviourIncludes = includes.filter(node => node.children[1].text.startsWith('<dt-bindings')) + + listNodes(behaviourIncludes) + console.log(layers) +} + +main() |