Comparing version 0.11.0-dev.200 to 0.11.0-dev.224
"use strict"; | ||
const calcReportFailures = require( "./passes/calc-report-failures" ); | ||
const generateBytecode = require( "./passes/generate-bytecode" ); | ||
@@ -11,3 +12,5 @@ const generateJS = require( "./passes/generate-js" ); | ||
const reportUndefinedRules = require( "./passes/report-undefined-rules" ); | ||
const inferenceMatchResult = require( "./passes/inference-match-result" ); | ||
const visitor = require( "./visitor" ); | ||
const util = require( "../util" ); | ||
@@ -18,18 +21,5 @@ function processOptions( options, defaults ) { | ||
Object.keys( options ).forEach( name => { | ||
util.extend( processedOptions, options ); | ||
util.extend( processedOptions, defaults ); | ||
processedOptions[ name ] = options[ name ]; | ||
} ); | ||
Object.keys( defaults ).forEach( name => { | ||
if ( ! Object.prototype.hasOwnProperty.call( processedOptions, name ) ) { | ||
processedOptions[ name ] = defaults[ name ]; | ||
} | ||
} ); | ||
return processedOptions; | ||
@@ -61,2 +51,4 @@ | ||
generate: { | ||
calcReportFailures: calcReportFailures, | ||
inferenceMatchResult: inferenceMatchResult, | ||
generateBytecode: generateBytecode, | ||
@@ -86,5 +78,5 @@ generateJS: generateJS | ||
Object.keys( passes ).forEach( stage => { | ||
util.each( passes, stage => { | ||
passes[ stage ].forEach( pass => { | ||
stage.forEach( pass => { | ||
@@ -91,0 +83,0 @@ pass( ast, options ); |
@@ -8,50 +8,53 @@ "use strict"; | ||
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 | ||
PUSH_EMPTY_STRING: 0, // PUSH_EMPTY_STRING | ||
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 | ||
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 | ||
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_CLASS: 20, // MATCH_CLASS c, a, f, ... | ||
ACCEPT_N: 21, // ACCEPT_N n | ||
ACCEPT_STRING: 22, // ACCEPT_STRING s | ||
EXPECT: 23, // EXPECT 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 | ||
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 | ||
RULE: 27, // RULE r | ||
// Failure Reporting | ||
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON | ||
SILENT_FAILS_OFF: 29 // SILENT_FAILS_OFF | ||
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON | ||
SILENT_FAILS_OFF: 29, // SILENT_FAILS_OFF | ||
EXPECT_NS_BEGIN: 38, // EXPECT_NS_BEGIN | ||
EXPECT_NS_END: 39 // EXPECT_NS_END invert | ||
}; | ||
module.exports = opcodes; |
"use strict"; | ||
const asts = require( "../asts" ); | ||
const js = require( "../js" ); | ||
const op = require( "../opcodes" ); | ||
const visitor = require( "../visitor" ); | ||
const util = require( "../../util" ); | ||
@@ -16,5 +16,5 @@ // Generates bytecode. | ||
// | ||
// [0] PUSH c | ||
// [0] PUSH_EMPTY_STRING | ||
// | ||
// stack.push(consts[c]); | ||
// stack.push(""); | ||
// | ||
@@ -120,3 +120,3 @@ // [1] PUSH_UNDEFINED | ||
// | ||
// if (input.substr(currPos, consts[s].length) === consts[s]) { | ||
// if (input.substr(currPos, literals[s].length) === literals[s]) { | ||
// interpret(ip + 4, ip + 4 + a); | ||
@@ -129,3 +129,3 @@ // } else { | ||
// | ||
// if (input.substr(currPos, consts[s].length).toLowerCase() === consts[s]) { | ||
// if (input.substr(currPos, literals[s].length).toLowerCase() === literals[s]) { | ||
// interpret(ip + 4, ip + 4 + a); | ||
@@ -136,5 +136,5 @@ // } else { | ||
// | ||
// [20] MATCH_REGEXP r, a, f, ... | ||
// [20] MATCH_CLASS c, a, f, ... | ||
// | ||
// if (consts[r].test(input.charAt(currPos))) { | ||
// if (classes[c].test(input.charAt(currPos))) { | ||
// interpret(ip + 4, ip + 4 + a); | ||
@@ -152,9 +152,8 @@ // } else { | ||
// | ||
// stack.push(consts[s]); | ||
// currPos += consts[s].length; | ||
// stack.push(literals[s]); | ||
// currPos += literals[s].length; | ||
// | ||
// [23] FAIL e | ||
// [23] EXPECT e | ||
// | ||
// stack.push(FAILED); | ||
// fail(consts[e]); | ||
// expect(expectations[e]); | ||
// | ||
@@ -174,3 +173,3 @@ // Calls | ||
// | ||
// value = consts[f](stack[p1], ..., stack[pN]); | ||
// value = functions[f](stack[p1], ..., stack[pN]); | ||
// stack.pop(n); | ||
@@ -196,32 +195,59 @@ // stack.push(value); | ||
// silentFails--; | ||
// | ||
// [38] EXPECT_NS_BEGIN | ||
// | ||
// expected.push({ pos: curPos, variants: [] }); | ||
// | ||
// [39] EXPECT_NS_END invert | ||
// | ||
// value = expected.pop(); | ||
// if (value.pos === expected.top().pos) { | ||
// if (invert) { | ||
// value.variants.forEach(e => { e.not = !e.not; }); | ||
// } | ||
// expected.top().variants.pushAll(value.variants); | ||
// } | ||
function generateBytecode( ast ) { | ||
const consts = []; | ||
const literals = []; | ||
const classes = []; | ||
const expectations = []; | ||
const functions = []; | ||
let generate; | ||
function addConst( value ) { | ||
function addLiteralConst( value ) { | ||
const index = consts.indexOf( value ); | ||
return index === -1 ? consts.push( value ) - 1 : index; | ||
const index = literals.indexOf( value ); | ||
return index === -1 ? literals.push( value ) - 1 : index; | ||
} | ||
function addFunctionConst( params, code ) { | ||
function addClassConst( node ) { | ||
return addConst( `function(${ params.join( ", " ) }) {${ code }}` ); | ||
const cls = { | ||
value: node.parts, | ||
inverted: node.inverted, | ||
ignoreCase: node.ignoreCase | ||
}; | ||
const pattern = JSON.stringify( cls ); | ||
const index = classes.findIndex( c => JSON.stringify( c ) === pattern ); | ||
return index === -1 ? classes.push( cls ) - 1 : index; | ||
} | ||
function cloneEnv( env ) { | ||
function addExpectedConst( expected ) { | ||
const clone = {}; | ||
const pattern = JSON.stringify( expected ); | ||
const index = expectations.findIndex( e => JSON.stringify( e ) === pattern ); | ||
return index === -1 ? expectations.push( expected ) - 1 : index; | ||
Object.keys( env ).forEach( name => { | ||
} | ||
clone[ name ] = env[ name ]; | ||
function addFunctionConst( predicate, params, code ) { | ||
} ); | ||
const func = { predicate: predicate, params: params, body: code }; | ||
const pattern = JSON.stringify( func ); | ||
const index = functions.findIndex( f => JSON.stringify( f ) === pattern ); | ||
return index === -1 ? functions.push( func ) - 1 : index; | ||
return clone; | ||
} | ||
@@ -235,4 +261,7 @@ | ||
function buildCondition( condCode, thenCode, elseCode ) { | ||
function buildCondition( match, condCode, thenCode, elseCode ) { | ||
if ( match > 0 ) return thenCode; | ||
if ( match < 0 ) return elseCode; | ||
return condCode.concat( | ||
@@ -254,3 +283,3 @@ [ thenCode.length, elseCode.length ], | ||
const params = Object.keys( env ).map( name => sp - env[ name ] ); | ||
const params = util.values( env, value => sp - value ); | ||
return [ op.CALL, functionIndex, delta, params.length ].concat( params ); | ||
@@ -262,12 +291,15 @@ | ||
const match = expression.match|0; | ||
return buildSequence( | ||
[ op.PUSH_CURR_POS ], | ||
[ op.SILENT_FAILS_ON ], | ||
[ op.EXPECT_NS_BEGIN ], | ||
generate( expression, { | ||
sp: context.sp + 1, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ), | ||
[ op.SILENT_FAILS_OFF ], | ||
[ op.EXPECT_NS_END, negative ? 1 : 0 ], | ||
buildCondition( | ||
negative ? -match : match, | ||
[ negative ? op.IF_ERROR : op.IF_NOT_ERROR ], | ||
@@ -289,5 +321,5 @@ buildSequence( | ||
function buildSemanticPredicate( code, negative, context ) { | ||
function buildSemanticPredicate( node, negative, context ) { | ||
const functionIndex = addFunctionConst( Object.keys( context.env ), code ); | ||
const functionIndex = addFunctionConst( true, Object.keys( context.env ), node.code ); | ||
@@ -298,2 +330,3 @@ return buildSequence( | ||
buildCondition( | ||
node.match|0, | ||
[ op.IF ], | ||
@@ -320,3 +353,6 @@ buildSequence( [ op.POP ], negative ? [ op.PUSH_FAILED ] : [ op.PUSH_UNDEFINED ] ), | ||
node.rules.forEach( generate ); | ||
node.consts = consts; | ||
node.literals = literals; | ||
node.classes = classes; | ||
node.expectations = expectations; | ||
node.functions = functions; | ||
@@ -328,5 +364,6 @@ }, | ||
node.bytecode = generate( node.expression, { | ||
sp: -1, // stack pointer | ||
env: { }, // mapping of label names to stack positions | ||
action: null // action nodes pass themselves to children here | ||
sp: -1, // stack pointer | ||
env: { }, // mapping of label names to stack positions | ||
action: null, // action nodes pass themselves to children here | ||
reportFailures: node.reportFailures // if `false`, suppress generation of EXPECT opcodes | ||
} ); | ||
@@ -338,16 +375,20 @@ | ||
const nameIndex = addConst( | ||
`peg$otherExpectation("${ js.stringEscape( node.name ) }")` | ||
); | ||
// Do not generate unused constant, if no need it | ||
const nameIndex = context.reportFailures ? addExpectedConst( | ||
{ type: "rule", value: node.name } | ||
) : null; | ||
const expressionCode = generate( node.expression, { | ||
sp: context.sp, | ||
env: context.env, | ||
action: context.action, | ||
reportFailures: false | ||
} ); | ||
// The code generated below is slightly suboptimal because |FAIL| pushes | ||
// to the stack, so we need to stick a |POP| in front of it. We lack a | ||
// dedicated instruction that would just report the failure and not touch | ||
// the stack. | ||
return buildSequence( | ||
// No need to disable report failures if it already disabled | ||
return context.reportFailures ? buildSequence( | ||
[ op.EXPECT, nameIndex ], | ||
[ op.SILENT_FAILS_ON ], | ||
generate( node.expression, context ), | ||
[ op.SILENT_FAILS_OFF ], | ||
buildCondition( [ op.IF_ERROR ], [ op.FAIL, nameIndex ], [] ) | ||
); | ||
expressionCode, | ||
[ op.SILENT_FAILS_OFF ] | ||
) : expressionCode; | ||
@@ -363,4 +404,5 @@ }, | ||
sp: context.sp, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ), | ||
@@ -370,2 +412,4 @@ alternatives.length < 2 | ||
: buildCondition( | ||
// If alternative always match no need generate code for next alternatives | ||
-( alternatives[ 0 ].match|0 ), | ||
[ op.IF_ERROR ], | ||
@@ -388,3 +432,3 @@ buildSequence( | ||
const env = cloneEnv( context.env ); | ||
const env = util.clone( context.env ); | ||
const emitCall = node.expression.type !== "sequence" || node.expression.elements.length === 0; | ||
@@ -394,5 +438,9 @@ const expressionCode = generate( node.expression, { | ||
env: env, | ||
action: node | ||
action: node, | ||
reportFailures: context.reportFailures | ||
} ); | ||
const functionIndex = addFunctionConst( Object.keys( env ), node.code ); | ||
const match = node.expression.match|0; | ||
const functionIndex = emitCall && match >= 0 | ||
? addFunctionConst( false, Object.keys( env ), node.code ) | ||
: null; | ||
@@ -405,2 +453,3 @@ return emitCall === false | ||
buildCondition( | ||
match, | ||
[ op.IF_NOT_ERROR ], | ||
@@ -430,5 +479,7 @@ buildSequence( | ||
env: context.env, | ||
action: null | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ), | ||
buildCondition( | ||
elements[ 0 ].match|0, | ||
[ op.IF_NOT_ERROR ], | ||
@@ -438,3 +489,4 @@ buildElementsCode( elements.slice( 1 ), { | ||
env: context.env, | ||
action: context.action | ||
action: context.action, | ||
reportFailures: context.reportFailures | ||
} ), | ||
@@ -452,2 +504,3 @@ buildSequence( | ||
const functionIndex = addFunctionConst( | ||
false, | ||
Object.keys( context.env ), | ||
@@ -477,3 +530,4 @@ context.action.code | ||
env: context.env, | ||
action: context.action | ||
action: context.action, | ||
reportFailures: context.reportFailures | ||
} ) | ||
@@ -486,3 +540,3 @@ ); | ||
const env = cloneEnv( context.env ); | ||
const env = util.clone( context.env ); | ||
@@ -494,3 +548,4 @@ context.env[ node.label ] = context.sp + 1; | ||
env: env, | ||
action: null | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ); | ||
@@ -506,6 +561,8 @@ | ||
sp: context.sp + 1, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ), | ||
buildCondition( | ||
node.expression.match|0, | ||
[ op.IF_NOT_ERROR ], | ||
@@ -536,6 +593,9 @@ buildSequence( [ op.POP ], [ op.TEXT ] ), | ||
sp: context.sp, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ), | ||
buildCondition( | ||
// If expression always match no need replace FAILED to NULL | ||
-( node.expression.match|0 ), | ||
[ op.IF_ERROR ], | ||
@@ -553,4 +613,5 @@ buildSequence( [ op.POP ], [ op.PUSH_NULL ] ), | ||
sp: context.sp + 1, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ); | ||
@@ -571,4 +632,5 @@ | ||
sp: context.sp + 1, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ); | ||
@@ -580,2 +642,3 @@ | ||
buildCondition( | ||
node.expression.match|0, | ||
[ op.IF_NOT_ERROR ], | ||
@@ -593,4 +656,5 @@ buildSequence( buildAppendLoop( expressionCode ), [ op.POP ] ), | ||
sp: context.sp, | ||
env: cloneEnv( context.env ), | ||
action: null | ||
env: util.clone( context.env ), | ||
action: null, | ||
reportFailures: context.reportFailures | ||
} ); | ||
@@ -602,3 +666,3 @@ | ||
return buildSemanticPredicate( node.code, false, context ); | ||
return buildSemanticPredicate( node, false, context ); | ||
@@ -609,3 +673,3 @@ }, | ||
return buildSemanticPredicate( node.code, true, context ); | ||
return buildSemanticPredicate( node, true, context ); | ||
@@ -620,15 +684,17 @@ }, | ||
literal( node ) { | ||
literal( node, context ) { | ||
if ( node.value.length > 0 ) { | ||
const stringIndex = addConst( `"${ js.stringEscape( | ||
const match = node.match|0; | ||
const needConst = match === 0 || ( match > 0 && ! node.ignoreCase ); | ||
const stringIndex = needConst ? addLiteralConst( | ||
node.ignoreCase ? node.value.toLowerCase() : node.value | ||
) }"` ); | ||
const expectedIndex = addConst( | ||
"peg$literalExpectation(" | ||
+ `"${ js.stringEscape( node.value ) }", ` | ||
+ node.ignoreCase | ||
+ ")" | ||
); | ||
) : null; | ||
// Do not generate unused constant, if no need it | ||
const expectedIndex = context.reportFailures ? addExpectedConst( { | ||
type: "literal", | ||
value: node.value, | ||
ignoreCase: node.ignoreCase | ||
} ) : null; | ||
@@ -638,10 +704,14 @@ // For case-sensitive strings the value must match the beginning of the | ||
// save one |substr| call that would be needed if we used |ACCEPT_N|. | ||
return buildCondition( | ||
node.ignoreCase | ||
? [ op.MATCH_STRING_IC, stringIndex ] | ||
: [ op.MATCH_STRING, stringIndex ], | ||
node.ignoreCase | ||
? [ op.ACCEPT_N, node.value.length ] | ||
: [ op.ACCEPT_STRING, stringIndex ], | ||
[ op.FAIL, expectedIndex ] | ||
return buildSequence( | ||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [], | ||
buildCondition( | ||
match, | ||
node.ignoreCase | ||
? [ op.MATCH_STRING_IC, stringIndex ] | ||
: [ op.MATCH_STRING, stringIndex ], | ||
node.ignoreCase | ||
? [ op.ACCEPT_N, node.value.length ] | ||
: [ op.ACCEPT_STRING, stringIndex ], | ||
[ op.PUSH_FAILED ] | ||
) | ||
); | ||
@@ -651,58 +721,45 @@ | ||
const stringIndex = addConst( "\"\"" ); | ||
return [ op.PUSH, stringIndex ]; | ||
return [ op.PUSH_EMPTY_STRING ]; | ||
}, | ||
class( node ) { | ||
class( node, context ) { | ||
const regexp = "/^[" | ||
+ ( node.inverted ? "^" : "" ) | ||
+ node.parts | ||
.map( part => | ||
( Array.isArray( part ) | ||
? js.regexpClassEscape( part[ 0 ] ) | ||
+ "-" | ||
+ js.regexpClassEscape( part[ 1 ] ) | ||
: js.regexpClassEscape( part ) ) | ||
) | ||
.join( "" ) | ||
+ "]/" | ||
+ ( node.ignoreCase ? "i" : "" ); | ||
const match = node.match|0; | ||
const classIndex = match === 0 ? addClassConst( node ) : null; | ||
// Do not generate unused constant, if no need it | ||
const expectedIndex = context.reportFailures ? addExpectedConst( { | ||
type: "class", | ||
value: node.parts, | ||
inverted: node.inverted, | ||
ignoreCase: node.ignoreCase | ||
} ) : null; | ||
const parts = "[" | ||
+ node.parts | ||
.map( part => | ||
( Array.isArray( part ) | ||
? `["${ js.stringEscape( part[ 0 ] ) }", "${ js.stringEscape( part[ 1 ] ) }"]` | ||
: "\"" + js.stringEscape( part ) + "\"" ) | ||
) | ||
.join( ", " ) | ||
+ "]"; | ||
const regexpIndex = addConst( regexp ); | ||
const expectedIndex = addConst( | ||
"peg$classExpectation(" | ||
+ parts + ", " | ||
+ node.inverted + ", " | ||
+ node.ignoreCase | ||
+ ")" | ||
return buildSequence( | ||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [], | ||
buildCondition( | ||
match, | ||
[ op.MATCH_CLASS, classIndex ], | ||
[ op.ACCEPT_N, 1 ], | ||
[ op.PUSH_FAILED ] | ||
) | ||
); | ||
return buildCondition( | ||
[ op.MATCH_REGEXP, regexpIndex ], | ||
[ op.ACCEPT_N, 1 ], | ||
[ op.FAIL, expectedIndex ] | ||
); | ||
}, | ||
any() { | ||
any( node, context ) { | ||
const expectedIndex = addConst( "peg$anyExpectation()" ); | ||
// Do not generate unused constant, if no need it | ||
const expectedIndex = context.reportFailures | ||
? addExpectedConst( { type: "any" } ) | ||
: null; | ||
return buildCondition( | ||
[ op.MATCH_ANY ], | ||
[ op.ACCEPT_N, 1 ], | ||
[ op.FAIL, expectedIndex ] | ||
return buildSequence( | ||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [], | ||
buildCondition( | ||
node.match|0, | ||
[ op.MATCH_ANY ], | ||
[ op.ACCEPT_N, 1 ], | ||
[ op.PUSH_FAILED ] | ||
) | ||
); | ||
@@ -709,0 +766,0 @@ |
@@ -25,10 +25,89 @@ /* eslint no-mixed-operators: 0, prefer-const: 0 */ | ||
const l = i => "peg$c" + i; // |literals[i]| of the abstract machine | ||
const r = i => "peg$r" + i; // |classes[i]| of the abstract machine | ||
const e = i => "peg$e" + i; // |expectations[i]| of the abstract machine | ||
const f = i => "peg$f" + i; // |actions[i]| of the abstract machine | ||
function generateTables() { | ||
function buildLiteral( literal ) { | ||
return `"${ js.stringEscape( literal ) }"`; | ||
} | ||
function buildRegexp( cls ) { | ||
return "/^[" | ||
+ ( cls.inverted ? "^" : "" ) | ||
+ cls.value | ||
.map( part => | ||
( Array.isArray( part ) | ||
? js.regexpClassEscape( part[ 0 ] ) | ||
+ "-" | ||
+ js.regexpClassEscape( part[ 1 ] ) | ||
: js.regexpClassEscape( part ) ) | ||
) | ||
.join( "" ) | ||
+ "]/" | ||
+ ( cls.ignoreCase ? "i" : "" ); | ||
} | ||
function buildExpectation( e ) { | ||
switch ( e.type ) { | ||
case "rule": | ||
return `peg$otherExpectation("${ js.stringEscape( e.value ) }")`; | ||
case "literal": | ||
return "peg$literalExpectation(\"" | ||
+ js.stringEscape( e.value ) | ||
+ "\", " | ||
+ e.ignoreCase | ||
+ ")"; | ||
case "class": { | ||
const parts = e.value.map( part => | ||
( Array.isArray( part ) | ||
? `["${ js.stringEscape( part[ 0 ] ) }", "${ js.stringEscape( part[ 1 ] ) }"]` | ||
: `"${ js.stringEscape( part ) }"` ) | ||
); | ||
return "peg$classExpectation([" | ||
+ parts.join( ", " ) + "], " | ||
+ e.inverted + ", " | ||
+ e.ignoreCase | ||
+ ")"; | ||
} | ||
case "any": return "peg$anyExpectation()"; | ||
// istanbul ignore next | ||
default: throw new Error( `Unknown expectation type (${ JSON.stringify( e ) })` ); | ||
} | ||
} | ||
function buildFunc( f ) { | ||
return `function(${ f.params.join( ", " ) }) {${ f.body }}`; | ||
} | ||
if ( options.optimize === "size" ) { | ||
return [ | ||
"var peg$consts = [", | ||
indent2( ast.consts.join( ",\n" ) ), | ||
"var peg$literals = [", | ||
indent2( ast.literals.map( buildLiteral ).join( ",\n" ) ), | ||
"];", | ||
"var peg$regexps = [", | ||
indent2( ast.classes.map( buildRegexp ).join( ",\n" ) ), | ||
"];", | ||
"var peg$expectations = [", | ||
indent2( ast.expectations.map( buildExpectation ).join( ",\n" ) ), | ||
"];", | ||
"var peg$functions = [", | ||
indent2( ast.functions.map( buildFunc ).join( ",\n" ) ), | ||
"];", | ||
"", | ||
@@ -52,3 +131,14 @@ "var peg$bytecode = [", | ||
return ast.consts.map( ( c, i ) => "var peg$c" + i + " = " + c + ";" ).join( "\n" ); | ||
return ast.literals | ||
.map( ( c, i ) => "var " + l( i ) + " = " + buildLiteral( c ) + ";" ) | ||
.concat( "", ast.classes.map( | ||
( c, i ) => "var " + r( i ) + " = " + buildRegexp( c ) + ";" | ||
) ) | ||
.concat( "", ast.expectations.map( | ||
( c, i ) => "var " + e( i ) + " = " + buildExpectation( c ) + ";" | ||
) ) | ||
.concat( "", ast.functions.map( | ||
( c, i ) => "var " + f( i ) + " = " + buildFunc( c ) + ";" | ||
) ) | ||
.join( "\n" ); | ||
@@ -61,3 +151,7 @@ } | ||
parts.push( "" ); | ||
parts.push( [ | ||
"", | ||
"var rule$expects = peg$expect;", | ||
"" | ||
].join( "\n" ) ); | ||
@@ -82,5 +176,16 @@ if ( options.trace ) { | ||
"var cached = peg$resultsCache[key];", | ||
"var rule$expectations = [];", | ||
"", | ||
"rule$expects = function (expected) {", | ||
" if (peg$silentFails === 0) peg$expect(expected);", | ||
" rule$expectations.push(expected);", | ||
"}", | ||
"", | ||
"if (cached) {", | ||
" peg$currPos = cached.nextPos;", | ||
"", | ||
" rule$expectations = cached.expectations;", | ||
" if (peg$silentFails === 0) {", | ||
" rule$expectations.forEach(peg$expect);", | ||
" }", | ||
"" | ||
@@ -131,3 +236,7 @@ ].join( "\n" ) ); | ||
"", | ||
"peg$resultsCache[key] = { nextPos: peg$currPos, result: " + resultCode + " };" | ||
"peg$resultsCache[key] = {", | ||
" nextPos: peg$currPos,", | ||
" result: " + resultCode + ",", | ||
" expectations: rule$expectations", | ||
"};" | ||
].join( "\n" ) ); | ||
@@ -228,3 +337,3 @@ | ||
" bc[ip + 2],", | ||
" peg$consts[bc[ip + 1]].apply(null, params)", | ||
" peg$functions[bc[ip + 1]].apply(null, params)", | ||
");", | ||
@@ -284,5 +393,5 @@ "", | ||
" switch (bc[ip]) {", | ||
" case " + op.PUSH + ":", // PUSH c | ||
" stack.push(peg$consts[bc[ip + 1]]);", | ||
" ip += 2;", | ||
" case " + op.PUSH_EMPTY_STRING + ":", // PUSH_EMPTY_STRING | ||
" stack.push('');", | ||
" ip++;", | ||
" break;", | ||
@@ -373,3 +482,3 @@ "", | ||
indent10( generateCondition( | ||
"input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]", | ||
"input.substr(peg$currPos, peg$literals[bc[ip + 1]].length) === peg$literals[bc[ip + 1]]", | ||
1 | ||
@@ -380,9 +489,9 @@ ) ), | ||
indent10( generateCondition( | ||
"input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]", | ||
"input.substr(peg$currPos, peg$literals[bc[ip + 1]].length).toLowerCase() === peg$literals[bc[ip + 1]]", | ||
1 | ||
) ), | ||
"", | ||
" case " + op.MATCH_REGEXP + ":", // MATCH_REGEXP r, a, f, ... | ||
" case " + op.MATCH_CLASS + ":", // MATCH_CLASS c, a, f, ... | ||
indent10( generateCondition( | ||
"peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))", | ||
"peg$regexps[bc[ip + 1]].test(input.charAt(peg$currPos))", | ||
1 | ||
@@ -398,12 +507,9 @@ ) ), | ||
" case " + op.ACCEPT_STRING + ":", // ACCEPT_STRING s | ||
" stack.push(peg$consts[bc[ip + 1]]);", | ||
" peg$currPos += peg$consts[bc[ip + 1]].length;", | ||
" stack.push(peg$literals[bc[ip + 1]]);", | ||
" peg$currPos += peg$literals[bc[ip + 1]].length;", | ||
" ip += 2;", | ||
" break;", | ||
"", | ||
" case " + op.FAIL + ":", // FAIL e | ||
" stack.push(peg$FAILED);", | ||
" if (peg$silentFails === 0) {", | ||
" peg$fail(peg$consts[bc[ip + 1]]);", | ||
" }", | ||
" case " + op.EXPECT + ":", // EXPECT e | ||
" rule$expects(peg$expectations[bc[ip + 1]]);", | ||
" ip += 2;", | ||
@@ -440,2 +546,12 @@ " break;", | ||
"", | ||
" case " + op.EXPECT_NS_BEGIN + ":", // EXPECT_NS_BEGIN | ||
" peg$begin();", | ||
" ip++;", | ||
" break;", | ||
"", | ||
" case " + op.EXPECT_NS_END + ":", // EXPECT_NS_END invert | ||
" peg$end(bc[ip + 1]);", | ||
" ip += 2;", | ||
" break;", | ||
"", | ||
" // istanbul ignore next", | ||
@@ -468,7 +584,2 @@ " default:", | ||
function c( i ) { | ||
return "peg$c" + i; | ||
} // |consts[i]| of the abstract machine | ||
function s( i ) { | ||
@@ -602,3 +713,3 @@ | ||
const value = c( bc[ ip + 1 ] ) | ||
const value = f( bc[ ip + 1 ] ) | ||
+ "(" | ||
@@ -621,5 +732,5 @@ + bc | ||
case op.PUSH: // PUSH c | ||
parts.push( stack.push( c( bc[ ip + 1 ] ) ) ); | ||
ip += 2; | ||
case op.PUSH_EMPTY_STRING: // PUSH_EMPTY_STRING | ||
parts.push( stack.push( "''" ) ); | ||
ip++; | ||
break; | ||
@@ -632,3 +743,3 @@ | ||
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED | ||
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED | ||
parts.push( stack.push( "undefined" ) ); | ||
@@ -717,9 +828,9 @@ ip++; | ||
compileCondition( | ||
eval( ast.consts[ bc[ ip + 1 ] ] ).length > 1 | ||
ast.literals[ bc[ ip + 1 ] ].length > 1 | ||
? "input.substr(peg$currPos, " | ||
+ eval( ast.consts[ bc[ ip + 1 ] ] ).length | ||
+ ast.literals[ bc[ ip + 1 ] ].length | ||
+ ") === " | ||
+ c( bc[ ip + 1 ] ) | ||
+ l( bc[ ip + 1 ] ) | ||
: "input.charCodeAt(peg$currPos) === " | ||
+ eval( ast.consts[ bc[ ip + 1 ] ] ).charCodeAt( 0 ) | ||
+ ast.literals[ bc[ ip + 1 ] ].charCodeAt( 0 ) | ||
, 1 | ||
@@ -732,5 +843,5 @@ ); | ||
"input.substr(peg$currPos, " | ||
+ eval( ast.consts[ bc[ ip + 1 ] ] ).length | ||
+ ast.literals[ bc[ ip + 1 ] ].length | ||
+ ").toLowerCase() === " | ||
+ c( bc[ ip + 1 ] ) | ||
+ l( bc[ ip + 1 ] ) | ||
, 1 | ||
@@ -740,4 +851,4 @@ ); | ||
case op.MATCH_REGEXP: // MATCH_REGEXP r, a, f, ... | ||
compileCondition( c( bc[ ip + 1 ] ) + ".test(input.charAt(peg$currPos))", 1 ); | ||
case op.MATCH_CLASS: // MATCH_CLASS c, a, f, ... | ||
compileCondition( r( bc[ ip + 1 ] ) + ".test(input.charAt(peg$currPos))", 1 ); | ||
break; | ||
@@ -760,6 +871,6 @@ | ||
case op.ACCEPT_STRING: // ACCEPT_STRING s | ||
parts.push( stack.push( c( bc[ ip + 1 ] ) ) ); | ||
parts.push( stack.push( l( bc[ ip + 1 ] ) ) ); | ||
parts.push( | ||
eval( ast.consts[ bc[ ip + 1 ] ] ).length > 1 | ||
? "peg$currPos += " + eval( ast.consts[ bc[ ip + 1 ] ] ).length + ";" | ||
ast.literals[ bc[ ip + 1 ] ].length > 1 | ||
? "peg$currPos += " + ast.literals[ bc[ ip + 1 ] ].length + ";" | ||
: "peg$currPos++;" | ||
@@ -770,5 +881,4 @@ ); | ||
case op.FAIL: // FAIL e | ||
parts.push( stack.push( "peg$FAILED" ) ); | ||
parts.push( "if (peg$silentFails === 0) { peg$fail(" + c( bc[ ip + 1 ] ) + "); }" ); | ||
case op.EXPECT: // EXPECT e | ||
parts.push( "rule$expects(" + e( bc[ ip + 1 ] ) + ");" ); | ||
ip += 2; | ||
@@ -806,2 +916,12 @@ break; | ||
case op.EXPECT_NS_BEGIN: // EXPECT_NS_BEGIN | ||
parts.push( "peg$begin();" ); | ||
ip++; | ||
break; | ||
case op.EXPECT_NS_END: // EXPECT_NS_END invert | ||
parts.push( "peg$end(" + ( bc[ ip + 1 ] !== 0 ) + ");" ); | ||
ip += 2; | ||
break; | ||
// istanbul ignore next | ||
@@ -905,2 +1025,6 @@ default: | ||
" return expectation.description;", | ||
" },", | ||
"", | ||
" not: function(expectation) {", | ||
" return \"not \" + describeExpectation(expectation.expected);", | ||
" }", | ||
@@ -1090,4 +1214,3 @@ " };", | ||
" var peg$posDetailsCache = [{ line: 1, column: 1 }];", | ||
" var peg$maxFailPos = 0;", | ||
" var peg$maxFailExpected = [];", | ||
" var peg$expected = [];", | ||
" var peg$silentFails = 0;", // 0 = report failures, > 0 = silence failures | ||
@@ -1272,13 +1395,35 @@ "" | ||
"", | ||
" function peg$fail(expected) {", | ||
" if (peg$currPos < peg$maxFailPos) { return; }", | ||
" function peg$begin() {", | ||
" peg$expected.push({ pos: peg$currPos, variants: [] });", | ||
" }", | ||
"", | ||
" if (peg$currPos > peg$maxFailPos) {", | ||
" peg$maxFailPos = peg$currPos;", | ||
" peg$maxFailExpected = [];", | ||
" function peg$expect(expected) {", | ||
" var top = peg$expected[peg$expected.length - 1];", | ||
"", | ||
" if (peg$currPos < top.pos) { return; }", | ||
"", | ||
" if (peg$currPos > top.pos) {", | ||
" top.pos = peg$currPos;", | ||
" top.variants = [];", | ||
" }", | ||
"", | ||
" peg$maxFailExpected.push(expected);", | ||
" top.variants.push(expected);", | ||
" }", | ||
"", | ||
" function peg$end(invert) {", | ||
" var expected = peg$expected.pop();", | ||
" var top = peg$expected[peg$expected.length - 1];", | ||
" var variants = expected.variants;", | ||
"", | ||
" if (top.pos !== expected.pos) { return; }", | ||
"", | ||
" if (invert) {", | ||
" variants = variants.map(function(e) {", | ||
" return e.type === \"not\" ? e.expected : { type: \"not\", expected: e };", | ||
" });", | ||
" }", | ||
"", | ||
" Array.prototype.push.apply(top.variants, variants);", | ||
" }", | ||
"", | ||
" function peg$buildSimpleError(message, location) {", | ||
@@ -1296,2 +1441,15 @@ " return new peg$SyntaxError(message, null, null, location);", | ||
" }", | ||
"", | ||
" function peg$buildError() {", | ||
" var expected = peg$expected[0];", | ||
" var failPos = expected.pos;", | ||
"", | ||
" return peg$buildStructuredError(", | ||
" expected.variants,", | ||
" failPos < input.length ? input.charAt(failPos) : null,", | ||
" failPos < input.length", | ||
" ? peg$computeLocation(failPos, failPos + 1)", | ||
" : peg$computeLocation(failPos, failPos)", | ||
" );", | ||
" }", | ||
"" | ||
@@ -1323,2 +1481,4 @@ ].join( "\n" ) ); | ||
parts.push( " peg$begin();" ); | ||
if ( options.optimize === "size" ) { | ||
@@ -1340,12 +1500,6 @@ | ||
" if (peg$result !== peg$FAILED && peg$currPos < input.length) {", | ||
" peg$fail(peg$endExpectation());", | ||
" peg$expect(peg$endExpectation());", | ||
" }", | ||
"", | ||
" throw peg$buildStructuredError(", | ||
" peg$maxFailExpected,", | ||
" peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,", | ||
" peg$maxFailPos < input.length", | ||
" ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)", | ||
" : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)", | ||
" );", | ||
" throw peg$buildError();", | ||
" }", | ||
@@ -1352,0 +1506,0 @@ "}" |
@@ -5,2 +5,4 @@ "use strict"; | ||
const visitor = require( "../visitor" ); | ||
const util = require( "../../util" ); | ||
const __hasOwnProperty = Object.prototype.hasOwnProperty; | ||
@@ -12,19 +14,5 @@ // Checks that each label is defined only once within each scope. | ||
function cloneEnv( env ) { | ||
const clone = {}; | ||
Object.keys( env ).forEach( name => { | ||
clone[ name ] = env[ name ]; | ||
} ); | ||
return clone; | ||
} | ||
function checkExpressionWithClonedEnv( node, env ) { | ||
check( node.expression, cloneEnv( env ) ); | ||
check( node.expression, util.clone( env ) ); | ||
@@ -44,3 +32,3 @@ } | ||
check( alternative, cloneEnv( env ) ); | ||
check( alternative, util.clone( env ) ); | ||
@@ -57,3 +45,3 @@ } ); | ||
if ( Object.prototype.hasOwnProperty.call( env, label ) ) { | ||
if ( __hasOwnProperty.call( env, label ) ) { | ||
@@ -60,0 +48,0 @@ const start = env[ label ].start; |
@@ -5,2 +5,3 @@ "use strict"; | ||
const visitor = require( "../visitor" ); | ||
const __hasOwnProperty = Object.prototype.hasOwnProperty; | ||
@@ -17,3 +18,3 @@ // Checks that each rule is defined only once. | ||
if ( Object.prototype.hasOwnProperty.call( rules, name ) ) { | ||
if ( __hasOwnProperty.call( rules, name ) ) { | ||
@@ -20,0 +21,0 @@ const start = rules[ name ].start; |
"use strict"; | ||
// Simple AST node visitor builder. | ||
const visitor = { | ||
build( functions ) { | ||
const util = require( "../util" ); | ||
const __slice = Array.prototype.slice; | ||
function visit( node ) { | ||
// Abstract syntax tree visitor for PEG.js | ||
class ASTVisitor { | ||
return functions[ node.type ].apply( null, arguments ); | ||
// Will traverse the node, strictly assuming the visitor can handle the node type. | ||
visit( node ) { | ||
} | ||
const args = __slice.call( arguments, 0 ); | ||
function visitNop() { | ||
// Do nothing. | ||
} | ||
return this[ node.type ].apply( this, args ); | ||
function visitExpression( node ) { | ||
} | ||
const extraArgs = Array.prototype.slice.call( arguments, 1 ); | ||
// Simple AST node visitor builder for PEG.js | ||
static build( functions ) { | ||
visit.apply( null, [ node.expression ].concat( extraArgs ) ); | ||
let visitor = new ASTVisitor(); | ||
util.extend( visitor, functions ); | ||
visitor = util.enforceFastProperties( visitor ); | ||
return visitor.visit.bind( visitor ); | ||
} | ||
} | ||
function visitChildren( property ) { | ||
} | ||
ASTVisitor.ASTVisitor = ASTVisitor; | ||
module.exports = ASTVisitor; | ||
return function visitProperty( node ) { | ||
// Helper's to create visitor's for use with the ASTVisitor class | ||
const on = ASTVisitor.for = { | ||
const extraArgs = Array.prototype.slice.call( arguments, 1 ); | ||
// Visit a node that is defined as a property on another node | ||
property( name ) { | ||
node[ property ].forEach( child => { | ||
return function visitProperty( node ) { | ||
visit.apply( null, [ child ].concat( extraArgs ) ); | ||
const extraArgs = __slice.call( arguments, 1 ); | ||
const value = node[ name ]; | ||
} ); | ||
if ( extraArgs.length ) | ||
}; | ||
this.visit.apply( this, [ value ].concat( extraArgs ) ); | ||
} | ||
else | ||
const DEFAULT_FUNCTIONS = { | ||
grammar( node ) { | ||
this.visit( value ); | ||
const extraArgs = Array.prototype.slice.call( arguments, 1 ); | ||
}; | ||
if ( node.initializer ) { | ||
}, | ||
visit.apply( null, [ node.initializer ].concat( extraArgs ) ); | ||
// Visit an array of nodes that are defined as a property on another node | ||
children( name ) { | ||
return function visitProperty( node ) { | ||
const args = __slice.call( arguments, 0 ); | ||
const children = node[ name ]; | ||
const visitor = this; | ||
const cb = args.length < 2 | ||
? function withoutArgs( child ) { | ||
visitor.visit( child ); | ||
} | ||
: function withArgs( child ) { | ||
node.rules.forEach( rule => { | ||
args[ 0 ] = child; | ||
visitor.visit.apply( visitor, args ); | ||
visit.apply( null, [ rule ].concat( extraArgs ) ); | ||
}; | ||
} ); | ||
children.forEach( cb ); | ||
}, | ||
initializer: visitNop, | ||
rule: visitExpression, | ||
named: visitExpression, | ||
choice: visitChildren( "alternatives" ), | ||
action: visitExpression, | ||
sequence: visitChildren( "elements" ), | ||
labeled: visitExpression, | ||
text: visitExpression, | ||
simple_and: visitExpression, | ||
simple_not: visitExpression, | ||
optional: visitExpression, | ||
zero_or_more: visitExpression, | ||
one_or_more: visitExpression, | ||
group: visitExpression, | ||
semantic_and: visitNop, | ||
semantic_not: visitNop, | ||
rule_ref: visitNop, | ||
literal: visitNop, | ||
class: visitNop, | ||
any: visitNop | ||
}; | ||
Object.keys( DEFAULT_FUNCTIONS ).forEach( type => { | ||
}, | ||
if ( ! Object.prototype.hasOwnProperty.call( functions, type ) ) { | ||
}; | ||
functions[ type ] = DEFAULT_FUNCTIONS[ type ]; | ||
// Build the default ast visitor functions | ||
} | ||
const visitNop = util.noop; | ||
const visitExpression = on.property( "expression" ); | ||
const DEFAULT_FUNCTIONS = { | ||
grammar( node ) { | ||
const extraArgs = __slice.call( arguments, 1 ); | ||
if ( node.initializer ) { | ||
this.visit.apply( this, [ node.initializer ].concat( extraArgs ) ); | ||
} | ||
node.rules.forEach( rule => { | ||
this.visit.apply( this, [ rule ].concat( extraArgs ) ); | ||
} ); | ||
return visit; | ||
}, | ||
} | ||
initializer: visitNop, | ||
rule: visitExpression, | ||
named: visitExpression, | ||
choice: on.children( "alternatives" ), | ||
action: visitExpression, | ||
sequence: on.children( "elements" ), | ||
labeled: visitExpression, | ||
text: visitExpression, | ||
simple_and: visitExpression, | ||
simple_not: visitExpression, | ||
optional: visitExpression, | ||
zero_or_more: visitExpression, | ||
one_or_more: visitExpression, | ||
group: visitExpression, | ||
semantic_and: visitNop, | ||
semantic_not: visitNop, | ||
rule_ref: visitNop, | ||
literal: visitNop, | ||
class: visitNop, | ||
any: visitNop, | ||
}; | ||
module.exports = visitor; | ||
util.each( DEFAULT_FUNCTIONS, ( fn, name ) => { | ||
ASTVisitor.prototype[ name ] = fn; | ||
} ); |
@@ -6,2 +6,3 @@ "use strict"; | ||
const parser = require( "./parser" ); | ||
const util = require( "./util" ); | ||
@@ -15,2 +16,3 @@ const peg = { | ||
compiler: compiler, | ||
util: util, | ||
@@ -30,21 +32,6 @@ // Generates a parser from a specified grammar and returns it. | ||
function convertPasses( passes ) { | ||
const converted = {}; | ||
Object.keys( passes ).forEach( stage => { | ||
converted[ stage ] = Object.keys( passes[ stage ] ) | ||
.map( name => passes[ stage ][ name ] ); | ||
} ); | ||
return converted; | ||
} | ||
const plugins = "plugins" in options ? options.plugins : []; | ||
const config = { | ||
parser: peg.parser, | ||
passes: convertPasses( peg.compiler.passes ) | ||
passes: util.convertPasses( peg.compiler.passes ) | ||
}; | ||
@@ -51,0 +38,0 @@ |
@@ -11,2 +11,3 @@ import gp from "./generated-parser"; | ||
type SyntaxError = gp.SyntaxErrorConstructor; | ||
type SourceLocation = gp.SourceLocation; | ||
@@ -25,5 +26,5 @@ /** | ||
message: string; | ||
location?: gp.SourceLocation; | ||
location?: SourceLocation; | ||
constructor( message: string, location?: gp.SourceLocation ); | ||
constructor( message: string, location?: SourceLocation ); | ||
@@ -58,3 +59,3 @@ } | ||
type: string; | ||
location: gp.SourceLocation; | ||
location: SourceLocation; | ||
@@ -96,4 +97,12 @@ } | ||
// Added by bytecode generator | ||
// Added by calc-report-failures pass | ||
reportFailures?: boolean; | ||
// Added by inference-match-result pass | ||
match?: number; | ||
// Added by generate-bytecode pass | ||
bytecode?: number[]; | ||
@@ -293,39 +302,42 @@ | ||
namespace visitor { | ||
interface IVisitor<R = any> { | ||
interface Visitor<R = any> { | ||
( node: parser.ast.Node, ...args ): R; | ||
( node: Node, ...args ): R; | ||
} | ||
} | ||
interface IVisitorMap<U = void> { | ||
interface VisitorMap<U = void> { | ||
[ key: string ]: any; | ||
grammar?<R = U>( node: Grammar, ...args ): R; | ||
initializer?<R = U>( node: parser.ast.Initializer, ...args ): R; | ||
rule?<R = U>( node: parser.ast.Rule, ...args ): R; | ||
named?<R = U>( node: parser.ast.Named, ...args ): R; | ||
choice?<R = U>( node: parser.ast.ChoiceExpression, ...args ): R; | ||
action?<R = U>( node: parser.ast.ActionExpression, ...args ): R; | ||
sequence?<R = U>( node: parser.ast.SequenceExpression, ...args ): R; | ||
labeled?<R = U>( node: parser.ast.LabeledExpression, ...args ): R; | ||
text?<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
simple_and?<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
simple_not?<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
optional?<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
zero_or_more?<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
one_or_more?<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
literal?<R = U>( node: parser.ast.LiteralMatcher, ...args ): R; | ||
class?<R = U>( node: parser.ast.CharacterClassMatcher, ...args ): R; | ||
any?<R = U>( node: parser.ast.AnyMatcher, ...args ): R; | ||
rule_ref?<R = U>( node: parser.ast.RuleReferenceExpression, ...args ): R; | ||
semantic_and?<R = U>( node: parser.ast.SemanticPredicateExpression, ...args ): R; | ||
semantic_not?<R = U>( node: parser.ast.SemanticPredicateExpression, ...args ): R; | ||
group?<R = U>( node: parser.ast.GroupExpression, ...args ): R; | ||
[ type: string ]: any; | ||
grammar<R = U>( node: Grammar, ...args ): R; | ||
initializer<R = U>( node: parser.ast.Initializer, ...args ): R; | ||
rule<R = U>( node: parser.ast.Rule, ...args ): R; | ||
named<R = U>( node: parser.ast.Named, ...args ): R; | ||
choice<R = U>( node: parser.ast.ChoiceExpression, ...args ): R; | ||
action<R = U>( node: parser.ast.ActionExpression, ...args ): R; | ||
sequence<R = U>( node: parser.ast.SequenceExpression, ...args ): R; | ||
labeled<R = U>( node: parser.ast.LabeledExpression, ...args ): R; | ||
text<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
simple_and<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
simple_not<R = U>( node: parser.ast.PrefixedExpression, ...args ): R; | ||
optional<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
zero_or_more<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
one_or_more<R = U>( node: parser.ast.SuffixedExpression, ...args ): R; | ||
literal<R = U>( node: parser.ast.LiteralMatcher, ...args ): R; | ||
class<R = U>( node: parser.ast.CharacterClassMatcher, ...args ): R; | ||
any<R = U>( node: parser.ast.AnyMatcher, ...args ): R; | ||
rule_ref<R = U>( node: parser.ast.RuleReferenceExpression, ...args ): R; | ||
semantic_and<R = U>( node: parser.ast.SemanticPredicateExpression, ...args ): R; | ||
semantic_not<R = U>( node: parser.ast.SemanticPredicateExpression, ...args ): R; | ||
group<R = U>( node: parser.ast.GroupExpression, ...args ): R; | ||
} | ||
} | ||
class visitor implements IVisitorMap { | ||
function build<T = void, R = any>( functions: VisitorMap<T> ): Visitor<R>; | ||
visit: IVisitor; | ||
static build<T = void, R = any>( functions: IVisitorMap<T> ): IVisitor<R>; | ||
static ASTVisitor: visitor; | ||
} | ||
@@ -353,2 +365,4 @@ | ||
function calcReportFailures( ast: Grammar, options: ICompilerPassOptions ): void; | ||
function inferenceMatchResult( ast: Grammar ): void; | ||
function generateBytecode( ast: Grammar ): void; | ||
@@ -378,2 +392,30 @@ function generateJS( ast: Grammar, options: ICompilerPassOptions ): void; | ||
namespace util { | ||
interface IStageMap { | ||
[ stage: string ] | ||
: compiler.ICompilerPass[] | ||
| { [ pass: string ]: compiler.ICompilerPass }; | ||
} | ||
function convertPasses( stages: IStageMap ): compiler.IPassesMap; | ||
interface IIterator<R = any> { | ||
( value: any ): R; | ||
( value: any, key: string ): R; | ||
} | ||
function clone( source: {} ): {}; | ||
function each( object: {}, iterator: IIterator<void> ): void; | ||
function extend( target: {}, source: {} ): {}; | ||
function map( object: {}, transformer: IIterator ): {}; | ||
function values( object: {}, transformer?: IIterator ): any[]; | ||
function enforceFastProperties( o: {} ): {}; | ||
} | ||
interface IBuildConfig<T = any> { | ||
@@ -380,0 +422,0 @@ |
@@ -70,2 +70,3 @@ export = generatedparser; | ||
ignoreCase?: boolean; | ||
expected?: SyntaxExpectation; | ||
@@ -110,2 +111,9 @@ } | ||
interface NotExpectation { | ||
type: "not"; | ||
expected: SyntaxExpectation; | ||
} | ||
type SyntaxErrorConstructor | ||
@@ -117,2 +125,3 @@ = SyntaxError<LiteralExpectation> | ||
| SyntaxError<OtherExpectation> | ||
| SyntaxError<NotExpectation> | ||
| SyntaxError<SyntaxExpectation>; | ||
@@ -119,0 +128,0 @@ |
@@ -21,2 +21,34 @@ /// <reference path="./api.d.ts" /> | ||
declare module "pegjs/lib/parser/ast" { | ||
export class Node { | ||
type: string; | ||
location: peg.SourceLocation; | ||
constructor( type: string, location: peg.SourceLocation ); | ||
} | ||
export class Grammar extends Node { | ||
initializer?: peg.parser.ast.Initializer; | ||
rules: peg.parser.ast.Rule[]; | ||
constructor( | ||
initializer: void | peg.parser.ast.Initializer, | ||
rules: peg.parser.ast.Rule[], | ||
location: peg.SourceLocation, | ||
); | ||
} | ||
} | ||
declare module "pegjs/lib/parser/index" { | ||
export default peg.parser; | ||
} | ||
declare module "pegjs/lib/peg" { | ||
@@ -78,2 +110,8 @@ | ||
declare module "pegjs/lib/compiler/passes/calc-report-failures" { | ||
export default peg.compiler.passes.generate.calcReportFailures; | ||
} | ||
declare module "pegjs/lib/compiler/passes/generate-bytecode" { | ||
@@ -91,2 +129,8 @@ | ||
declare module "pegjs/lib/compiler/passes/inference-match-result" { | ||
export default peg.compiler.passes.generate.inferenceMatchResult; | ||
} | ||
declare module "pegjs/lib/compiler/passes/remove-proxy-rules" { | ||
@@ -127,1 +171,35 @@ | ||
} | ||
declare module "pegjs/lib/util" { | ||
export default peg.util; | ||
} | ||
declare module "pegjs/lib/util/convert-passes" { | ||
export default peg.util.convertPasses; | ||
} | ||
declare module "pegjs/lib/util/index" { | ||
export default peg.util; | ||
} | ||
declare module "pegjs/lib/util/objects" { | ||
namespace objects { | ||
function clone( source: {} ): {}; | ||
function each( object: {}, iterator: peg.util.IIterator<void> ): void; | ||
function extend( target: {}, source: {} ): {}; | ||
function map( object: {}, transformer: peg.util.IIterator ): {}; | ||
function values( object: {}, transformer?: peg.util.IIterator ): any[]; | ||
function enforceFastProperties( o: {} ): {}; | ||
} | ||
export default objects; | ||
} |
{ | ||
"name": "pegjs", | ||
"version": "0.11.0-dev.200", | ||
"version": "0.11.0-dev.224", | ||
"description": "Parser generator for JavaScript", | ||
@@ -37,11 +37,12 @@ "keywords": [ | ||
"devDependencies": { | ||
"babel-preset-es2015": "6.24.1", | ||
"babel-core": "6.26.0", | ||
"dedent": "0.7.0", | ||
"babel-preset-env": "1.6.1", | ||
"babelify": "8.0.0", | ||
"browserify": "14.5.0", | ||
"chai": "4.1.2", | ||
"chai-like": "^1.0.0", | ||
"coveralls": "3.0.0", | ||
"dedent": "0.7.0", | ||
"del": "3.0.0", | ||
"eslint-config-futagozaryuu": "3.7.x", | ||
"eslint-config-futagozaryuu": "3.8.x", | ||
"express": "4.16.2", | ||
@@ -52,11 +53,11 @@ "glob": "7.1.2", | ||
"gulp-header": "1.8.9", | ||
"gulp-mocha": "4.3.1", | ||
"gulp-mocha": "5.0.0", | ||
"gulp-rename": "1.2.2", | ||
"gulp-uglify": "3.0.0", | ||
"morgan": "1.9.0", | ||
"nyc": "11.3.0", | ||
"run-sequence": "2.2.0", | ||
"nyc": "11.4.1", | ||
"run-sequence": "2.2.1", | ||
"sinon": "4.1.3", | ||
"vinyl-buffer": "1.0.0", | ||
"vinyl-source-stream": "1.1.0" | ||
"vinyl-buffer": "1.0.1", | ||
"vinyl-source-stream": "2.0.0" | ||
}, | ||
@@ -63,0 +64,0 @@ "engines": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34
2
281425
24
6683