diff --git a/README.md b/README.md index 221871f..271d592 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ The [online generator](http://pegjs.majda.cz/online) is easiest to use — you j To generate the parser from JavaScript code, include the `lib/compiler.js` file and use the `PEG.buildParser` function. This function accepts a string with a grammar and either returns the built parser object or throws an exception if the grammar is invalid. -To generate the parser from a command line, you need to have Java installed (so that [Rhino](http://www.mozilla.org/rhino/) — which is included in PEG.js — can run). Use the `bin/pegjs` script on Unix or `bin/pegjs.bat` batch file on Windows: +To generate the parser from a command line, you need to have [Node](http://nodejs.org/) installed. Then use the `bin/pegjs` script: $ bin/pegjs --export-var arithmeticsParser examples/arithmetics.pegjs @@ -72,4 +72,4 @@ Both the parser generator and generated parsers should run well in the following * Chrome * Safari * Opera - * Rhino + * Node diff --git a/bin/pegjs b/bin/pegjs index 276c2b6..89bbe50 100755 --- a/bin/pegjs +++ b/bin/pegjs @@ -1,10 +1,127 @@ -#!/bin/sh +#!/usr/bin/env node -if [ -L "$0" ]; then - THIS_FILE=`readlink "$0"` -else - THIS_FILE=$0 -fi -DIR=`dirname "$THIS_FILE"` +var sys = require("sys"); +var fs = require("fs"); +var PEG = require("../lib/peg"); -java -jar "$DIR/../vendor/rhino/js.jar" "$DIR/pegjs-main.js" "$DIR" "$@" +/* ===== Helpers ===== */ + +function printVersion() { + sys.puts("PEG.js " + PEG.VERSION); +} + +function printHelp() { + sys.puts("Usage: pegjs [options] [--] [] []"); + sys.puts(""); + sys.puts("Generates a parser from the PEG grammar specified in the and"); + sys.puts("writes it to the ."); + sys.puts(""); + sys.puts("If the is omitted, its name is generated by changing the"); + sys.puts(" extension to \".js\". If both and are"); + sys.puts("omitted, standard input and output are used."); + sys.puts(""); + sys.puts("Options:"); + sys.puts(" -e, --export-var name of the variable where the parser object"); + sys.puts(" will be stored (default: \"exports.parser\")"); + sys.puts(" -v, --version print version information and exit"); + sys.puts(" -h, --help print help and exit"); +} + +function exitSuccess() { + process.exit(0); +} + +function exitFailure() { + process.exit(1); +} + +function abort(message) { + sys.error(message); + exitFailure(); +} + +/* ===== Arguments ===== */ + +var args = process.argv.slice(2); // Trim "node" and the script path. + +function isOption(arg) { + return /-.+/.test(arg); +} + +function nextArg() { + args.shift(); +} + +/* ===== Files ===== */ + +function readStream(inputStream, callback) { + var input = ""; + inputStream.on("data", function(data) { input += data; }); + inputStream.on("end", function() { callback(input); }); +} + +/* ===== Main ===== */ + +/* This makes the generated parser a CommonJS module by default. */ +var exportVar = "exports.parser"; + +while (args.length > 0 && isOption(args[0])) { + switch (args[0]) { + case "-e": + case "--export-var": + nextArg(); + exportVar = args[0]; + break; + + case "-v": + case "--version": + printVersion(); + exitSuccess(); + break; + + case "-h": + case "--help": + printHelp(); + exitSuccess(); + break; + + case "--": + nextArg(); + break; + + default: + abort("Unknown option: " + args[0] + "."); + } + nextArg(); +} + +switch (args.length) { + case 0: + var inputStream = process.openStdin(); + var outputStream = process.stdout; + break; + case 1: + case 2: + var inputStream = fs.createReadStream(args[0]); + var outputStream = fs.createWriteStream( + args.length == 1 ? args[0].replace(/\.[^.]*$/, ".js") : args[1] + ); + break; + default: + abort("Too many arguments."); +} + +readStream(inputStream, function(input) { + try { + var parser = PEG.buildParser(input); + } catch (e) { + if (e.line !== undefined && e.column !== undefined) { + abort(e.line + ":" + e.column + ": " + e.message); + } else { + abort(e.message); + } + } + + outputStream.write(exportVar + " = " + parser.toSource() + ";\n"); + outputStream.end(); +}); diff --git a/bin/pegjs-main.js b/bin/pegjs-main.js deleted file mode 100644 index b032177..0000000 --- a/bin/pegjs-main.js +++ /dev/null @@ -1,155 +0,0 @@ -importPackage(java.io); -importPackage(java.lang); - -/* - * Rhino does not have __FILE__ or anything similar so we have to pass the - * script path from the outside. - */ -load(arguments[0] + "/../lib/peg.js"); - -var FILE_STDIN = "-"; -var FILE_STDOUT = "-"; - -function readFile(file) { - var f = new BufferedReader(new InputStreamReader( - file === FILE_STDIN ? System["in"] : new FileInputStream(file) - )); - - var result = ""; - var line = ""; - try { - while ((line = f.readLine()) !== null) { - result += line + "\n"; - } - } finally { - f.close(); - } - - return result; -} - -function writeFile(file, text) { - var f = new BufferedWriter(new OutputStreamWriter( - file === FILE_STDOUT ? System.out : new FileOutputStream(file) - )); - - try { - f.write(text); - } finally { - f.close(); - } -} - -function isOption(arg) { - return /-.+/.test(arg); -} - -function printVersion() { - print("PEG.js " + PEG.VERSION); -} - -function printHelp() { - print("Usage: pegjs [options] [--] [] []"); - print(""); - print("Generates a parser from the PEG grammar specified in the and"); - print("writes it to the ."); - print(""); - print("If the is omitted, its name is generated by changing the"); - print(" extension to \".js\". If both and are"); - print("omitted, standard input and output are used."); - print(""); - print("Options:"); - print(" -e, --export-var name of the variable where the parser object"); - print(" will be stored (default: \"exports.parser\")"); - print(" -v, --version print version information and exit"); - print(" -h, --help print help and exit"); -} - -function nextArg() { - args.shift(); -} - -function exitSuccess() { - quit(0); -} - -function exitFailure() { - quit(1); -} - -function abort(message) { - System.out.println(message); - exitFailure(); -} - -/* This makes the generated parser a CommonJS module by default. */ -var exportVar = "exports.parser"; - -/* - * The trimmed first argument is the script path -- see the beginning of this - * file. - */ -var args = Array.prototype.slice.call(arguments, 1); - -while (args.length > 0 && isOption(args[0])) { - switch (args[0]) { - case "-e": - case "--export-var": - nextArg(); - exportVar = args[0]; - break; - - case "--version": - printVersion(); - exitSuccess(); - break; - case "-v": - case "--version": - printVersion(); - exitSuccess(); - break; - - case "-h": - case "--help": - printHelp(); - exitSuccess(); - break; - - case "--": - nextArg(); - break; - - default: - abort("Unknown option: " + args[0] + "."); - } - nextArg(); -} - -switch (args.length) { - case 0: - var inputFile = FILE_STDIN; - var outputFile = FILE_STDOUT; - break; - case 1: - var inputFile = args[0]; - var outputFile = args[0].replace(/\.[^.]*$/, ".js"); - break; - case 2: - var inputFile = args[0]; - var outputFile = args[1]; - break; - default: - abort("Too many arguments."); -} - -var input = readFile(inputFile); -try { - var parser = PEG.buildParser(input); -} catch (e) { - if (e.line !== undefined && e.column !== undefined) { - abort(e.line + ":" + e.column + ": " + e.message); - } else { - abort(e.message); - } -} -writeFile(outputFile, exportVar + " = " + parser.toSource() + ";\n"); diff --git a/bin/pegjs.bat b/bin/pegjs.bat deleted file mode 100644 index dbed212..0000000 --- a/bin/pegjs.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -set DIR_WITH_SLASH=%~dp0 -set DIR=%DIR_WITH_SLASH:~0,-1% - -java -jar "%DIR%\..\vendor\rhino\js.jar" "%DIR%\pegjs-main.js" "%DIR%" %* diff --git a/vendor/rhino/js.jar b/vendor/rhino/js.jar deleted file mode 100644 index 2369f99..0000000 Binary files a/vendor/rhino/js.jar and /dev/null differ