Browse Source

Fix IE11 Support (#583)

- Revert ES6 changes to arithmetics.pegjs
- Use Array#forEach instead of for..of
- Don't use native Array#find & Array#findIndex
- Added util/arrays.js (find & findIndex)
- Use Function instead of eval
master
Futago-za Ryuu 3 years ago
parent
commit
616749377b
  1. 12
      examples/arithmetics.pegjs
  2. 12
      packages/pegjs/lib/ast/Grammar.js
  3. 3
      packages/pegjs/lib/compiler/index.js
  4. 6
      packages/pegjs/lib/compiler/passes/generate-bytecode.js
  5. 6
      packages/pegjs/lib/compiler/passes/remove-proxy-rules.js
  6. 6
      packages/pegjs/lib/parser.js
  7. 33
      packages/pegjs/lib/util/arrays.js
  8. 2
      packages/pegjs/lib/util/index.js
  9. 64
      packages/pegjs/lib/util/vm.js
  10. 10
      packages/pegjs/typings/api.d.ts
  11. 7
      packages/pegjs/typings/modules.d.ts
  12. 6
      src/parser.pegjs

12
examples/arithmetics.pegjs

@ -5,17 +5,17 @@
Expression
= head:Term tail:(_ @("+" / "-") _ @Term)* {
return tail.reduce(function(result, [operator, factor]) {
if (operator === "+") return result + factor;
if (operator === "-") return result - factor;
return tail.reduce(function(result, element) {
if (element[0] === "+") return result + element[1];
if (element[0] === "-") return result - element[1];
}, head);
}
Term
= head:Factor tail:(_ @("*" / "/") _ @Factor)* {
return tail.reduce(function(result, [operator, factor]) {
if (operator === "*") return result * factor;
if (operator === "/") return result / factor;
return tail.reduce(function(result, element) {
if (element[0] === "*") return result * element[1];
if (element[0] === "/") return result / element[1];
}, head);
}

12
packages/pegjs/lib/ast/Grammar.js

@ -27,21 +27,13 @@ class Grammar extends Node {
findRule( name ) {
return this.rules.find( rule => rule.name === name );
return util.find( this.rules, rule => rule.name === name );
}
indexOfRule( name ) {
const rules = this.rules;
for ( let i = 0; i < rules.length; ++i ) {
if ( rules[ i ].name === name ) return i;
}
return -1;
return util.findIndex( this.rules, rule => rule.name === name );
}

3
packages/pegjs/lib/compiler/index.js

@ -67,6 +67,9 @@ const compiler = {
trace: false
} );
// We want `session.vm.runInContext` to return the parser
if ( options.output === "parser" ) options.format = "bare";
util.each( session.passes, stage => {
stage.forEach( pass => {

6
packages/pegjs/lib/compiler/passes/generate-bytecode.js

@ -222,7 +222,7 @@ function generateBytecode( ast, session ) {
ignoreCase: node.ignoreCase
};
const pattern = JSON.stringify( cls );
const index = classes.findIndex( c => JSON.stringify( c ) === pattern );
const index = util.findIndex( classes, c => JSON.stringify( c ) === pattern );
return index === -1 ? classes.push( cls ) - 1 : index;
}
@ -230,7 +230,7 @@ function generateBytecode( ast, session ) {
function addExpectedConst( expected ) {
const pattern = JSON.stringify( expected );
const index = expectations.findIndex( e => JSON.stringify( e ) === pattern );
const index = util.findIndex( expectations, e => JSON.stringify( e ) === pattern );
return index === -1 ? expectations.push( expected ) - 1 : index;
}
@ -239,7 +239,7 @@ function generateBytecode( ast, session ) {
const func = { predicate: predicate, params: params, body: code };
const pattern = JSON.stringify( func );
const index = functions.findIndex( f => JSON.stringify( f ) === pattern );
const index = util.findIndex( functions, f => JSON.stringify( f ) === pattern );
return index === -1 ? functions.push( func ) - 1 : index;
}

6
packages/pegjs/lib/compiler/passes/remove-proxy-rules.js

@ -22,18 +22,18 @@ function removeProxyRules( ast, session, options ) {
const allowedStartRules = options.allowedStartRules;
const rules = [];
for ( const rule of ast.rules ) {
ast.rules.forEach( rule => {
if ( isProxyRule( rule ) ) {
replaceRuleRefs( ast, rule.name, rule.expression.name );
if ( allowedStartRules.indexOf( rule.name ) < 0 ) continue;
if ( allowedStartRules.indexOf( rule.name ) < 0 ) return;
}
rules.push( rule );
}
} );
ast.rules = rules;

6
packages/pegjs/lib/parser.js

@ -3414,11 +3414,11 @@ function peg$parse(input, options) {
// Populate `RESERVED_WORDS` using the optional option `reservedWords`
const reservedWords = options.reservedWords || util.reservedWords;
if ( Array.isArray( reservedWords ) ) {
if ( Array.isArray( reservedWords ) ) reservedWords.forEach( word => {
for ( const word of reservedWords ) RESERVED_WORDS[ word ] = true;
RESERVED_WORDS[ word ] = true;
}
} );
// Helper to construct a new AST Node
function createNode( type, details ) {

33
packages/pegjs/lib/util/arrays.js

@ -0,0 +1,33 @@
"use strict";
/**
* The `findIndex()` method returns the index of the first element in the array that satisfies the
* provided testing function, otherwise `-1` is returned.
*/
function findIndex( array, condition ) {
for ( let i = 0; i < array.length; ++i ) {
if ( condition( array[ i ], i ) ) return i;
}
return -1;
}
/**
* The `find()` method returns the value of the first element in the array that satisfies the
* provided testing function, otherwise `undefined` is returned.
*/
function find( array, condition ) {
const index = findIndex( array, condition );
return index < 0 ? void 0 : array[ index ];
}
// Exports
module.exports = { findIndex, find };

2
packages/pegjs/lib/util/index.js

@ -1,9 +1,11 @@
"use strict";
const arrays = require( "./arrays" );
const js = require( "./js" );
const objects = require( "./objects" );
const vm = require( "./vm" );
objects.extend( exports, arrays );
objects.extend( exports, js );
objects.extend( exports, objects );
objects.extend( exports, vm );

64
packages/pegjs/lib/util/vm.js

@ -1,58 +1,26 @@
"use strict";
const code = ( () => {
/**
* `eval` the given source, using properties found in `context` as top-level variables.
*
* Based on `vm.runInContext` found in Node.js, this is a cross-env solution.
*/
function runInContext( source, context ) {
let preface = "";
const MODULE_VARS = {
const argumentKeys = Object.keys( context );
const argumentValues = argumentKeys.map( argument => context[ argument ] );
"module": true,
"process": true,
"code": true,
"runInContext": true,
"source": true,
"preface": true,
const object = {};
argumentKeys.push( "_peg$object", `_peg$object.result = ${ source };` );
argumentValues.push( object );
};
Function( ...argumentKeys )( ...argumentValues );
Object.keys( MODULE_VARS ).forEach( name => {
return object.result;
preface += `var ${ name } = void 0;`;
} );
}
function generate( name ) {
// Exports
return `${ ( MODULE_VARS[ name ] ? "" : "var " ) + name } = __context.${ name };`;
}
return { generate, preface };
} )();
module.exports = {
// `eval` the given source, using properties found in `context` as top-level
// variables, while hiding some variables in this module from the source.
//
// Based on `vm.runInContext` found in Node.js, this is a cross-env solution.
runInContext( source, __context ) {
let preface = code.preface;
if ( typeof __context === "object" ) {
Object.keys( __context ).forEach( name => {
preface += code.generate( name );
} );
}
return eval( preface + source );
},
};
module.exports = { runInContext };

10
packages/pegjs/typings/api.d.ts

@ -435,7 +435,7 @@ declare namespace peg {
interface ISessionVM {
runInContext( code: string, vm$context?: { [ name: string ]: any; } ): any;
runInContext( code: string, context?: { [ name: string ]: any; } ): any;
}
@ -537,6 +537,12 @@ declare namespace peg {
}
interface IArrayUtils {
findIndex( array: any[], condition: IIterator ): number;
find( array: any[], condition: IIterator ): any;
}
interface IJavaScriptUtils {
stringEscape( s: string ): string;
@ -554,7 +560,7 @@ declare namespace peg {
enforceFastProperties( o: {} ): {};
}
interface util extends IJavaScriptUtils, IObjectUtils, compiler.ISessionVM {
interface util extends IArrayUtils, IJavaScriptUtils, IObjectUtils, compiler.ISessionVM {
noop(): void;
convertPasses( stages: IStageMap ): compiler.IPassesMap;

7
packages/pegjs/typings/modules.d.ts

@ -151,6 +151,13 @@ declare module "pegjs/lib/util" {
}
declare module "pegjs/lib/util/arrays" {
const arrays: peg.IArrayUtils;
export default arrays;
}
declare module "pegjs/lib/util/index" {
export default peg.util;

6
src/parser.pegjs

@ -31,11 +31,11 @@
// Populate `RESERVED_WORDS` using the optional option `reservedWords`
const reservedWords = options.reservedWords || util.reservedWords;
if ( Array.isArray( reservedWords ) ) {
if ( Array.isArray( reservedWords ) ) reservedWords.forEach( word => {
for ( const word of reservedWords ) RESERVED_WORDS[ word ] = true;
RESERVED_WORDS[ word ] = true;
}
} );
// Helper to construct a new AST Node
function createNode( type, details ) {

Loading…
Cancel
Save