Browse Source
This is related to my last commit. I've updated all the JavaScript files to satisfy 'eslint-config-futagozaryuu', my eslint configuration. I'm sure I've probally missed something, but I've run all NPM scripts and Gulp tasks, fixed any bugs that cropped up, and updated some stuff (mainly related to generated messages), so as far as I can, tell this conversion is over (I know I've probally jixed it just by saying this ;P).master
41 changed files with 8668 additions and 6958 deletions
@ -1,89 +1,96 @@ |
|||
"use strict"; |
|||
|
|||
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 rename = require("gulp-rename"); |
|||
let runSequence = require("run-sequence"); |
|||
let source = require("vinyl-source-stream"); |
|||
let spawn = require("child_process").spawn; |
|||
let uglify = require("gulp-uglify"); |
|||
|
|||
function execFile(args) { |
|||
return spawn("node", args.split(" "), { stdio: "inherit" }); |
|||
const version = require( "./package" ).version; |
|||
const spawn = require( "child_process" ).spawn; |
|||
const gulp = require( "gulp" ); |
|||
const task = gulp.task.bind( gulp ); |
|||
const eslint = require( "gulp-eslint" ); |
|||
const mocha = require( "gulp-mocha" ); |
|||
const dedent = require( "dedent" ); |
|||
const browserify = require( "browserify" ); |
|||
const babelify = require( "babelify" ); |
|||
const source = require( "vinyl-source-stream" ); |
|||
const rename = require( "gulp-rename" ); |
|||
const buffer = require( "vinyl-buffer" ); |
|||
const uglify = require( "gulp-uglify" ); |
|||
const header = require( "gulp-header" ); |
|||
const del = require( "del" ); |
|||
const runSequence = require( "run-sequence" ); |
|||
|
|||
function node( args ) { |
|||
|
|||
return spawn( "node", args.split( " " ), { stdio: "inherit" } ); |
|||
|
|||
} |
|||
|
|||
// Run ESLint on all JavaScript files.
|
|||
gulp.task("lint", () => |
|||
gulp.src([ |
|||
"lib/**/*.js", |
|||
"!lib/parser.js", |
|||
"test/benchmark/**/*.js", |
|||
"test/benchmark/run", |
|||
"test/impact", |
|||
"test/spec/**/*.js", |
|||
"test/server/run", |
|||
"bin/*.js", |
|||
"gulpfile.js" |
|||
]) |
|||
.pipe(eslint()) |
|||
.pipe(eslint.format()) |
|||
.pipe(eslint.failAfterError()) |
|||
task( "lint", () => gulp |
|||
.src( [ |
|||
"**/.*rc.js", |
|||
"lib/**/*.js", |
|||
"!lib/parser.js", |
|||
"test/benchmark/**/*.js", |
|||
"test/benchmark/run", |
|||
"test/impact", |
|||
"test/spec/**/*.js", |
|||
"test/server/run", |
|||
"bin/*.js", |
|||
"gulpfile.js" |
|||
] ) |
|||
.pipe( eslint( { dotfiles: true } ) ) |
|||
.pipe( eslint.format() ) |
|||
.pipe( eslint.failAfterError() ) |
|||
); |
|||
|
|||
// Run tests.
|
|||
gulp.task("test", () => |
|||
gulp.src("test/spec/**/*.spec.js", { read: false }) |
|||
.pipe(mocha()) |
|||
task( "test", () => gulp |
|||
.src( "test/spec/**/*.spec.js", { read: false } ) |
|||
.pipe( mocha() ) |
|||
); |
|||
|
|||
// Run benchmarks.
|
|||
gulp.task("benchmark", () => execFile("test/benchmark/run")); |
|||
task( "benchmark", () => node( "test/benchmark/run" ) ); |
|||
|
|||
// Create the browser build.
|
|||
gulp.task("browser:build", () => { |
|||
const HEADER = [ |
|||
"//", |
|||
"// PEG.js v" + require("./package").version, |
|||
"// https://pegjs.org/", |
|||
"//", |
|||
"// Copyright (c) 2010-2016 David Majda", |
|||
"// Copyright (c) 2017+ Futago-za Ryuu", |
|||
"//", |
|||
"// Licensed under the MIT License.", |
|||
"//", |
|||
"" |
|||
] |
|||
.map(line => `${line}\n`) |
|||
.join(""); |
|||
|
|||
return 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")); |
|||
}); |
|||
task( "browser:build", () => { |
|||
|
|||
const HEADER = dedent` |
|||
|
|||
/** |
|||
* PEG.js v${ version } |
|||
* https://pegjs.org/
|
|||
* |
|||
* Copyright (c) 2010-2016 David Majda |
|||
* Copyright (c) 2017+ Futago-za Ryuu |
|||
* |
|||
* Released under the MIT License. |
|||
*/\n\n |
|||
|
|||
`;
|
|||
|
|||
return 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")); |
|||
task( "browser:clean", () => del( "browser" ) ); |
|||
|
|||
// Generate the grammar parser.
|
|||
gulp.task("parser", () => |
|||
execFile("bin/peg src/parser.pegjs -o lib/parser.js") |
|||
task( "parser", () => |
|||
node( "bin/peg src/parser.pegjs -o lib/parser.js" ) |
|||
); |
|||
|
|||
// Default task.
|
|||
gulp.task("default", cb => |
|||
runSequence("lint", "test", cb) |
|||
task( "default", cb => |
|||
runSequence( "benchmark", "test", cb ) |
|||
); |
|||
|
@ -1,76 +1,102 @@ |
|||
"use strict"; |
|||
|
|||
let visitor = require("./visitor"); |
|||
const visitor = require( "./visitor" ); |
|||
|
|||
// AST utilities.
|
|||
let asts = { |
|||
findRule(ast, name) { |
|||
for (let i = 0; i < ast.rules.length; i++) { |
|||
if (ast.rules[i].name === name) { |
|||
return ast.rules[i]; |
|||
} |
|||
} |
|||
const asts = { |
|||
findRule( ast, name ) { |
|||
|
|||
return undefined; |
|||
}, |
|||
for ( let i = 0; i < ast.rules.length; i++ ) { |
|||
|
|||
indexOfRule(ast, name) { |
|||
for (let i = 0; i < ast.rules.length; i++) { |
|||
if (ast.rules[i].name === name) { |
|||
return i; |
|||
} |
|||
} |
|||
if ( ast.rules[ i ].name === name ) return ast.rules[ i ]; |
|||
|
|||
return -1; |
|||
}, |
|||
} |
|||
|
|||
alwaysConsumesOnSuccess(ast, node) { |
|||
function consumesTrue() { return true; } |
|||
function consumesFalse() { return false; } |
|||
return void 0; |
|||
|
|||
function consumesExpression(node) { |
|||
return consumes(node.expression); |
|||
} |
|||
}, |
|||
|
|||
indexOfRule( ast, name ) { |
|||
|
|||
for ( let i = 0; i < ast.rules.length; i++ ) { |
|||
|
|||
if ( ast.rules[ i ].name === name ) return i; |
|||
|
|||
} |
|||
|
|||
return -1; |
|||
|
|||
}, |
|||
|
|||
alwaysConsumesOnSuccess( ast, node ) { |
|||
|
|||
let consumes; |
|||
|
|||
function consumesTrue() { |
|||
|
|||
return true; |
|||
|
|||
} |
|||
function consumesFalse() { |
|||
|
|||
return false; |
|||
|
|||
} |
|||
|
|||
function consumesExpression( node ) { |
|||
|
|||
return consumes( node.expression ); |
|||
|
|||
} |
|||
|
|||
let consumes = visitor.build({ |
|||
rule: consumesExpression, |
|||
named: consumesExpression, |
|||
|
|||
choice(node) { |
|||
return node.alternatives.every(consumes); |
|||
}, |
|||
|
|||
action: consumesExpression, |
|||
|
|||
sequence(node) { |
|||
return node.elements.some(consumes); |
|||
}, |
|||
|
|||
labeled: consumesExpression, |
|||
text: consumesExpression, |
|||
simple_and: consumesFalse, |
|||
simple_not: consumesFalse, |
|||
optional: consumesFalse, |
|||
zero_or_more: consumesFalse, |
|||
one_or_more: consumesExpression, |
|||
group: consumesExpression, |
|||
semantic_and: consumesFalse, |
|||
semantic_not: consumesFalse, |
|||
|
|||
rule_ref(node) { |
|||
return consumes(asts.findRule(ast, node.name)); |
|||
}, |
|||
|
|||
literal(node) { |
|||
return node.value !== ""; |
|||
}, |
|||
|
|||
class: consumesTrue, |
|||
any: consumesTrue |
|||
}); |
|||
|
|||
return consumes(node); |
|||
} |
|||
consumes = visitor.build( { |
|||
rule: consumesExpression, |
|||
named: consumesExpression, |
|||
|
|||
choice( node ) { |
|||
|
|||
return node.alternatives.every( consumes ); |
|||
|
|||
}, |
|||
|
|||
action: consumesExpression, |
|||
|
|||
sequence( node ) { |
|||
|
|||
return node.elements.some( consumes ); |
|||
|
|||
}, |
|||
|
|||
labeled: consumesExpression, |
|||
text: consumesExpression, |
|||
simple_and: consumesFalse, |
|||
simple_not: consumesFalse, |
|||
optional: consumesFalse, |
|||
zero_or_more: consumesFalse, |
|||
one_or_more: consumesExpression, |
|||
group: consumesExpression, |
|||
semantic_and: consumesFalse, |
|||
semantic_not: consumesFalse, |
|||
|
|||
rule_ref( node ) { |
|||
|
|||
return consumes( asts.findRule( ast, node.name ) ); |
|||
|
|||
}, |
|||
|
|||
literal( node ) { |
|||
|
|||
return node.value !== ""; |
|||
|
|||
}, |
|||
|
|||
class: consumesTrue, |
|||
any: consumesTrue |
|||
} ); |
|||
|
|||
return consumes( node ); |
|||
|
|||
} |
|||
}; |
|||
|
|||
module.exports = asts; |
|||
|
@ -1,91 +1,109 @@ |
|||
"use strict"; |
|||
|
|||
let generateBytecode = require("./passes/generate-bytecode"); |
|||
let generateJS = require("./passes/generate-js"); |
|||
let removeProxyRules = require("./passes/remove-proxy-rules"); |
|||
let reportDuplicateLabels = require("./passes/report-duplicate-labels"); |
|||
let reportDuplicateRules = require("./passes/report-duplicate-rules"); |
|||
let reportInfiniteRecursion = require("./passes/report-infinite-recursion"); |
|||
let reportInfiniteRepetition = require("./passes/report-infinite-repetition"); |
|||
let reportUndefinedRules = require("./passes/report-undefined-rules"); |
|||
let visitor = require("./visitor"); |
|||
|
|||
function processOptions(options, defaults) { |
|||
let processedOptions = {}; |
|||
|
|||
Object.keys(options).forEach(name => { |
|||
processedOptions[name] = options[name]; |
|||
}); |
|||
|
|||
Object.keys(defaults).forEach(name => { |
|||
if (!Object.prototype.hasOwnProperty.call(processedOptions, name)) { |
|||
processedOptions[name] = defaults[name]; |
|||
} |
|||
}); |
|||
const generateBytecode = require( "./passes/generate-bytecode" ); |
|||
const generateJS = require( "./passes/generate-js" ); |
|||
const removeProxyRules = require( "./passes/remove-proxy-rules" ); |
|||
const reportDuplicateLabels = require( "./passes/report-duplicate-labels" ); |
|||
const reportDuplicateRules = require( "./passes/report-duplicate-rules" ); |
|||
const reportInfiniteRecursion = require( "./passes/report-infinite-recursion" ); |
|||
const reportInfiniteRepetition = require( "./passes/report-infinite-repetition" ); |
|||
const reportUndefinedRules = require( "./passes/report-undefined-rules" ); |
|||
const visitor = require( "./visitor" ); |
|||
|
|||
function processOptions( options, defaults ) { |
|||
|
|||
const processedOptions = {}; |
|||
|
|||
Object.keys( options ).forEach( name => { |
|||
|
|||
processedOptions[ name ] = options[ name ]; |
|||
|
|||
} ); |
|||
|
|||
Object.keys( defaults ).forEach( name => { |
|||
|
|||
if ( ! Object.prototype.hasOwnProperty.call( processedOptions, name ) ) { |
|||
|
|||
processedOptions[ name ] = defaults[ name ]; |
|||
|
|||
} |
|||
|
|||
} ); |
|||
|
|||
return processedOptions; |
|||
|
|||
return processedOptions; |
|||
} |
|||
|
|||
let compiler = { |
|||
// AST node visitor builder. Useful mainly for plugins which manipulate the
|
|||
// AST.
|
|||
visitor: visitor, |
|||
|
|||
// Compiler passes.
|
|||
//
|
|||
// Each pass is a function that is passed the AST. It can perform checks on it
|
|||
// or modify it as needed. If the pass encounters a semantic error, it throws
|
|||
// |peg.GrammarError|.
|
|||
passes: { |
|||
check: { |
|||
reportUndefinedRules: reportUndefinedRules, |
|||
reportDuplicateRules: reportDuplicateRules, |
|||
reportDuplicateLabels: reportDuplicateLabels, |
|||
reportInfiniteRecursion: reportInfiniteRecursion, |
|||
reportInfiniteRepetition: reportInfiniteRepetition |
|||
}, |
|||
transform: { |
|||
removeProxyRules: removeProxyRules |
|||
const compiler = { |
|||
// AST node visitor builder. Useful mainly for plugins which manipulate the
|
|||
// AST.
|
|||
visitor: visitor, |
|||
|
|||
// Compiler passes.
|
|||
//
|
|||
// Each pass is a function that is passed the AST. It can perform checks on it
|
|||
// or modify it as needed. If the pass encounters a semantic error, it throws
|
|||
// |peg.GrammarError|.
|
|||
passes: { |
|||
check: { |
|||
reportUndefinedRules: reportUndefinedRules, |
|||
reportDuplicateRules: reportDuplicateRules, |
|||
reportDuplicateLabels: reportDuplicateLabels, |
|||
reportInfiniteRecursion: reportInfiniteRecursion, |
|||
reportInfiniteRepetition: reportInfiniteRepetition |
|||
}, |
|||
transform: { |
|||
removeProxyRules: removeProxyRules |
|||
}, |
|||
generate: { |
|||
generateBytecode: generateBytecode, |
|||
generateJS: generateJS |
|||
} |
|||
}, |
|||
generate: { |
|||
generateBytecode: generateBytecode, |
|||
generateJS: generateJS |
|||
} |
|||
}, |
|||
|
|||
// Generates a parser from a specified grammar AST. Throws |peg.GrammarError|
|
|||
// if the AST contains a semantic error. Note that not all errors are detected
|
|||
// during the generation and some may protrude to the generated parser and
|
|||
// cause its malfunction.
|
|||
compile(ast, passes, options) { |
|||
options = options !== undefined ? options : {}; |
|||
|
|||
options = processOptions(options, { |
|||
allowedStartRules: [ast.rules[0].name], |
|||
cache: false, |
|||
dependencies: {}, |
|||
exportVar: null, |
|||
format: "bare", |
|||
optimize: "speed", |
|||
output: "parser", |
|||
trace: false |
|||
}); |
|||
|
|||
Object.keys(passes).forEach(stage => { |
|||
passes[stage].forEach(p => { p(ast, options); }); |
|||
}); |
|||
|
|||
switch (options.output) { |
|||
case "parser": |
|||
return eval(ast.code); |
|||
|
|||
case "source": |
|||
return ast.code; |
|||
|
|||
default: |
|||
throw new Error("Invalid output format: " + options.output + "."); |
|||
|
|||
// Generates a parser from a specified grammar AST. Throws |peg.GrammarError|
|
|||
// if the AST contains a semantic error. Note that not all errors are detected
|
|||
// during the generation and some may protrude to the generated parser and
|
|||
// cause its malfunction.
|
|||
compile( ast, passes, options ) { |
|||
|
|||
options = typeof options !== "undefined" ? options : {}; |
|||
|
|||
options = processOptions( options, { |
|||
allowedStartRules: [ ast.rules[ 0 ].name ], |
|||
cache: false, |
|||
dependencies: {}, |
|||
exportVar: null, |
|||
format: "bare", |
|||
optimize: "speed", |
|||
output: "parser", |
|||
trace: false |
|||
} ); |
|||
|
|||
Object.keys( passes ).forEach( stage => { |
|||
|
|||
passes[ stage ].forEach( pass => { |
|||
|
|||
pass( ast, options ); |
|||
|
|||
} ); |
|||
|
|||
} ); |
|||
|
|||
switch ( options.output ) { |
|||
|
|||
case "parser": |
|||
return eval( ast.code ); |
|||
|
|||
case "source": |
|||
return ast.code; |
|||
|
|||
default: |
|||
throw new Error( `Invalid output format: ${ options.output }.` ); |
|||
|
|||
} |
|||
|
|||
} |
|||
} |
|||
}; |
|||
|
|||
module.exports = compiler; |
|||
|
@ -1,54 +1,62 @@ |
|||
"use strict"; |
|||
|
|||
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } |
|||
function hex( ch ) { |
|||
|
|||
return ch.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)); |
|||
}, |
|||
|
|||
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)); |
|||
} |
|||
const 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 ) ); |
|||
|
|||
}, |
|||
|
|||
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; |
|||
|
@ -1,54 +1,56 @@ |
|||
"use strict"; |
|||
|
|||
// Bytecode instruction opcodes.
|
|||
let opcodes = { |
|||
// Stack Manipulation
|
|||
|
|||
PUSH: 0, // PUSH c
|
|||
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
|
|||
PUSH_NULL: 2, // PUSH_NULL
|
|||
PUSH_FAILED: 3, // PUSH_FAILED
|
|||
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
|
|||
PUSH_CURR_POS: 5, // PUSH_CURR_POS
|
|||
POP: 6, // POP
|
|||
POP_CURR_POS: 7, // POP_CURR_POS
|
|||
POP_N: 8, // POP_N n
|
|||
NIP: 9, // NIP
|
|||
APPEND: 10, // APPEND
|
|||
WRAP: 11, // WRAP n
|
|||
TEXT: 12, // TEXT
|
|||
|
|||
// Conditions and Loops
|
|||
|
|||
IF: 13, // IF t, f
|
|||
IF_ERROR: 14, // IF_ERROR t, f
|
|||
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
|
|||
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
|
|||
|
|||
// Matching
|
|||
|
|||
MATCH_ANY: 17, // MATCH_ANY a, f, ...
|
|||
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
|
|||
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
|
|||
MATCH_REGEXP: 20, // MATCH_REGEXP r, a, f, ...
|
|||
ACCEPT_N: 21, // ACCEPT_N n
|
|||
ACCEPT_STRING: 22, // ACCEPT_STRING s
|
|||
FAIL: 23, // FAIL e
|
|||
|
|||
// Calls
|
|||
|
|||
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
|
|||
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
|
|||
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
|
|||
|
|||
// Rules
|
|||
|
|||
RULE: 27, // RULE r
|
|||
|
|||
// Failure Reporting
|
|||
|
|||
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
|
|||
SILENT_FAILS_OFF: 29 // SILENT_FAILS_OFF
|
|||
const opcodes = { |
|||
|
|||
// Stack Manipulation
|
|||
|
|||
PUSH: 0, // PUSH c
|
|||
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
|
|||
PUSH_NULL: 2, // PUSH_NULL
|
|||
PUSH_FAILED: 3, // PUSH_FAILED
|
|||
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
|
|||
PUSH_CURR_POS: 5, // PUSH_CURR_POS
|
|||
POP: 6, // POP
|
|||
POP_CURR_POS: 7, // POP_CURR_POS
|
|||
POP_N: 8, // POP_N n
|
|||
NIP: 9, // NIP
|
|||
APPEND: 10, // APPEND
|
|||
WRAP: 11, // WRAP n
|
|||
TEXT: 12, // TEXT
|
|||
|
|||
// Conditions and Loops
|
|||
|
|||
IF: 13, // IF t, f
|
|||
IF_ERROR: 14, // IF_ERROR t, f
|
|||
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
|
|||
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
|
|||
|
|||
// Matching
|
|||
|
|||
MATCH_ANY: 17, // MATCH_ANY a, f, ...
|
|||
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
|
|||
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
|
|||
MATCH_REGEXP: 20, // MATCH_REGEXP r, a, f, ...
|
|||
ACCEPT_N: 21, // ACCEPT_N n
|
|||
ACCEPT_STRING: 22, // ACCEPT_STRING s
|
|||
FAIL: 23, // FAIL e
|
|||
|
|||
// Calls
|
|||
|
|||
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
|
|||
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
|
|||
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
|
|||
|
|||
// Rules
|
|||
|
|||
RULE: 27, // RULE r
|
|||
|
|||
// Failure Reporting
|
|||
|
|||
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
|
|||
SILENT_FAILS_OFF: 29 // SILENT_FAILS_OFF
|
|||
|
|||
}; |
|||
|
|||
module.exports = opcodes; |
|||
|