diff --git a/Jakefile b/Jakefile deleted file mode 100644 index 7231a7e..0000000 --- a/Jakefile +++ /dev/null @@ -1,244 +0,0 @@ -var util = require("util"); -var fs = require("fs"); -var path = require("path"); -var childProcess = require("child_process"); - -var PEGJS_VERSION = fs.readFileSync("VERSION", "utf8").trim(); - -/* Relative paths are here because of use in |require|. */ -var SRC_DIR = "./src"; -var TEST_DIR = "./test"; -var BENCHMARK_DIR = "./benchmark"; -var LIB_DIR = "./lib"; -var BIN_DIR = "./bin"; -var EXAMPLES_DIR = "./examples"; -var DIST_DIR = "./dist"; -var DIST_WEB_DIR = "./dist/web"; -var DIST_NODE_DIR = "./dist/node"; - -var SRC_FILES = fs.readdirSync(SRC_DIR).filter(function(file) { - return /\.js$/.test(file); -}).map(function(file) { - return SRC_DIR + "/" + file; -}); - -var TEST_FILES = fs.readdirSync(TEST_DIR).filter(function(file) { - return /-test\.js$/.test(file); -}).map(function(file) { - return TEST_DIR + "/" + file; -}); -var TEST_HELPERS_FILE = TEST_DIR + "/helpers.js"; -var TEST_RUN_FILE = TEST_DIR + "/run"; - -var BENCHMARK_BENCHMARKS_FILE = BENCHMARK_DIR + "/benchmarks.js"; -var BENCHMARK_RUNNER_FILE = BENCHMARK_DIR + "/runner.js"; -var BENCHMARK_INDEX_FILE = BENCHMARK_DIR + "/index.js"; -var BENCHMARK_RUN_FILE = BENCHMARK_DIR + "/run"; - -var PEGJS = BIN_DIR + "/pegjs"; - -var PEGJS_SRC_FILE = SRC_DIR + "/peg.js"; -var PEGJS_OUT_FILE = LIB_DIR + "/peg.js"; - -var PEGJS_DIST_FILE = DIST_WEB_DIR + "/peg-" + PEGJS_VERSION + ".js" -var PEGJS_DIST_MIN_FILE = DIST_WEB_DIR + "/peg-" + PEGJS_VERSION + ".min.js" - -var PARSER_SRC_FILE = SRC_DIR + "/parser.pegjs"; -var PARSER_OUT_FILE = SRC_DIR + "/parser.js"; - -var JAKEFILE = "./Jakefile"; - -function exitFailure() { - process.exit(1); -} - -function abort(message) { - util.error(message); - exitFailure(); -} - -function mkdirUnlessExists(dir) { - try { - fs.statSync(dir); - } catch (e) { - fs.mkdirSync(dir, 0755); - } -} - -function copyFile(src, dest) { - fs.writeFileSync(dest, fs.readFileSync(src)); -} - -function copyDir(src, dest) { - mkdirUnlessExists(dest); - - fs.readdirSync(src).every(function(file) { - var srcFile = src + "/" + file; - var destFile = dest + "/" + file; - - var stats = fs.statSync(srcFile); - if (stats.isDirectory()) { - copyDir(srcFile, destFile); - } else { - copyFile(srcFile, destFile); - fs.chmodSync(destFile, stats.mode); - } - - return true; - }); -} - -function dirExists(dir) { - try { - var stats = fs.statSync(file); - } catch (e) { - return false; - } - - return stats.isDirectory(); -} - -function removeDir(dir) { - fs.readdirSync(dir).every(function(file) { - var file = dir + "/" + file; - - var stats = fs.statSync(file); - if (stats.isDirectory()) { - removeDir(file); - } else { - fs.unlinkSync(file); - } - - return true; - }); - - fs.rmdirSync(dir); -} - -function preprocess(file) { - var input = fs.readFileSync(file, "utf8").trim(); - return input.split("\n").map(function(line) { - var matches = /^\s*\/\/\s*@include\s*"([^"]*)"\s*$/.exec(line); - if (matches !== null) { - var includedFile = SRC_DIR + "/" + matches[1]; - - try { - fs.statSync(includedFile); - } catch (e) { - abort("Included file \"" + includedFile + "\" does not exist."); - } - - return preprocess(includedFile); - } else { - return line; - } - }).join("\n").replace(/@VERSION/g, PEGJS_VERSION); -} - -desc("Generate the grammar parser"); -task("parser", [], function() { - var PEG = require(PEGJS_OUT_FILE); - var input = fs.readFileSync(PARSER_SRC_FILE, "utf8"); - - 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); - } - } - - fs.writeFileSync(PARSER_OUT_FILE, "PEG.parser = " + parser.toSource() + ";\n"); -}); - -desc("Build the peg.js file"); -task("build", [], function() { - mkdirUnlessExists(LIB_DIR); - fs.writeFileSync(PEGJS_OUT_FILE, preprocess(PEGJS_SRC_FILE), "utf8"); -}); - -desc("Remove built peg.js file (created by \"build\")"); -task("clean", [], function() { - if (dirExists(LIB_DIR)) { - removeDir(LIB_DIR); - } -}); - -desc("Prepare the distribution files"); -task("dist", ["build"], function() { - mkdirUnlessExists(DIST_DIR); - - /* Web */ - - mkdirUnlessExists(DIST_WEB_DIR); - - copyFile(PEGJS_OUT_FILE, PEGJS_DIST_FILE); - - var process = childProcess.spawn( - "uglifyjs", - ["--ascii", "-o", PEGJS_DIST_MIN_FILE, PEGJS_OUT_FILE], - { customFds: [0, 1, 2] } - ); - process.on("exit", function() { complete(); }); - - /* Node.js */ - - mkdirUnlessExists(DIST_NODE_DIR); - - copyDir(LIB_DIR, DIST_NODE_DIR + "/lib"); - copyDir(BIN_DIR, DIST_NODE_DIR + "/bin"); - copyDir(EXAMPLES_DIR, DIST_NODE_DIR + "/examples"); - - copyFile("CHANGELOG", DIST_NODE_DIR + "/CHANGELOG"); - copyFile("LICENSE", DIST_NODE_DIR + "/LICENSE"); - copyFile("README.md", DIST_NODE_DIR + "/README.md"); - copyFile("VERSION", DIST_NODE_DIR + "/VERSION"); - - fs.writeFileSync(DIST_NODE_DIR + "/package.json", preprocess("package.json"), "utf8"); -}, true); - -desc("Remove the distribution files (created by \"dist\")"); -task("distclean", [], function() { - if (dirExists(DIST_DIR)) { - removeDir(DIST_DIR); - } -}); - -desc("Run the test suite"); -task("test", ["build"], function() { - var process = childProcess.spawn("test/run", [], { customFds: [0, 1, 2] }); - process.on("exit", function() { complete(); }); -}, true); - -desc("Run the benchmark suite"); -task("benchmark", ["build"], function(runCount) { - var process = childProcess.spawn( - "benchmark/run", - runCount !== undefined ? [runCount] : [], - { customFds: [0, 1, 2] } - ); - process.on("exit", function() { complete(); }); -}, true); - -desc("Run JSHint"); -task("hint", ["build"], function() { - var process = childProcess.spawn( - "jshint", - SRC_FILES.concat(TEST_FILES).concat([ - TEST_HELPERS_FILE, - TEST_RUN_FILE, - BENCHMARK_BENCHMARKS_FILE, - BENCHMARK_RUNNER_FILE, - BENCHMARK_INDEX_FILE, - BENCHMARK_RUN_FILE, - PEGJS, - JAKEFILE - ]), - { customFds: [0, 1, 2] } - ); - process.on("exit", function() { complete(); }); -}, true); - -task("default", ["build"], function() {}); diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fdd7807 --- /dev/null +++ b/Makefile @@ -0,0 +1,145 @@ +# ===== Directories ===== + +SRC_DIR = src +BIN_DIR = bin +TEST_DIR = test +BENCHMARK_DIR = benchmark +EXAMPLES_DIR = examples +LIB_DIR = lib +DIST_DIR = dist +DIST_WEB_DIR = $(DIST_DIR)/web +DIST_NODE_DIR = $(DIST_DIR)/node + +# ===== Files ===== + +PARSER_SRC_FILE = $(SRC_DIR)/parser.pegjs +PARSER_OUT_FILE = $(SRC_DIR)/parser.js + +PEGJS_SRC_FILE = $(SRC_DIR)/peg.js +PEGJS_LIB_FILE = $(LIB_DIR)/peg.js + +PACKAGE_JSON_SRC_FILE = package.json +PACKAGE_JSON_DIST_FILE = $(DIST_NODE_DIR)/package.json + +PEGJS_DIST_FILE_DEV = $(DIST_WEB_DIR)/peg-$(PEGJS_VERSION).js +PEGJS_DIST_FILE_MIN = $(DIST_WEB_DIR)/peg-$(PEGJS_VERSION).min.js + +CHANGELOG_FILE = CHANGELOG +LICENSE_FILE = LICENSE +README_FILE = README.md +VERSION_FILE = VERSION + +# ===== Executables ===== + +JSHINT = jshint +UGLIFYJS = uglifyjs +PEGJS = $(BIN_DIR)/pegjs +TEST_RUN = $(TEST_DIR)/run +BENCHMARK_RUN = $(BENCHMARK_DIR)/run + +# ===== Variables ===== + +PEGJS_VERSION = `cat $(VERSION_FILE)` + +# ===== Preprocessor ===== + +# A simple preprocessor that recognizes two directives: +# +# @VERSION -- insert PEG.js version +# @include "" -- include here +# +# This could have been implemented many ways. I chose Perl because everyone will +# have it. +PREPROCESS=perl -e ' \ + use strict; \ + use warnings; \ + \ + use File::Basename; \ + \ + open(my $$f, "$(VERSION_FILE)") or die "Can\x27t open $(VERSION_FILE): $$!"; \ + my $$PEGJS_VERSION = <$$f>; \ + close($$f); \ + chomp($$PEGJS_VERSION); \ + \ + sub preprocess { \ + my $$file = shift; \ + my $$output = ""; \ + \ + open(my $$f, $$file) or die "Can\x27t open $$file: $$!"; \ + while(<$$f>) { \ + s/\@VERSION/$$PEGJS_VERSION/g; \ + \ + if (/^\s*\/\/\s*\@include\s*"([^"]*)"\s*$$/) { \ + $$output .= preprocess(dirname($$file) . "/" . $$1); \ + next; \ + } \ + \ + $$output .= $$_; \ + } \ + close($$f); \ + \ + return $$output; \ + } \ + \ + print preprocess($$ARGV[0]); \ +' + +# ===== Targets ===== + +# Generate the grammar parser +parser: + $(PEGJS) --export-var PEG.parser $(PARSER_SRC_FILE) $(PARSER_OUT_FILE) + +# Build the PEG.js library +build: + mkdir -p $(LIB_DIR) + $(PREPROCESS) $(PEGJS_SRC_FILE) > $(PEGJS_LIB_FILE) + +# Remove built PEG.js library (created by "build") +clean: + rm -rf $(LIB_DIR) + +# Prepare dstribution files +dist: build + # Web + mkdir -p $(DIST_WEB_DIR) + cp $(PEGJS_LIB_FILE) $(PEGJS_DIST_FILE_DEV) + $(UGLIFYJS) --ascii -o $(PEGJS_DIST_FILE_MIN) $(PEGJS_LIB_FILE) + + # Node.js + mkdir -p $(DIST_NODE_DIR) + cp -r \ + $(LIB_DIR) \ + $(BIN_DIR) \ + $(EXAMPLES_DIR) \ + $(CHANGELOG_FILE) \ + $(LICENSE_FILE) \ + $(README_FILE) \ + $(VERSION_FILE) \ + $(DIST_NODE_DIR) + $(PREPROCESS) $(PACKAGE_JSON_SRC_FILE) > $(PACKAGE_JSON_DIST_FILE) + +# Remove distribution file (created by "dist") +distclean: + rm -rf $(DIST_DIR) + +# Run the test suite +test: build + $(TEST_RUN) + +# Run the benchmark suite +benchmark: build + $(BENCHMARK_RUN) + +# Run JSHint on the source +hint: build + $(JSHINT) \ + $(SRC_DIR)/*.js \ + $(TEST_DIR)/*.js \ + $(TEST_RUN) \ + $(BENCHMARK_DIR)/*.js \ + $(BENCHMARK_RUN) \ + $(PEGJS) + +.PHONY: test benchmark hint parser build clean dist distclean +.SILENT: test benchmark hint parser build clean dist distclean diff --git a/package.json b/package.json index fff90fc..893ddce 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "url": "http://github.com/dmajda/pegjs.git" }, "devDependencies": { - "jake": ">= 0.1.22", "uglify-js": ">= 1.2.4", "jshint": ">= 0.5.5" }, diff --git a/tools/impact b/tools/impact index 92099ec..89d79bf 100755 --- a/tools/impact +++ b/tools/impact @@ -9,11 +9,11 @@ set -e prepare() { git checkout --quiet "$1" - jake build + make build } run_benchmark() { - echo $(jake benchmark | awk 'BEGIN { FS = " *│ *" } /Total/ { split($5, a, " "); print a[1] }') + echo $(make benchmark | awk 'BEGIN { FS = " *│ *" } /Total/ { split($5, a, " "); print a[1] }') } measure_speed() {