UNPKG

gfd3

Version:

API for d3 trees with gf

215 lines (214 loc) 8.57 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GFD3 = void 0; const d3 = __importStar(require("d3")); // class GFD3 { constructor() { this.grammar = null; this.abstractAST = null; this.grammarMode = 'abstract'; this.selectedConcrete = null; } loadGrammarFromFile(file) { return __awaiter(this, void 0, void 0, function* () { const text = yield file.text(); this.setGrammar(JSON.parse(text)); }); } loadGrammarFromURL(url) { return __awaiter(this, void 0, void 0, function* () { const response = yield fetch(url); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = yield response.json(); this.setGrammar(json); }); } setGrammar(grammar) { this.grammar = grammar; this.abstractAST = this.transformAbstractToTree(grammar); this.grammarMode = 'abstract'; const concreteLanguages = this.getConcreteLanguages(); if (concreteLanguages.length > 0) { this.selectedConcrete = concreteLanguages[0]; } } transformAbstractToTree(grammar) { const startCat = grammar.abstract.startcat; const buildTree = (cat, visited) => { if (visited.has(cat)) { return { name: cat, type: 'cat' }; } visited.add(cat); const node = { name: cat, children: [], type: 'cat' }; const funs = Object.entries(grammar.abstract.funs) .filter(([, funDetails]) => funDetails.cat === cat) .map(([funName]) => funName); node.funs = funs; if (grammar.concretes) { node.concreteFunctions = {}; Object.entries(grammar.concretes).forEach(([lang, concrete]) => { if (concrete.productions[cat]) { node.concreteFunctions[lang] = concrete.productions[cat] .map(prod => concrete.functions[prod.fid].name); } }); } Object.values(grammar.abstract.funs) .filter(fun => fun.cat === cat) .forEach(fun => { fun.args.forEach(arg => { var _a, _b; if (!((_a = node.children) === null || _a === void 0 ? void 0 : _a.some(child => child.name === arg))) { (_b = node.children) === null || _b === void 0 ? void 0 : _b.push(buildTree(arg, new Set(visited))); } }); }); visited.delete(cat); return node; }; return buildTree(startCat, new Set()); } getGrammar() { return this.grammar; } getAbstractAST() { return this.abstractAST; } getConcreteLanguages() { if (!this.grammar || !this.grammar.concretes) return []; return Object.values(this.grammar.concretes).map(concrete => concrete.flags.language); } setGrammarMode(mode) { this.grammarMode = mode; } getGrammarMode() { return this.grammarMode; } setSelectedConcrete(language) { this.selectedConcrete = language; } getSelectedConcrete() { return this.selectedConcrete; } getOptionsForNode(node) { if (!this.grammar) return []; const category = node.name; if (this.grammarMode === 'abstract') { return Object.entries(this.grammar.abstract.funs) .filter(([, funDetails]) => funDetails.cat === category) .map(([funName]) => funName); } else if (this.selectedConcrete) { const concreteLang = Object.keys(this.grammar.concretes).find(key => this.grammar.concretes[key].flags.language === this.selectedConcrete); if (concreteLang) { const concrete = this.grammar.concretes[concreteLang]; if (concrete.productions[category]) { return concrete.productions[category] .map(prod => concrete.functions[prod.fid].name); } } } return []; } updateNodeName(node, newName) { node.originalName = node.originalName || node.name; node.name = newName; } resetNodeName(node) { if (node.originalName) { node.name = node.originalName; } } parseLins(lins, sequences) { return lins.map(linIndex => { const sequence = sequences[linIndex]; return sequence.map(seq => { if (seq.type === 'SymKS') { return seq.args[0]; } if (seq.type === 'SymCat') { return `{${seq.args[1]}}`; } if (seq.type === 'SymLit') { return seq.args.join(''); } return ''; }).join(' '); }).join(' '); } resolveSequence(sequence, cats) { return sequence.map(seq => { if (seq.type === 'SymKS') { return seq.args[0]; } if (seq.type === 'SymCat') { const catIndex = seq.args[0]; return cats[catIndex] || `{${catIndex}}`; } if (seq.type === 'SymLit') { return `<${seq.args.join(',')}>`; } return ''; }).join(' '); } replaceLins() { if (!this.grammar) throw new Error("Grammar not loaded"); const resolvedGrammar = Object.assign(Object.assign({}, this.grammar), { concretes: {} }); const cats = new Set(); Object.values(this.grammar.abstract.funs).forEach(fun => { cats.add(fun.cat); fun.args.forEach(arg => cats.add(arg)); }); const catsArray = Array.from(cats); for (const [concreteName, concreteGrammar] of Object.entries(this.grammar.concretes)) { const resolvedFunctions = concreteGrammar.functions.map(func => (Object.assign(Object.assign({}, func), { resolvedLins: func.lins.map(linIndex => this.resolveSequence(concreteGrammar.sequences[linIndex], catsArray)) }))); resolvedGrammar.concretes[concreteName] = Object.assign(Object.assign({}, concreteGrammar), { functions: resolvedFunctions, resolvedSequences: concreteGrammar.sequences.map(seq => this.resolveSequence(seq, catsArray)) }); } return resolvedGrammar; } // return data getTreeData() { if (!this.abstractAST) return null; return d3.hierarchy(this.abstractAST); } } exports.GFD3 = GFD3;