UNPKG

uppaal-to-tchecker

Version:

JavaScript implementation of Uppaal to TChecker translator - convert Uppaal timed automata models to TChecker format

183 lines (154 loc) 5.72 kB
#!/usr/bin/env node /** * CLI interface for uppaal-to-tchecker * JavaScript implementation of utot.cpp */ const { Command } = require('commander'); const chalk = require('chalk'); const fs = require('fs').promises; const path = require('path'); const UppaalToTChecker = require('../src/index'); const { UTOTException } = require('../src/exceptions'); const program = new Command(); // Package version const packageJson = require('../package.json'); program .name('utot') .description('Translate Uppaal models to TChecker format') .version(packageJson.version) .argument('[input-file]', 'Uppaal input file (stdin if not specified)') .argument('[output-file]', 'TChecker output file (stdout if not specified)') .option('-d, --debug', 'enable debug traces') .option('-e, --erase', 'erase output file if it exists') .option('-V, --verbose', 'increase the level of verbosity', (value, previous) => previous + 1, 0) .option('--xml', 'enforce XML as input format') .option('--xta', 'enforce XTA as input language') .option('--ta', 'enforce TA as input language') .option('--sysname <id>', 'specify the label of the system') .helpOption('-h, --help', 'display this help message'); program.parse(); const options = program.opts(); const args = program.args; async function main() { try { const translator = new UppaalToTChecker(); // Set options translator.setVerbose(options.verbose); translator.setDebug(options.debug); // Determine input and output const inputFile = args[0]; const outputFile = args[1]; // Build translation options const translateOptions = { verbose: options.verbose, debug: options.debug }; // Set format and language if (options.xml) { translateOptions.format = 'xml'; translateOptions.language = 'xta'; } else if (options.xta) { translateOptions.format = 'xta'; translateOptions.language = 'xta'; } else if (options.ta) { translateOptions.format = 'xta'; translateOptions.language = 'ta'; } // Set system name if (options.sysname) { translateOptions.systemName = options.sysname; } let result; if (inputFile) { // Check if output file exists and handle erase option if (outputFile && !options.erase) { try { await fs.access(outputFile); console.error(chalk.red(`Output file '${outputFile}' already exists. Use -e to overwrite.`)); process.exit(1); } catch (error) { // File doesn't exist, continue } } // Translate file result = await translator.translateFile(inputFile, outputFile, translateOptions); // Print to stdout if no output file specified if (!outputFile) { console.log(result); } } else { // Read from stdin const inputContent = await readStdin(); if (options.verbose) { console.error('Reading input from: standard input.'); } result = await translator.translate(inputContent, translateOptions); if (outputFile) { // Check if output file exists and handle erase option if (!options.erase) { try { await fs.access(outputFile); console.error(chalk.red(`Output file '${outputFile}' already exists. Use -e to overwrite.`)); process.exit(1); } catch (error) { // File doesn't exist, continue } } await fs.writeFile(outputFile, result); if (options.verbose) { console.error(`Output written to: ${outputFile}`); } } else { console.log(result); } } } catch (error) { if (error instanceof UTOTException) { console.error(chalk.red(`Error: ${error.message}`)); process.exit(1); } else { console.error(chalk.red(`Unexpected error: ${error.message}`)); if (options.debug) { console.error(error.stack); } process.exit(1); } } } /** * Read from stdin * @returns {Promise<string>} - Input content */ function readStdin() { return new Promise((resolve, reject) => { let content = ''; process.stdin.setEncoding('utf8'); process.stdin.on('readable', () => { let chunk; while (null !== (chunk = process.stdin.read())) { content += chunk; } }); process.stdin.on('end', () => { resolve(content); }); process.stdin.on('error', (error) => { reject(error); }); }); } // Handle unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { console.error(chalk.red('Unhandled Rejection at:'), promise, chalk.red('reason:'), reason); process.exit(1); }); // Handle uncaught exceptions process.on('uncaughtException', (error) => { console.error(chalk.red('Uncaught Exception:'), error.message); if (options && options.debug) { console.error(error.stack); } process.exit(1); }); // Run main function main();