diff --git a/src/compile-testcases.ts b/src/compile-testcases.ts index f8e10de..26b3e27 100644 --- a/src/compile-testcases.ts +++ b/src/compile-testcases.ts @@ -18,11 +18,99 @@ compile(['Main.elm'], { const elmParser = new Parser(); elmParser.setLanguage(Elm); -const parseElm = (filename: string) => { +interface ElmVariant { + typeName: string; + name: string; + index: number; + slots: [string]; +} + +const parseElm = (filename: string): { [id: string]: [ElmVariant] } => { const source = fs.readFileSync(filename, 'utf8'); - console.log(source); const tree = elmParser.parse(source); - console.log(tree); + const found: { [id: string]: [ElmVariant] } = {}; + + /* + A quick reference for using treesitter. + Generally it's pretty easy to see what methods are available here: + https://github.com/tree-sitter/node-tree-sitter/blob/master/index.js + + We usually want these things + + - node.namedChildren + Gives a list of named children for a node. Unnamed children are things like intermediate characters in the AST. + http://tree-sitter.github.io/tree-sitter/using-parsers#named-vs-anonymous-nodes + + - node.type + The name of the AST node that was parsed. e.g. upper_case_identifier, or union_variant + + - node.toString() + See the s-expression version of the node. e.g. (union_variant (upper_case_identifier) (type_ref (upper_case_qid (upper_case_identifier)))) + May look kinda weird, but it's basically describing the AST for that node. + http://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax + + - node.text + Render the literal text for that node. + + */ + + for (let child of tree.rootNode.namedChildren) { + if (child.type == 'type_declaration') { + let name = ''; + let index = 0; + + for (let variant of child.namedChildren) { + switch (variant.type) { + case 'upper_case_identifier': { + name = variant.text; + break; + } + case 'union_variant': { + let foundVariantName = ''; + let slots: string[] = []; + for (let detail of variant.namedChildren) { + switch (detail.type) { + case 'upper_case_identifier': { + foundVariantName = detail.text; + break; + } + + default: { + slots.push(detail.text); + break; + } + } + } + + if (name in found) { + found[name].push({ + typeName: name, + name: foundVariantName, + index: index, + slots: slots, + }); + } else { + found[name] = [ + { + typeName: name, + name: foundVariantName, + index: index, + slots: slots, + }, + ]; + } + + index = index + 1; + break; + } + default: { + break; + } + } + } + } + } + return found; }; const result = parseElm('./testcases/simple/Main.elm');