UNPKG

@gobstones/gobstones-lang

Version:
145 lines (128 loc) 4.54 kB
/* eslint-disable no-console */ /* eslint-disable quote-props */ /* Command-line interface */ import { RuntimeState } from './runtime'; import { Runner } from './runner'; import { readJboardFromFile, writeJboardToFile } from './board_formats'; import fs from 'fs'; import { GbsInterpreterException } from '@gobstones/gobstones-parser'; const startsWith = (string: string, prefix: string): boolean => string.substring(0, prefix.length) === prefix; export interface Options { arguments: string[]; 'initial-board'?: string; 'output-board'?: string; 'print-ast': boolean; 'print-code': boolean; help: boolean; } function readOptions(argv: string[]): Options { const options = { arguments: [], 'initial-board': undefined, 'output-board': undefined, 'print-ast': false, 'print-code': false, help: false }; let i = 2; while (i < argv.length) { if (argv[i] === '-h' || argv[i] === '--help') { options['help'] = true; } else if (argv[i] === '-a' || argv[i] === '--ast') { options['print-ast'] = true; } else if (argv[i] === '-c' || argv[i] === '--code') { options['print-code'] = true; } else if (argv[i] === '-i' && i + 1 < argv.length) { options['initial-board'] = argv[i + 1]; i++; } else if (startsWith(argv[i], '--initial-board=')) { options['initial-board'] = argv[i].substring('--initial-board='.length); } else if (argv[i] === '-o' && i + 1 < argv.length) { options['output-board'] = argv[i + 1]; i++; } else if (startsWith(argv[i], '--output-board=')) { options['output-board'] = argv[i].substring('--output-board='.length); } else { options['arguments'].push(argv[i]); } i++; } return options; } function help(): void { const helpMessage = [ 'Usage:', 'gobstones-lang input.gbs', '', ' -a, --ast Print AST (do not run).', ' -c, --code Print virtual machine code (do not run).', ' -i, --initial-board=<file> Load initial board. Default: empty 9x9.', ' -o, --output-board=<file> Save final board.', ' -h, --help Display this help message.' ]; console.log(helpMessage.join('\n')); } function printGbsException(exception: GbsInterpreterException): void { console.log(exception.message); const startPos = [ exception.startPos.filename, exception.startPos.line, exception.startPos.column ].join(':'); const endPos = [exception.endPos.line, exception.endPos.column].join(':'); console.log('At: ' + startPos + '--' + endPos); } function runProgram(options: Options, filename: string): void { const contents = fs.readFileSync(filename, 'utf8'); try { const inputs = {}; inputs[filename] = contents; const runner = new Runner(); if (options['print-ast']) { runner.parse(inputs); runner.lint(); console.log(runner.abstractSyntaxTree.toString()); return; } if (options['print-code']) { runner.parse(inputs); runner.lint(); runner.compile(); console.log(runner.virtualMachineCode.toString()); return; } const initialState = new RuntimeState(); if (options['initial-board'] !== undefined) { initialState.load(readJboardFromFile(options['initial-board'])); } const output = runner.runState(inputs, initialState); const finalState = output.state.dump(); console.log(JSON.stringify(finalState)); if (options['output-board'] !== undefined) { writeJboardToFile(options['output-board'], finalState); } if (output.result !== undefined) { /* The program has a return value */ console.log(output.result.toString()); } } catch (exception) { if (exception.isGobstonesException === undefined) { throw exception; } printGbsException(exception); } } function main(): void { const options = readOptions(process.argv); if (options['help']) { help(); return; } if (options['arguments'].length === 1) { runProgram(options, options['arguments'][0]); } else { help(); } } main();