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 2 years ago
parent
commit
616749377b
12 changed files with 89 additions and 78 deletions
  1. +6
    -6
      examples/arithmetics.pegjs
  2. +2
    -10
      packages/pegjs/lib/ast/Grammar.js
  3. +3
    -0
      packages/pegjs/lib/compiler/index.js
  4. +3
    -3
      packages/pegjs/lib/compiler/passes/generate-bytecode.js
  5. +3
    -3
      packages/pegjs/lib/compiler/passes/remove-proxy-rules.js
  6. +3
    -3
      packages/pegjs/lib/parser.js
  7. +33
    -0
      packages/pegjs/lib/util/arrays.js
  8. +2
    -0
      packages/pegjs/lib/util/index.js
  9. +16
    -48
      packages/pegjs/lib/util/vm.js
  10. +8
    -2
      packages/pegjs/typings/api.d.ts
  11. +7
    -0
      packages/pegjs/typings/modules.d.ts
  12. +3
    -3
      src/parser.pegjs

+ 6
- 6
examples/arithmetics.pegjs View File

@@ -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);
}



+ 2
- 10
packages/pegjs/lib/ast/Grammar.js View File

@@ -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
- 0
packages/pegjs/lib/compiler/index.js View File

@@ -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 => {


+ 3
- 3
packages/pegjs/lib/compiler/passes/generate-bytecode.js View File

@@ -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;

}


+ 3
- 3
packages/pegjs/lib/compiler/passes/remove-proxy-rules.js View File

@@ -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;



+ 3
- 3
packages/pegjs/lib/parser.js View File

@@ -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
- 0
packages/pegjs/lib/util/arrays.js View File

@@ -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
- 0
packages/pegjs/lib/util/index.js View File

@@ -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 );


+ 16
- 48
packages/pegjs/lib/util/vm.js View File

@@ -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 };

+ 8
- 2
packages/pegjs/typings/api.d.ts View File

@@ -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
- 0
packages/pegjs/typings/modules.d.ts View File

@@ -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;


+ 3
- 3
src/parser.pegjs View File

@@ -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