what have i done
This commit is contained in:
207
scripts/csound-parser/generator.ts
Normal file
207
scripts/csound-parser/generator.ts
Normal file
@ -0,0 +1,207 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import type { CsoundReference } from './types';
|
||||
|
||||
export class TypeScriptGenerator {
|
||||
private outputDir: string;
|
||||
|
||||
constructor(outputDir: string) {
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
sanitizeCategoryName(category: string): string {
|
||||
return category
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '');
|
||||
}
|
||||
|
||||
sanitizeVariableName(category: string): string {
|
||||
return category
|
||||
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
||||
.split(' ')
|
||||
.map((word, index) =>
|
||||
index === 0
|
||||
? word.toLowerCase()
|
||||
: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
||||
)
|
||||
.join('')
|
||||
.replace(/^[0-9]/, '_$&');
|
||||
}
|
||||
|
||||
escapeString(str: string): string {
|
||||
return str
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\t/g, '\\t');
|
||||
}
|
||||
|
||||
generateReferenceObject(ref: CsoundReference, indent: string = ' '): string {
|
||||
const lines: string[] = [];
|
||||
lines.push(`{`);
|
||||
lines.push(`${indent}name: '${this.escapeString(ref.name)}',`);
|
||||
lines.push(`${indent}type: '${ref.type}',`);
|
||||
lines.push(`${indent}category: '${this.escapeString(ref.category)}',`);
|
||||
lines.push(`${indent}description: '${this.escapeString(ref.description)}',`);
|
||||
|
||||
if (ref.syntax) {
|
||||
lines.push(`${indent}syntax: '${this.escapeString(ref.syntax)}',`);
|
||||
}
|
||||
|
||||
if (ref.example) {
|
||||
const escapedExample = this.escapeString(ref.example);
|
||||
lines.push(`${indent}example: '${escapedExample}',`);
|
||||
}
|
||||
|
||||
if (ref.rates && ref.rates.length > 0) {
|
||||
lines.push(`${indent}rates: [${ref.rates.map(r => `'${r}'`).join(', ')}],`);
|
||||
}
|
||||
|
||||
if (ref.parameters && ref.parameters.length > 0) {
|
||||
lines.push(`${indent}parameters: [`);
|
||||
for (const param of ref.parameters) {
|
||||
lines.push(`${indent} {`);
|
||||
lines.push(`${indent} name: '${this.escapeString(param.name)}',`);
|
||||
lines.push(`${indent} description: '${this.escapeString(param.description)}',`);
|
||||
lines.push(`${indent} type: '${param.type}'`);
|
||||
lines.push(`${indent} },`);
|
||||
}
|
||||
lines.push(`${indent}],`);
|
||||
}
|
||||
|
||||
if (ref.seeAlso && ref.seeAlso.length > 0) {
|
||||
lines.push(`${indent}seeAlso: [${ref.seeAlso.map(s => `'${this.escapeString(s)}'`).join(', ')}]`);
|
||||
}
|
||||
|
||||
lines.push(`}`);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
generateCategoryFile(
|
||||
category: string,
|
||||
references: CsoundReference[],
|
||||
fileName: string
|
||||
): string {
|
||||
const varName = this.sanitizeVariableName(category);
|
||||
|
||||
const lines: string[] = [];
|
||||
lines.push(`import type { CsoundReference } from './types'`);
|
||||
lines.push(``);
|
||||
lines.push(`// ${category}`);
|
||||
lines.push(`export const ${varName}: CsoundReference[] = [`);
|
||||
|
||||
for (const ref of references) {
|
||||
const refLines = this.generateReferenceObject(ref, ' ');
|
||||
lines.push(refLines + ',');
|
||||
}
|
||||
|
||||
lines.push(`]`);
|
||||
lines.push(``);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
generateMainFile(categories: Map<string, CsoundReference[]>): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push(`import type { CsoundReference } from './types'`);
|
||||
|
||||
const imports: string[] = [];
|
||||
const varNames: string[] = [];
|
||||
|
||||
for (const [category] of categories) {
|
||||
const fileName = this.sanitizeCategoryName(category);
|
||||
const varName = this.sanitizeVariableName(category);
|
||||
imports.push(`import { ${varName} } from './${fileName}'`);
|
||||
varNames.push(varName);
|
||||
}
|
||||
|
||||
lines.push(...imports);
|
||||
lines.push(``);
|
||||
lines.push(`export type { CsoundReference }`);
|
||||
lines.push(``);
|
||||
lines.push(`export const allCsoundReferences: CsoundReference[] = [`);
|
||||
for (const varName of varNames) {
|
||||
lines.push(` ...${varName},`);
|
||||
}
|
||||
lines.push(`]`);
|
||||
lines.push(``);
|
||||
|
||||
lines.push(`export const csoundReferenceMap = new Map<string, CsoundReference>()`);
|
||||
lines.push(`allCsoundReferences.forEach(ref => {`);
|
||||
lines.push(` csoundReferenceMap.set(ref.name, ref)`);
|
||||
lines.push(`})`);
|
||||
lines.push(``);
|
||||
|
||||
lines.push(`export function getCsoundReference(name: string): CsoundReference | undefined {`);
|
||||
lines.push(` return csoundReferenceMap.get(name)`);
|
||||
lines.push(`}`);
|
||||
lines.push(``);
|
||||
|
||||
lines.push(`export function getCsoundReferencesByCategory(category: string): CsoundReference[] {`);
|
||||
lines.push(` return allCsoundReferences.filter(ref => ref.category === category)`);
|
||||
lines.push(`}`);
|
||||
lines.push(``);
|
||||
|
||||
lines.push(`export {`);
|
||||
for (const varName of varNames) {
|
||||
lines.push(` ${varName},`);
|
||||
}
|
||||
lines.push(`}`);
|
||||
lines.push(``);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
writeCategoryFiles(categories: Map<string, CsoundReference[]>): void {
|
||||
if (!fs.existsSync(this.outputDir)) {
|
||||
fs.mkdirSync(this.outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
let fileCount = 0;
|
||||
|
||||
for (const [category, references] of categories) {
|
||||
const fileName = this.sanitizeCategoryName(category);
|
||||
const filePath = path.join(this.outputDir, `${fileName}.ts`);
|
||||
const content = this.generateCategoryFile(category, references, fileName);
|
||||
|
||||
fs.writeFileSync(filePath, content, 'utf-8');
|
||||
fileCount++;
|
||||
console.log(`Generated: ${fileName}.ts (${references.length} opcodes)`);
|
||||
}
|
||||
|
||||
console.log(`\nGenerated ${fileCount} category files`);
|
||||
}
|
||||
|
||||
writeMainFile(categories: Map<string, CsoundReference[]>): void {
|
||||
const filePath = path.join(this.outputDir, 'csoundReference.ts');
|
||||
const content = this.generateMainFile(categories);
|
||||
|
||||
fs.writeFileSync(filePath, content, 'utf-8');
|
||||
console.log(`Generated: csoundReference.ts`);
|
||||
}
|
||||
|
||||
copyTypes(): void {
|
||||
if (!fs.existsSync(this.outputDir)) {
|
||||
fs.mkdirSync(this.outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
const sourceTypes = path.join(__dirname, 'types.ts');
|
||||
const destTypes = path.join(this.outputDir, 'types.ts');
|
||||
|
||||
if (fs.existsSync(sourceTypes)) {
|
||||
fs.copyFileSync(sourceTypes, destTypes);
|
||||
console.log(`Copied: types.ts`);
|
||||
}
|
||||
}
|
||||
|
||||
generateAll(categories: Map<string, CsoundReference[]>): void {
|
||||
console.log(`\nGenerating TypeScript files...`);
|
||||
this.copyTypes();
|
||||
this.writeCategoryFiles(categories);
|
||||
this.writeMainFile(categories);
|
||||
console.log(`\nDone!`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user