Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
Sven Slootweg | 1d3a57d256 | 4 years ago |
Sven Slootweg | 1431320019 | 4 years ago |
Sven Slootweg | f11ef306c8 | 4 years ago |
Sven Slootweg | 51d6414151 | 4 years ago |
Sven Slootweg | 233f92f285 | 4 years ago |
Sven Slootweg | 937e1d4698 | 4 years ago |
Sven Slootweg | baf846b53f | 4 years ago |
Sven Slootweg | 8f737014fe | 4 years ago |
Sven Slootweg | 30400240e3 | 4 years ago |
Sven Slootweg | 69dbe3a4e4 | 4 years ago |
@ -0,0 +1,3 @@
|
||||
lib/parser.js
|
||||
test/vendor/**/*
|
||||
benchmark/vendor/**/*
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"extends": "dmajda"
|
||||
"extends": "@joepie91/eslint-config"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
browser/*
|
||||
browser
|
||||
examples/*.js
|
||||
node_modules/*
|
||||
node_modules
|
||||
|
@ -1,42 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
let benchmarks = [
|
||||
{
|
||||
id: "json",
|
||||
title: "JSON",
|
||||
tests: [
|
||||
{ file: "example1.json", title: "Example 1" },
|
||||
{ file: "example2.json", title: "Example 2" },
|
||||
{ file: "example3.json", title: "Example 3" },
|
||||
{ file: "example4.json", title: "Example 4" },
|
||||
{ file: "example5.json", title: "Example 5" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "css",
|
||||
title: "CSS",
|
||||
tests: [
|
||||
{ file: "blueprint/src/reset.css", title: "Blueprint - reset.css (source)" },
|
||||
{ file: "blueprint/src/typography.css", title: "Blueprint - typography.css (source)" },
|
||||
{ file: "blueprint/src/forms.css", title: "Blueprint - forms.css (source)" },
|
||||
{ file: "blueprint/src/grid.css", title: "Blueprint - grid.css (source)" },
|
||||
{ file: "blueprint/src/print.css", title: "Blueprint - print.css (source)" },
|
||||
// Contains syntax errors.
|
||||
// { file: "blueprint/src/ie.css", title: "Blueprint - ie.css (source)" },
|
||||
{ file: "blueprint/min/screen.css", title: "Blueprint - screen.css (minified)" },
|
||||
{ file: "blueprint/min/print.css", title: "Blueprint - print.css (minified)" },
|
||||
// Contains syntax errors.
|
||||
// { file: "blueprint/min/ie.css", title: "Blueprint - ie.css (minified)" },
|
||||
{ file: "960.gs/src/reset.css", title: "960.gs - reset.css (source)" },
|
||||
{ file: "960.gs/src/text.css", title: "960.gs - text.css (source)" },
|
||||
{ file: "960.gs/src/960.css", title: "960.gs - 960.css (source)" },
|
||||
{ file: "960.gs/src/960_24_col.css", title: "960.gs - 960_24_col.css (source)" },
|
||||
{ file: "960.gs/min/reset.css", title: "960.gs - reset.css (minified)" },
|
||||
{ file: "960.gs/min/text.css", title: "960.gs - text.css (minified)" },
|
||||
{ file: "960.gs/min/960.css", title: "960.gs - 960.css (minified)" },
|
||||
{ file: "960.gs/min/960_24_col.css", title: "960.gs - 960_24_col.css (minified)" }
|
||||
]
|
||||
}
|
||||
{
|
||||
id: "json",
|
||||
title: "JSON",
|
||||
tests: [
|
||||
{ file: "example1.json", title: "Example 1" },
|
||||
{ file: "example2.json", title: "Example 2" },
|
||||
{ file: "example3.json", title: "Example 3" },
|
||||
{ file: "example4.json", title: "Example 4" },
|
||||
{ file: "example5.json", title: "Example 5" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "css",
|
||||
title: "CSS",
|
||||
tests: [
|
||||
{ file: "blueprint/src/reset.css", title: "Blueprint - reset.css (source)" },
|
||||
{ file: "blueprint/src/typography.css", title: "Blueprint - typography.css (source)" },
|
||||
{ file: "blueprint/src/forms.css", title: "Blueprint - forms.css (source)" },
|
||||
{ file: "blueprint/src/grid.css", title: "Blueprint - grid.css (source)" },
|
||||
{ file: "blueprint/src/print.css", title: "Blueprint - print.css (source)" },
|
||||
// Contains syntax errors.
|
||||
// { file: "blueprint/src/ie.css", title: "Blueprint - ie.css (source)" },
|
||||
{ file: "blueprint/min/screen.css", title: "Blueprint - screen.css (minified)" },
|
||||
{ file: "blueprint/min/print.css", title: "Blueprint - print.css (minified)" },
|
||||
// Contains syntax errors.
|
||||
// { file: "blueprint/min/ie.css", title: "Blueprint - ie.css (minified)" },
|
||||
{ file: "960.gs/src/reset.css", title: "960.gs - reset.css (source)" },
|
||||
{ file: "960.gs/src/text.css", title: "960.gs - text.css (source)" },
|
||||
{ file: "960.gs/src/960.css", title: "960.gs - 960.css (source)" },
|
||||
{ file: "960.gs/src/960_24_col.css", title: "960.gs - 960_24_col.css (source)" },
|
||||
{ file: "960.gs/min/reset.css", title: "960.gs - reset.css (minified)" },
|
||||
{ file: "960.gs/min/text.css", title: "960.gs - text.css (minified)" },
|
||||
{ file: "960.gs/min/960.css", title: "960.gs - 960.css (minified)" },
|
||||
{ file: "960.gs/min/960_24_col.css", title: "960.gs - 960_24_col.css (minified)" }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = benchmarks;
|
||||
|
@ -1,118 +1,116 @@
|
||||
"use strict";
|
||||
|
||||
/* global setTimeout */
|
||||
|
||||
let peg = require("../lib/peg");
|
||||
|
||||
let Runner = {
|
||||
run(benchmarks, runCount, options, callbacks) {
|
||||
// Queue
|
||||
|
||||
let Q = {
|
||||
functions: [],
|
||||
|
||||
add(f) {
|
||||
this.functions.push(f);
|
||||
},
|
||||
|
||||
run() {
|
||||
if (this.functions.length > 0) {
|
||||
this.functions.shift()();
|
||||
|
||||
// We can't use |arguments.callee| here because |this| would get
|
||||
// messed-up in that case.
|
||||
setTimeout(() => { Q.run(); }, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The benchmark itself is factored out into several functions (some of them
|
||||
// generated), which are enqueued and run one by one using |setTimeout|. We
|
||||
// do this for two reasons:
|
||||
//
|
||||
// 1. To avoid bowser mechanism for interrupting long-running scripts to
|
||||
// kick-in (or at least to not kick-in that often).
|
||||
//
|
||||
// 2. To ensure progressive rendering of results in the browser (some
|
||||
// browsers do not render at all when running JavaScript code).
|
||||
//
|
||||
// The enqueued functions share state, which is all stored in the properties
|
||||
// of the |state| object.
|
||||
|
||||
let state = {};
|
||||
|
||||
function initialize() {
|
||||
callbacks.start();
|
||||
|
||||
state.totalInputSize = 0;
|
||||
state.totalParseTime = 0;
|
||||
}
|
||||
|
||||
function benchmarkInitializer(benchmark) {
|
||||
return function() {
|
||||
callbacks.benchmarkStart(benchmark);
|
||||
|
||||
state.parser = peg.generate(
|
||||
callbacks.readFile("../examples/" + benchmark.id + ".pegjs"),
|
||||
options
|
||||
);
|
||||
state.benchmarkInputSize = 0;
|
||||
state.benchmarkParseTime = 0;
|
||||
};
|
||||
}
|
||||
|
||||
function testRunner(benchmark, test) {
|
||||
return function() {
|
||||
callbacks.testStart(benchmark, test);
|
||||
|
||||
let input = callbacks.readFile(benchmark.id + "/" + test.file);
|
||||
|
||||
let parseTime = 0;
|
||||
for (let i = 0; i < runCount; i++) {
|
||||
let t = (new Date()).getTime();
|
||||
state.parser.parse(input);
|
||||
parseTime += (new Date()).getTime() - t;
|
||||
}
|
||||
let averageParseTime = parseTime / runCount;
|
||||
|
||||
callbacks.testFinish(benchmark, test, input.length, averageParseTime);
|
||||
|
||||
state.benchmarkInputSize += input.length;
|
||||
state.benchmarkParseTime += averageParseTime;
|
||||
};
|
||||
}
|
||||
|
||||
function benchmarkFinalizer(benchmark) {
|
||||
return function() {
|
||||
callbacks.benchmarkFinish(
|
||||
benchmark,
|
||||
state.benchmarkInputSize,
|
||||
state.benchmarkParseTime
|
||||
);
|
||||
|
||||
state.totalInputSize += state.benchmarkInputSize;
|
||||
state.totalParseTime += state.benchmarkParseTime;
|
||||
};
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
callbacks.finish(state.totalInputSize, state.totalParseTime);
|
||||
}
|
||||
|
||||
// Main
|
||||
|
||||
Q.add(initialize);
|
||||
benchmarks.forEach(benchmark => {
|
||||
Q.add(benchmarkInitializer(benchmark));
|
||||
benchmark.tests.forEach(test => {
|
||||
Q.add(testRunner(benchmark, test));
|
||||
});
|
||||
Q.add(benchmarkFinalizer(benchmark));
|
||||
});
|
||||
Q.add(finalize);
|
||||
|
||||
Q.run();
|
||||
}
|
||||
run(benchmarks, runCount, options, callbacks) {
|
||||
// Queue
|
||||
|
||||
let Q = {
|
||||
functions: [],
|
||||
|
||||
add(f) {
|
||||
this.functions.push(f);
|
||||
},
|
||||
|
||||
run() {
|
||||
if (this.functions.length > 0) {
|
||||
this.functions.shift()();
|
||||
|
||||
// We can't use |arguments.callee| here because |this| would get
|
||||
// messed-up in that case.
|
||||
setTimeout(() => { Q.run(); }, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The benchmark itself is factored out into several functions (some of them
|
||||
// generated), which are enqueued and run one by one using |setTimeout|. We
|
||||
// do this for two reasons:
|
||||
//
|
||||
// 1. To avoid bowser mechanism for interrupting long-running scripts to
|
||||
// kick-in (or at least to not kick-in that often).
|
||||
//
|
||||
// 2. To ensure progressive rendering of results in the browser (some
|
||||
// browsers do not render at all when running JavaScript code).
|
||||
//
|
||||
// The enqueued functions share state, which is all stored in the properties
|
||||
// of the |state| object.
|
||||
|
||||
let state = {};
|
||||
|
||||
function initialize() {
|
||||
callbacks.start();
|
||||
|
||||
state.totalInputSize = 0;
|
||||
state.totalParseTime = 0;
|
||||
}
|
||||
|
||||
function benchmarkInitializer(benchmark) {
|
||||
return function() {
|
||||
callbacks.benchmarkStart(benchmark);
|
||||
|
||||
state.parser = peg.generate(
|
||||
callbacks.readFile("../examples/" + benchmark.id + ".pegjs"),
|
||||
options
|
||||
);
|
||||
state.benchmarkInputSize = 0;
|
||||
state.benchmarkParseTime = 0;
|
||||
};
|
||||
}
|
||||
|
||||
function testRunner(benchmark, test) {
|
||||
return function() {
|
||||
callbacks.testStart(benchmark, test);
|
||||
|
||||
let input = callbacks.readFile(benchmark.id + "/" + test.file);
|
||||
|
||||
let parseTime = 0;
|
||||
for (let i = 0; i < runCount; i++) {
|
||||
let t = (new Date()).getTime();
|
||||
state.parser.parse(input);
|
||||
parseTime += (new Date()).getTime() - t;
|
||||
}
|
||||
let averageParseTime = parseTime / runCount;
|
||||
|
||||
callbacks.testFinish(benchmark, test, input.length, averageParseTime);
|
||||
|
||||
state.benchmarkInputSize += input.length;
|
||||
state.benchmarkParseTime += averageParseTime;
|
||||
};
|
||||
}
|
||||
|
||||
function benchmarkFinalizer(benchmark) {
|
||||
return function() {
|
||||
callbacks.benchmarkFinish(
|
||||
benchmark,
|
||||
state.benchmarkInputSize,
|
||||
state.benchmarkParseTime
|
||||
);
|
||||
|
||||
state.totalInputSize += state.benchmarkInputSize;
|
||||
state.totalParseTime += state.benchmarkParseTime;
|
||||
};
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
callbacks.finish(state.totalInputSize, state.totalParseTime);
|
||||
}
|
||||
|
||||
// Main
|
||||
|
||||
Q.add(initialize);
|
||||
benchmarks.forEach(benchmark => {
|
||||
Q.add(benchmarkInitializer(benchmark));
|
||||
benchmark.tests.forEach(test => {
|
||||
Q.add(testRunner(benchmark, test));
|
||||
});
|
||||
Q.add(benchmarkFinalizer(benchmark));
|
||||
});
|
||||
Q.add(finalize);
|
||||
|
||||
Q.run();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Runner;
|
||||
|
@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const util = require("util");
|
||||
|
||||
const generate = require("../").generate;
|
||||
const parser = require("../lib/parser");
|
||||
|
||||
let grammar = fs.readFileSync(path.join(__dirname, "test.pegjs"), { encoding: "utf-8" });
|
||||
// let parseResult = parser.parse(grammar);
|
||||
let parseResult = generate(grammar);
|
||||
|
||||
console.log(util.inspect(parseResult, { depth: null, colors: true }));
|
@ -0,0 +1,5 @@
|
||||
import Foo from "./util.pegjs"
|
||||
import { CommaDelimited as DelimitedNumber } from "./delimited-number"
|
||||
|
||||
TopLevelRule
|
||||
= "hello"
|
@ -1,108 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
let babelify = require("babelify");
|
||||
let browserify = require("browserify");
|
||||
let buffer = require("vinyl-buffer");
|
||||
let del = require("del");
|
||||
let eslint = require("gulp-eslint");
|
||||
let gulp = require("gulp");
|
||||
let header = require("gulp-header");
|
||||
let mocha = require("gulp-mocha");
|
||||
let package_ = require("./package");
|
||||
let peg = require("./lib/peg");
|
||||
let rename = require("gulp-rename");
|
||||
let runSequence = require("run-sequence");
|
||||
let source = require("vinyl-source-stream");
|
||||
let spawn = require("child_process").spawn;
|
||||
let transform = require("gulp-transform");
|
||||
let uglify = require("gulp-uglify");
|
||||
|
||||
const HEADER = [
|
||||
"// PEG.js " + package_.version,
|
||||
"//",
|
||||
"// https://pegjs.org/",
|
||||
"//",
|
||||
"// Copyright (c) 2010-2016 David Majda",
|
||||
"// Licensed under the MIT License.",
|
||||
""
|
||||
].map(line => `${line}\n`).join("");
|
||||
|
||||
const JS_FILES = [
|
||||
"lib/**/*.js",
|
||||
"!lib/parser.js",
|
||||
"test/**/*.js",
|
||||
"test/server",
|
||||
"!test/vendor/**/*",
|
||||
"benchmark/**/*.js",
|
||||
"benchmark/run",
|
||||
"benchmark/server",
|
||||
"!benchmark/vendor/**/*",
|
||||
"bin/pegjs",
|
||||
"gulpfile.js"
|
||||
];
|
||||
|
||||
const TEST_FILES = [
|
||||
"test/**/*.js",
|
||||
"!test/vendor/**/*"
|
||||
];
|
||||
|
||||
function generate(contents) {
|
||||
return peg.generate(contents.toString(), {
|
||||
output: "source",
|
||||
format: "commonjs"
|
||||
});
|
||||
return peg.generate(contents.toString(), {
|
||||
output: "source",
|
||||
format: "commonjs"
|
||||
});
|
||||
}
|
||||
|
||||
// Run ESLint on all JavaScript files.
|
||||
gulp.task("lint", () =>
|
||||
gulp.src(JS_FILES)
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failAfterError())
|
||||
);
|
||||
|
||||
// Run tests.
|
||||
gulp.task("test", () =>
|
||||
gulp.src(TEST_FILES, { read: false })
|
||||
.pipe(mocha())
|
||||
);
|
||||
|
||||
// Run benchmarks.
|
||||
gulp.task("benchmark", () =>
|
||||
spawn("benchmark/run", { stdio: "inherit" })
|
||||
);
|
||||
|
||||
// Create the browser build.
|
||||
gulp.task("browser:build", () =>
|
||||
browserify("lib/peg.js", { standalone: "peg" })
|
||||
.transform(babelify, { presets: "es2015", compact: false })
|
||||
.bundle()
|
||||
.pipe(source("peg.js"))
|
||||
.pipe(header(HEADER))
|
||||
.pipe(gulp.dest("browser"))
|
||||
.pipe(rename({ suffix: ".min" }))
|
||||
.pipe(buffer())
|
||||
.pipe(uglify())
|
||||
.pipe(header(HEADER))
|
||||
.pipe(gulp.dest("browser"))
|
||||
);
|
||||
|
||||
// Delete the browser build.
|
||||
gulp.task("browser:clean", () =>
|
||||
del("browser")
|
||||
);
|
||||
|
||||
// Generate the grammar parser.
|
||||
gulp.task("parser", () =>
|
||||
gulp.src("src/parser.pegjs")
|
||||
.pipe(transform(generate))
|
||||
.pipe(rename({ extname: ".js" }))
|
||||
.pipe(gulp.dest("lib"))
|
||||
);
|
||||
|
||||
// Default task.
|
||||
gulp.task("default", cb =>
|
||||
runSequence("lint", "test", cb)
|
||||
gulp.src("src/parser.pegjs")
|
||||
.pipe(transform("utf8", generate))
|
||||
.pipe(rename({ extname: ".js" }))
|
||||
.pipe(gulp.dest("lib"))
|
||||
);
|
||||
|
@ -1,54 +1,59 @@
|
||||
"use strict";
|
||||
|
||||
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
|
||||
function hex(character) {
|
||||
return character
|
||||
.charCodeAt(0)
|
||||
.toString(16)
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
// JavaScript code generation helpers.
|
||||
let js = {
|
||||
stringEscape(s) {
|
||||
// ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
|
||||
// literal except for the closing quote character, backslash, carriage
|
||||
// return, line separator, paragraph separator, and line feed. Any character
|
||||
// may appear in the form of an escape sequence.
|
||||
//
|
||||
// For portability, we also escape all control and non-ASCII characters.
|
||||
return s
|
||||
.replace(/\\/g, "\\\\") // backslash
|
||||
.replace(/"/g, "\\\"") // closing double quote
|
||||
.replace(/\0/g, "\\0") // null
|
||||
.replace(/\x08/g, "\\b") // backspace
|
||||
.replace(/\t/g, "\\t") // horizontal tab
|
||||
.replace(/\n/g, "\\n") // line feed
|
||||
.replace(/\v/g, "\\v") // vertical tab
|
||||
.replace(/\f/g, "\\f") // form feed
|
||||
.replace(/\r/g, "\\r") // carriage return
|
||||
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
||||
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
||||
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
||||
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
||||
},
|
||||
stringEscape(s) {
|
||||
// ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
|
||||
// literal except for the closing quote character, backslash, carriage
|
||||
// return, line separator, paragraph separator, and line feed. Any character
|
||||
// may appear in the form of an escape sequence.
|
||||
//
|
||||
// For portability, we also escape all control and non-ASCII characters.
|
||||
return s
|
||||
.replace(/\\/g, "\\\\") // backslash
|
||||
.replace(/"/g, "\\\"") // closing double quote
|
||||
.replace(/\0/g, "\\0") // null
|
||||
.replace(/\x08/g, "\\b") // backspace
|
||||
.replace(/\t/g, "\\t") // horizontal tab
|
||||
.replace(/\n/g, "\\n") // line feed
|
||||
.replace(/\v/g, "\\v") // vertical tab
|
||||
.replace(/\f/g, "\\f") // form feed
|
||||
.replace(/\r/g, "\\r") // carriage return
|
||||
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
||||
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
||||
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
||||
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
||||
},
|
||||
|
||||
regexpClassEscape(s) {
|
||||
// Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
|
||||
//
|
||||
// For portability, we also escape all control and non-ASCII characters.
|
||||
return s
|
||||
.replace(/\\/g, "\\\\") // backslash
|
||||
.replace(/\//g, "\\/") // closing slash
|
||||
.replace(/]/g, "\\]") // closing bracket
|
||||
.replace(/\^/g, "\\^") // caret
|
||||
.replace(/-/g, "\\-") // dash
|
||||
.replace(/\0/g, "\\0") // null
|
||||
.replace(/\x08/g, "\\b") // backspace
|
||||
.replace(/\t/g, "\\t") // horizontal tab
|
||||
.replace(/\n/g, "\\n") // line feed
|
||||
.replace(/\v/g, "\\v") // vertical tab
|
||||
.replace(/\f/g, "\\f") // form feed
|
||||
.replace(/\r/g, "\\r") // carriage return
|
||||
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
||||
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
||||
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
||||
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
||||
}
|
||||
regexpClassEscape(s) {
|
||||
// Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
|
||||
//
|
||||
// For portability, we also escape all control and non-ASCII characters.
|
||||
return s
|
||||
.replace(/\\/g, "\\\\") // backslash
|
||||
.replace(/\//g, "\\/") // closing slash
|
||||
.replace(/]/g, "\\]") // closing bracket
|
||||
.replace(/\^/g, "\\^") // caret
|
||||
.replace(/-/g, "\\-") // dash
|
||||
.replace(/\0/g, "\\0") // null
|
||||
.replace(/\x08/g, "\\b") // backspace
|
||||
.replace(/\t/g, "\\t") // horizontal tab
|
||||
.replace(/\n/g, "\\n") // line feed
|
||||
.replace(/\v/g, "\\v") // vertical tab
|
||||
.replace(/\f/g, "\\f") // form feed
|
||||
.replace(/\r/g, "\\r") // carriage return
|
||||
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
||||
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
||||
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
||||
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = js;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,52 @@
|
||||
Import syntax
|
||||
|
||||
import Foo from packagename
|
||||
import { Foo, Bar } from ./util
|
||||
import { Foo as Bar, Baz, Qux } from ../quz
|
||||
|
||||
|
||||
need to mangle identifiers declared in the initializer!
|
||||
|
||||
===========
|
||||
|
||||
Benchmark before internals changes (best of 3):
|
||||
|
||||
$ yarn benchmark
|
||||
yarn run v1.21.1
|
||||
$ node benchmark/run
|
||||
┌─────────────────────────────────────┬───────────┬────────────┬──────────────┐
|
||||
│ Test │ Inp. size │ Avg. time │ Avg. speed │
|
||||
├─────────────────────────────────────┴───────────┴────────────┴──────────────┤
|
||||
│ JSON │
|
||||
├─────────────────────────────────────┬───────────┬────────────┬──────────────┤
|
||||
│ Example 1 │ 0.69 kB │ 0.40 ms │ 1723.63 kB/s │
|
||||
│ Example 2 │ 0.24 kB │ 0.10 ms │ 2363.28 kB/s │
|
||||
│ Example 3 │ 0.59 kB │ 0.40 ms │ 1474.61 kB/s │
|
||||
│ Example 4 │ 3.39 kB │ 0.90 ms │ 3763.02 kB/s │
|
||||
│ Example 5 │ 0.85 kB │ 0.20 ms │ 4262.70 kB/s │
|
||||
├─────────────────────────────────────┼───────────┼────────────┼──────────────┤
|
||||
│ JSON total │ 5.75 kB │ 2.00 ms │ 2877.44 kB/s │
|
||||
├─────────────────────────────────────┴───────────┴────────────┴──────────────┤
|
||||
│ CSS │
|
||||
├─────────────────────────────────────┬───────────┬────────────┬──────────────┤
|
||||
│ Blueprint - reset.css (source) │ 1.20 kB │ 3.00 ms │ 401.04 kB/s │
|
||||
│ Blueprint - typography.css (source) │ 3.11 kB │ 5.00 ms │ 621.48 kB/s │
|
||||
│ Blueprint - forms.css (source) │ 1.79 kB │ 2.00 ms │ 896.00 kB/s │
|
||||
│ Blueprint - grid.css (source) │ 9.54 kB │ 6.50 ms │ 1467.25 kB/s │
|
||||
│ Blueprint - print.css (source) │ 1.78 kB │ 1.10 ms │ 1621.09 kB/s │
|
||||
│ Blueprint - screen.css (minified) │ 11.83 kB │ 8.00 ms │ 1478.64 kB/s │
|
||||
│ Blueprint - print.css (minified) │ 1.25 kB │ 0.60 ms │ 2089.84 kB/s │
|
||||
│ 960.gs - reset.css (source) │ 0.99 kB │ 0.50 ms │ 1980.47 kB/s │
|
||||
│ 960.gs - text.css (source) │ 0.97 kB │ 0.40 ms │ 2426.76 kB/s │
|
||||
│ 960.gs - 960.css (source) │ 8.94 kB │ 3.00 ms │ 2979.49 kB/s │
|
||||
│ 960.gs - 960_24_col.css (source) │ 7.48 kB │ 2.60 ms │ 2877.85 kB/s │
|
||||
│ 960.gs - reset.css (minified) │ 0.63 kB │ 0.50 ms │ 1265.63 kB/s │
|
||||
│ 960.gs - text.css (minified) │ 0.41 kB │ 0.40 ms │ 1020.51 kB/s │
|
||||
│ 960.gs - 960.css (minified) │ 5.21 kB │ 2.60 ms │ 2004.21 kB/s │
|
||||
│ 960.gs - 960_24_col.css (minified) │ 4.94 kB │ 2.40 ms │ 2057.70 kB/s │
|
||||
├─────────────────────────────────────┼───────────┼────────────┼──────────────┤
|
||||
│ CSS total │ 60.08 kB │ 38.60 ms │ 1556.43 kB/s │
|
||||
├─────────────────────────────────────┼───────────┼────────────┼──────────────┤
|
||||
│ Total │ 65.83 kB │ 40.60 ms │ 1621.50 kB/s │
|
||||
└─────────────────────────────────────┴───────────┴────────────┴──────────────┘
|
||||
Done in 0.60s.
|
@ -1,128 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
let chai = require("chai");
|
||||
let peg = require("../../lib/peg");
|
||||
|
||||
let expect = chai.expect;
|
||||
|
||||
describe("plugin API", function() {
|
||||
describe("use", function() {
|
||||
let grammar = "start = 'a'";
|
||||
|
||||
it("is called for each plugin", function() {
|
||||
let pluginsUsed = [false, false, false];
|
||||
let plugins = [
|
||||
{ use() { pluginsUsed[0] = true; } },
|
||||
{ use() { pluginsUsed[1] = true; } },
|
||||
{ use() { pluginsUsed[2] = true; } }
|
||||
];
|
||||
|
||||
peg.generate(grammar, { plugins: plugins });
|
||||
|
||||
expect(pluginsUsed).to.deep.equal([true, true, true]);
|
||||
});
|
||||
|
||||
it("receives configuration", function() {
|
||||
let plugin = {
|
||||
use(config) {
|
||||
expect(config).to.be.an("object");
|
||||
|
||||
expect(config.parser).to.be.an("object");
|
||||
expect(config.parser.parse("start = 'a'")).to.be.an("object");
|
||||
|
||||
expect(config.passes).to.be.an("object");
|
||||
|
||||
expect(config.passes.check).to.be.an("array");
|
||||
config.passes.check.forEach(pass => {
|
||||
expect(pass).to.be.a("function");
|
||||
});
|
||||
|
||||
expect(config.passes.transform).to.be.an("array");
|
||||
config.passes.transform.forEach(pass => {
|
||||
expect(pass).to.be.a("function");
|
||||
});
|
||||
|
||||
expect(config.passes.generate).to.be.an("array");
|
||||
config.passes.generate.forEach(pass => {
|
||||
expect(pass).to.be.a("function");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
peg.generate(grammar, { plugins: [plugin] });
|
||||
});
|
||||
|
||||
it("receives options", function() {
|
||||
let plugin = {
|
||||
use(config, options) {
|
||||
expect(options).to.equal(generateOptions);
|
||||
}
|
||||
};
|
||||
let generateOptions = { plugins: [plugin], foo: 42 };
|
||||
|
||||
peg.generate(grammar, generateOptions);
|
||||
});
|
||||
|
||||
it("can replace parser", function() {
|
||||
let plugin = {
|
||||
use(config) {
|
||||
let parser = peg.generate([
|
||||
"start = .* {",
|
||||
" return {",
|
||||
" type: 'grammar',",
|
||||
" rules: [",
|
||||
" {",
|
||||
" type: 'rule',",
|
||||
" name: 'start',",
|
||||
" expression: { type: 'literal', value: text(), ignoreCase: false }",
|
||||
" }",
|
||||
" ]",
|
||||
" };",
|
||||
"}"
|
||||
].join("\n"));
|
||||
|
||||
config.parser = parser;
|
||||
}
|
||||
};
|
||||
let parser = peg.generate("a", { plugins: [plugin] });
|
||||
|
||||
expect(parser.parse("a")).to.equal("a");
|
||||
});
|
||||
|
||||
it("can change compiler passes", function() {
|
||||
let plugin = {
|
||||
use(config) {
|
||||
function pass(ast) {
|
||||
ast.code = "({ parse: function() { return 42; } })";
|
||||
}
|
||||
|
||||
config.passes.generate = [pass];
|
||||
}
|
||||
};
|
||||
let parser = peg.generate(grammar, { plugins: [plugin] });
|
||||
|
||||
expect(parser.parse("a")).to.equal(42);
|
||||
});
|
||||
|
||||
it("can change options", function() {
|
||||
let grammar = [
|
||||
"a = 'x'",
|
||||
"b = 'x'",
|
||||
"c = 'x'"
|
||||
].join("\n");
|
||||
let plugin = {
|
||||
use(config, options) {
|
||||
options.allowedStartRules = ["b", "c"];
|
||||
}
|
||||
};
|
||||
let parser = peg.generate(grammar, {
|
||||
allowedStartRules: ["a"],
|
||||
plugins: [plugin]
|
||||
});
|
||||
|
||||
expect(() => { parser.parse("x", { startRule: "a" }); }).to.throw();
|
||||
expect(parser.parse("x", { startRule: "b" })).to.equal("x");
|
||||
expect(parser.parse("x", { startRule: "c" })).to.equal("x");
|
||||
});
|
||||
});
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue