parent
ed45a1808e
commit
bc5abfef5c
@ -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() {});
|
|
@ -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 "<file>" -- include <file> 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
|
Loading…
Reference in New Issue