Move all codegeneration from generateBytecode
pass to generateJs
pass (#459)
* Split 'consts' collection by content types into: - literals: for literal expressions, like `"a"` - classes: for character class expressions, like `[a]` - expectations: for constants describing expected values when parse failed - functions: for constants with function code * Move any JavaScript code generation from 'generateBytecode' to 'generateJs'. * Rename opcode 'MATCH_REGEXP' to 'MATCH_CLASS' (name reflects purpose, not implementation). * Replace 'PUSH' opcode with 'PUSH_EMPTY_STRING' opcode because it is only used with empty strings
This commit is contained in:
parent
617b6b7425
commit
9b90fa1d81
|
@ -5,54 +5,54 @@ const opcodes = {
|
||||||
|
|
||||||
// Stack Manipulation
|
// Stack Manipulation
|
||||||
|
|
||||||
PUSH: 0, // PUSH c
|
PUSH_EMPTY_STRING: 0, // PUSH_EMPTY_STRING
|
||||||
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
|
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
|
||||||
PUSH_NULL: 2, // PUSH_NULL
|
PUSH_NULL: 2, // PUSH_NULL
|
||||||
PUSH_FAILED: 3, // PUSH_FAILED
|
PUSH_FAILED: 3, // PUSH_FAILED
|
||||||
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
|
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
|
||||||
PUSH_CURR_POS: 5, // PUSH_CURR_POS
|
PUSH_CURR_POS: 5, // PUSH_CURR_POS
|
||||||
POP: 6, // POP
|
POP: 6, // POP
|
||||||
POP_CURR_POS: 7, // POP_CURR_POS
|
POP_CURR_POS: 7, // POP_CURR_POS
|
||||||
POP_N: 8, // POP_N n
|
POP_N: 8, // POP_N n
|
||||||
NIP: 9, // NIP
|
NIP: 9, // NIP
|
||||||
APPEND: 10, // APPEND
|
APPEND: 10, // APPEND
|
||||||
WRAP: 11, // WRAP n
|
WRAP: 11, // WRAP n
|
||||||
TEXT: 12, // TEXT
|
TEXT: 12, // TEXT
|
||||||
|
|
||||||
// Conditions and Loops
|
// Conditions and Loops
|
||||||
|
|
||||||
IF: 13, // IF t, f
|
IF: 13, // IF t, f
|
||||||
IF_ERROR: 14, // IF_ERROR t, f
|
IF_ERROR: 14, // IF_ERROR t, f
|
||||||
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
|
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
|
||||||
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
|
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
|
||||||
|
|
||||||
// Matching
|
// Matching
|
||||||
|
|
||||||
MATCH_ANY: 17, // MATCH_ANY a, f, ...
|
MATCH_ANY: 17, // MATCH_ANY a, f, ...
|
||||||
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
|
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
|
||||||
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
|
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
|
||||||
MATCH_REGEXP: 20, // MATCH_REGEXP r, a, f, ...
|
MATCH_CLASS: 20, // MATCH_CLASS c, a, f, ...
|
||||||
ACCEPT_N: 21, // ACCEPT_N n
|
ACCEPT_N: 21, // ACCEPT_N n
|
||||||
ACCEPT_STRING: 22, // ACCEPT_STRING s
|
ACCEPT_STRING: 22, // ACCEPT_STRING s
|
||||||
EXPECT: 23, // EXPECT e
|
EXPECT: 23, // EXPECT e
|
||||||
|
|
||||||
// Calls
|
// Calls
|
||||||
|
|
||||||
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
|
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
|
||||||
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
|
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
|
||||||
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
|
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
|
||||||
|
|
||||||
// Rules
|
// Rules
|
||||||
|
|
||||||
RULE: 27, // RULE r
|
RULE: 27, // RULE r
|
||||||
|
|
||||||
// Failure Reporting
|
// Failure Reporting
|
||||||
|
|
||||||
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
|
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
|
||||||
SILENT_FAILS_OFF: 29, // SILENT_FAILS_OFF
|
SILENT_FAILS_OFF: 29, // SILENT_FAILS_OFF
|
||||||
|
|
||||||
EXPECT_NS_BEGIN: 38, // EXPECT_NS_BEGIN
|
EXPECT_NS_BEGIN: 38, // EXPECT_NS_BEGIN
|
||||||
EXPECT_NS_END: 39 // EXPECT_NS_END invert
|
EXPECT_NS_END: 39 // EXPECT_NS_END invert
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const asts = require( "../asts" );
|
const asts = require( "../asts" );
|
||||||
const js = require( "../js" );
|
|
||||||
const op = require( "../opcodes" );
|
const op = require( "../opcodes" );
|
||||||
const visitor = require( "../visitor" );
|
const visitor = require( "../visitor" );
|
||||||
const util = require( "../../util" );
|
const util = require( "../../util" );
|
||||||
|
@ -14,9 +13,9 @@ const util = require( "../../util" );
|
||||||
// Stack Manipulation
|
// Stack Manipulation
|
||||||
// ------------------
|
// ------------------
|
||||||
//
|
//
|
||||||
// [0] PUSH c
|
// [0] PUSH_EMPTY_STRING
|
||||||
//
|
//
|
||||||
// stack.push(consts[c]);
|
// stack.push("");
|
||||||
//
|
//
|
||||||
// [1] PUSH_UNDEFINED
|
// [1] PUSH_UNDEFINED
|
||||||
//
|
//
|
||||||
|
@ -117,7 +116,7 @@ const util = require( "../../util" );
|
||||||
//
|
//
|
||||||
// [18] MATCH_STRING s, a, f, ...
|
// [18] MATCH_STRING s, a, f, ...
|
||||||
//
|
//
|
||||||
// if (input.substr(currPos, consts[s].length) === consts[s]) {
|
// if (input.substr(currPos, literals[s].length) === literals[s]) {
|
||||||
// interpret(ip + 4, ip + 4 + a);
|
// interpret(ip + 4, ip + 4 + a);
|
||||||
// } else {
|
// } else {
|
||||||
// interpret(ip + 4 + a, ip + 4 + a + f);
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
||||||
|
@ -125,15 +124,15 @@ const util = require( "../../util" );
|
||||||
//
|
//
|
||||||
// [19] MATCH_STRING_IC s, a, f, ...
|
// [19] MATCH_STRING_IC s, a, f, ...
|
||||||
//
|
//
|
||||||
// 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);
|
// interpret(ip + 4, ip + 4 + a);
|
||||||
// } else {
|
// } else {
|
||||||
// interpret(ip + 4 + a, ip + 4 + a + f);
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// [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);
|
// interpret(ip + 4, ip + 4 + a);
|
||||||
// } else {
|
// } else {
|
||||||
// interpret(ip + 4 + a, ip + 4 + a + f);
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
||||||
|
@ -146,12 +145,12 @@ const util = require( "../../util" );
|
||||||
//
|
//
|
||||||
// [22] ACCEPT_STRING s
|
// [22] ACCEPT_STRING s
|
||||||
//
|
//
|
||||||
// stack.push(consts[s]);
|
// stack.push(literals[s]);
|
||||||
// currPos += consts[s].length;
|
// currPos += literals[s].length;
|
||||||
//
|
//
|
||||||
// [23] EXPECT e
|
// [23] EXPECT e
|
||||||
//
|
//
|
||||||
// expect(consts[e]);
|
// expect(expectations[e]);
|
||||||
//
|
//
|
||||||
// Calls
|
// Calls
|
||||||
// -----
|
// -----
|
||||||
|
@ -166,7 +165,7 @@ const util = require( "../../util" );
|
||||||
//
|
//
|
||||||
// [26] CALL f, n, pc, p1, p2, ..., pN
|
// [26] CALL f, n, pc, p1, p2, ..., pN
|
||||||
//
|
//
|
||||||
// value = consts[f](stack[p1], ..., stack[pN]);
|
// value = functions[f](stack[p1], ..., stack[pN]);
|
||||||
// stack.pop(n);
|
// stack.pop(n);
|
||||||
// stack.push(value);
|
// stack.push(value);
|
||||||
//
|
//
|
||||||
|
@ -203,19 +202,46 @@ const util = require( "../../util" );
|
||||||
// }
|
// }
|
||||||
function generateBytecode( ast ) {
|
function generateBytecode( ast ) {
|
||||||
|
|
||||||
const consts = [];
|
const literals = [];
|
||||||
|
const classes = [];
|
||||||
|
const expectations = [];
|
||||||
|
const functions = [];
|
||||||
let generate;
|
let generate;
|
||||||
|
|
||||||
function addConst( value ) {
|
function addLiteralConst( value ) {
|
||||||
|
|
||||||
const index = consts.indexOf( value );
|
const index = literals.indexOf( value );
|
||||||
return index === -1 ? consts.push( value ) - 1 : index;
|
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 addExpectedConst( expected ) {
|
||||||
|
|
||||||
|
const pattern = JSON.stringify( expected );
|
||||||
|
const index = expectations.findIndex( e => JSON.stringify( e ) === pattern );
|
||||||
|
return index === -1 ? expectations.push( expected ) - 1 : index;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +310,7 @@ function generateBytecode( ast ) {
|
||||||
|
|
||||||
function buildSemanticPredicate( node, negative, context ) {
|
function buildSemanticPredicate( node, negative, context ) {
|
||||||
|
|
||||||
const functionIndex = addFunctionConst( Object.keys( context.env ), node.code );
|
const functionIndex = addFunctionConst( true, Object.keys( context.env ), node.code );
|
||||||
|
|
||||||
return buildSequence(
|
return buildSequence(
|
||||||
[ op.UPDATE_SAVED_POS ],
|
[ op.UPDATE_SAVED_POS ],
|
||||||
|
@ -312,7 +338,10 @@ function generateBytecode( ast ) {
|
||||||
grammar( node ) {
|
grammar( node ) {
|
||||||
|
|
||||||
node.rules.forEach( generate );
|
node.rules.forEach( generate );
|
||||||
node.consts = consts;
|
node.literals = literals;
|
||||||
|
node.classes = classes;
|
||||||
|
node.expectations = expectations;
|
||||||
|
node.functions = functions;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -330,8 +359,8 @@ function generateBytecode( ast ) {
|
||||||
named( node, context ) {
|
named( node, context ) {
|
||||||
|
|
||||||
// Do not generate unused constant, if no need it
|
// Do not generate unused constant, if no need it
|
||||||
const nameIndex = context.reportFailures ? addConst(
|
const nameIndex = context.reportFailures ? addExpectedConst(
|
||||||
`peg$otherExpectation("${ js.stringEscape( node.name ) }")`
|
{ type: "rule", value: node.name }
|
||||||
) : null;
|
) : null;
|
||||||
const expressionCode = generate( node.expression, {
|
const expressionCode = generate( node.expression, {
|
||||||
sp: context.sp,
|
sp: context.sp,
|
||||||
|
@ -393,7 +422,7 @@ function generateBytecode( ast ) {
|
||||||
} );
|
} );
|
||||||
const match = node.expression.match|0;
|
const match = node.expression.match|0;
|
||||||
const functionIndex = emitCall && match >= 0
|
const functionIndex = emitCall && match >= 0
|
||||||
? addFunctionConst( Object.keys( env ), node.code )
|
? addFunctionConst( false, Object.keys( env ), node.code )
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return emitCall === false
|
return emitCall === false
|
||||||
|
@ -450,6 +479,7 @@ function generateBytecode( ast ) {
|
||||||
} else if ( context.action ) {
|
} else if ( context.action ) {
|
||||||
|
|
||||||
const functionIndex = addFunctionConst(
|
const functionIndex = addFunctionConst(
|
||||||
|
false,
|
||||||
Object.keys( context.env ),
|
Object.keys( context.env ),
|
||||||
context.action.code
|
context.action.code
|
||||||
);
|
);
|
||||||
|
@ -623,16 +653,15 @@ function generateBytecode( ast ) {
|
||||||
|
|
||||||
const match = node.match|0;
|
const match = node.match|0;
|
||||||
const needConst = match === 0 || ( match > 0 && ! node.ignoreCase );
|
const needConst = match === 0 || ( match > 0 && ! node.ignoreCase );
|
||||||
const stringIndex = needConst ? addConst( `"${ js.stringEscape(
|
const stringIndex = needConst ? addLiteralConst(
|
||||||
node.ignoreCase ? node.value.toLowerCase() : node.value
|
node.ignoreCase ? node.value.toLowerCase() : node.value
|
||||||
) }"` ) : null;
|
|
||||||
// Do not generate unused constant, if no need it
|
|
||||||
const expectedIndex = context.reportFailures ? addConst(
|
|
||||||
"peg$literalExpectation("
|
|
||||||
+ `"${ js.stringEscape( node.value ) }", `
|
|
||||||
+ node.ignoreCase
|
|
||||||
+ ")"
|
|
||||||
) : null;
|
) : null;
|
||||||
|
// Do not generate unused constant, if no need it
|
||||||
|
const expectedIndex = context.reportFailures ? addExpectedConst( {
|
||||||
|
type: "literal",
|
||||||
|
value: node.value,
|
||||||
|
ignoreCase: node.ignoreCase
|
||||||
|
} ) : null;
|
||||||
|
|
||||||
// For case-sensitive strings the value must match the beginning of the
|
// For case-sensitive strings the value must match the beginning of the
|
||||||
// remaining input exactly. As a result, we can use |ACCEPT_STRING| and
|
// remaining input exactly. As a result, we can use |ACCEPT_STRING| and
|
||||||
|
@ -653,53 +682,27 @@ function generateBytecode( ast ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const stringIndex = addConst( "\"\"" );
|
return [ op.PUSH_EMPTY_STRING ];
|
||||||
return [ op.PUSH, stringIndex ];
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
class( node, context ) {
|
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 parts = "["
|
|
||||||
+ node.parts
|
|
||||||
.map( part =>
|
|
||||||
( Array.isArray( part )
|
|
||||||
? `["${ js.stringEscape( part[ 0 ] ) }", "${ js.stringEscape( part[ 1 ] ) }"]`
|
|
||||||
: "\"" + js.stringEscape( part ) + "\"" )
|
|
||||||
)
|
|
||||||
.join( ", " )
|
|
||||||
+ "]";
|
|
||||||
|
|
||||||
const match = node.match|0;
|
const match = node.match|0;
|
||||||
const regexpIndex = match === 0 ? addConst( regexp ) : null;
|
const classIndex = match === 0 ? addClassConst( node ) : null;
|
||||||
// Do not generate unused constant, if no need it
|
// Do not generate unused constant, if no need it
|
||||||
const expectedIndex = context.reportFailures ? addConst(
|
const expectedIndex = context.reportFailures ? addExpectedConst( {
|
||||||
"peg$classExpectation("
|
type: "class",
|
||||||
+ parts + ", "
|
value: node.parts,
|
||||||
+ node.inverted + ", "
|
inverted: node.inverted,
|
||||||
+ node.ignoreCase
|
ignoreCase: node.ignoreCase
|
||||||
+ ")"
|
} ) : null;
|
||||||
) : null;
|
|
||||||
|
|
||||||
return buildSequence(
|
return buildSequence(
|
||||||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [],
|
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [],
|
||||||
buildCondition(
|
buildCondition(
|
||||||
match,
|
match,
|
||||||
[ op.MATCH_REGEXP, regexpIndex ],
|
[ op.MATCH_CLASS, classIndex ],
|
||||||
[ op.ACCEPT_N, 1 ],
|
[ op.ACCEPT_N, 1 ],
|
||||||
[ op.PUSH_FAILED ]
|
[ op.PUSH_FAILED ]
|
||||||
)
|
)
|
||||||
|
@ -711,7 +714,7 @@ function generateBytecode( ast ) {
|
||||||
|
|
||||||
// Do not generate unused constant, if no need it
|
// Do not generate unused constant, if no need it
|
||||||
const expectedIndex = context.reportFailures
|
const expectedIndex = context.reportFailures
|
||||||
? addConst( "peg$anyExpectation()" )
|
? addExpectedConst( { type: "any" } )
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return buildSequence(
|
return buildSequence(
|
||||||
|
|
|
@ -22,13 +22,92 @@ function generateJS( ast, options ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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" ) {
|
if ( options.optimize === "size" ) {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
"var peg$consts = [",
|
"var peg$literals = [",
|
||||||
indent2( ast.consts.join( ",\n" ) ),
|
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" ) ),
|
||||||
"];",
|
"];",
|
||||||
"",
|
"",
|
||||||
"var peg$bytecode = [",
|
"var peg$bytecode = [",
|
||||||
|
@ -48,7 +127,15 @@ function generateJS( ast, options ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +307,7 @@ function generateJS( ast, options ) {
|
||||||
"stack.splice(",
|
"stack.splice(",
|
||||||
" stack.length - bc[ip + 2],",
|
" stack.length - bc[ip + 2],",
|
||||||
" bc[ip + 2],",
|
" bc[ip + 2],",
|
||||||
" peg$consts[bc[ip + 1]].apply(null, params)",
|
" peg$functions[bc[ip + 1]].apply(null, params)",
|
||||||
");",
|
");",
|
||||||
"",
|
"",
|
||||||
"ip += " + baseLength + " + " + paramsLengthCode + ";",
|
"ip += " + baseLength + " + " + paramsLengthCode + ";",
|
||||||
|
@ -275,9 +362,9 @@ function generateJS( ast, options ) {
|
||||||
" while (true) {",
|
" while (true) {",
|
||||||
" while (ip < end) {",
|
" while (ip < end) {",
|
||||||
" switch (bc[ip]) {",
|
" switch (bc[ip]) {",
|
||||||
" case " + op.PUSH + ":", // PUSH c
|
" case " + op.PUSH_EMPTY_STRING + ":", // PUSH_EMPTY_STRING
|
||||||
" stack.push(peg$consts[bc[ip + 1]]);",
|
" stack.push('');",
|
||||||
" ip += 2;",
|
" ip++;",
|
||||||
" break;",
|
" break;",
|
||||||
"",
|
"",
|
||||||
" case " + op.PUSH_UNDEFINED + ":", // PUSH_UNDEFINED
|
" case " + op.PUSH_UNDEFINED + ":", // PUSH_UNDEFINED
|
||||||
|
@ -363,19 +450,19 @@ function generateJS( ast, options ) {
|
||||||
"",
|
"",
|
||||||
" case " + op.MATCH_STRING + ":", // MATCH_STRING s, a, f, ...
|
" case " + op.MATCH_STRING + ":", // MATCH_STRING s, a, f, ...
|
||||||
indent10( generateCondition(
|
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
|
1
|
||||||
) ),
|
) ),
|
||||||
"",
|
"",
|
||||||
" case " + op.MATCH_STRING_IC + ":", // MATCH_STRING_IC s, a, f, ...
|
" case " + op.MATCH_STRING_IC + ":", // MATCH_STRING_IC s, a, f, ...
|
||||||
indent10( generateCondition(
|
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
|
1
|
||||||
) ),
|
) ),
|
||||||
"",
|
"",
|
||||||
" case " + op.MATCH_REGEXP + ":", // MATCH_REGEXP r, a, f, ...
|
" case " + op.MATCH_CLASS + ":", // MATCH_CLASS c, a, f, ...
|
||||||
indent10( generateCondition(
|
indent10( generateCondition(
|
||||||
"peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))",
|
"peg$regexps[bc[ip + 1]].test(input.charAt(peg$currPos))",
|
||||||
1
|
1
|
||||||
) ),
|
) ),
|
||||||
"",
|
"",
|
||||||
|
@ -386,14 +473,14 @@ function generateJS( ast, options ) {
|
||||||
" break;",
|
" break;",
|
||||||
"",
|
"",
|
||||||
" case " + op.ACCEPT_STRING + ":", // ACCEPT_STRING s
|
" case " + op.ACCEPT_STRING + ":", // ACCEPT_STRING s
|
||||||
" stack.push(peg$consts[bc[ip + 1]]);",
|
" stack.push(peg$literals[bc[ip + 1]]);",
|
||||||
" peg$currPos += peg$consts[bc[ip + 1]].length;",
|
" peg$currPos += peg$literals[bc[ip + 1]].length;",
|
||||||
" ip += 2;",
|
" ip += 2;",
|
||||||
" break;",
|
" break;",
|
||||||
"",
|
"",
|
||||||
" case " + op.EXPECT + ":", // EXPECT e
|
" case " + op.EXPECT + ":", // EXPECT e
|
||||||
" if (peg$silentFails === 0) {",
|
" if (peg$silentFails === 0) {",
|
||||||
" peg$expect(peg$consts[bc[ip + 1]]);",
|
" peg$expect(peg$expectations[bc[ip + 1]]);",
|
||||||
" }",
|
" }",
|
||||||
" ip += 2;",
|
" ip += 2;",
|
||||||
" break;",
|
" break;",
|
||||||
|
@ -463,11 +550,6 @@ function generateJS( ast, options ) {
|
||||||
const parts = [];
|
const parts = [];
|
||||||
const stackVars = [];
|
const stackVars = [];
|
||||||
|
|
||||||
function c( i ) {
|
|
||||||
|
|
||||||
return "peg$c" + i;
|
|
||||||
|
|
||||||
} // |consts[i]| of the abstract machine
|
|
||||||
function s( i ) {
|
function s( i ) {
|
||||||
|
|
||||||
return "s" + i;
|
return "s" + i;
|
||||||
|
@ -596,7 +678,7 @@ function generateJS( ast, options ) {
|
||||||
const baseLength = 4;
|
const baseLength = 4;
|
||||||
const paramsLength = bc[ ip + baseLength - 1 ];
|
const paramsLength = bc[ ip + baseLength - 1 ];
|
||||||
|
|
||||||
const value = c( bc[ ip + 1 ] )
|
const value = f( bc[ ip + 1 ] )
|
||||||
+ "("
|
+ "("
|
||||||
+ bc
|
+ bc
|
||||||
.slice( ip + baseLength, ip + baseLength + paramsLength )
|
.slice( ip + baseLength, ip + baseLength + paramsLength )
|
||||||
|
@ -614,9 +696,9 @@ function generateJS( ast, options ) {
|
||||||
|
|
||||||
switch ( bc[ ip ] ) {
|
switch ( bc[ ip ] ) {
|
||||||
|
|
||||||
case op.PUSH: // PUSH c
|
case op.PUSH_EMPTY_STRING: // PUSH_EMPTY_STRING
|
||||||
parts.push( stack.push( c( bc[ ip + 1 ] ) ) );
|
parts.push( stack.push( "''" ) );
|
||||||
ip += 2;
|
ip++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.PUSH_CURR_POS: // PUSH_CURR_POS
|
case op.PUSH_CURR_POS: // PUSH_CURR_POS
|
||||||
|
@ -624,7 +706,7 @@ function generateJS( ast, options ) {
|
||||||
ip++;
|
ip++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED
|
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED
|
||||||
parts.push( stack.push( "undefined" ) );
|
parts.push( stack.push( "undefined" ) );
|
||||||
ip++;
|
ip++;
|
||||||
break;
|
break;
|
||||||
|
@ -708,13 +790,13 @@ function generateJS( ast, options ) {
|
||||||
|
|
||||||
case op.MATCH_STRING: // MATCH_STRING s, a, f, ...
|
case op.MATCH_STRING: // MATCH_STRING s, a, f, ...
|
||||||
compileCondition(
|
compileCondition(
|
||||||
eval( ast.consts[ bc[ ip + 1 ] ] ).length > 1
|
ast.literals[ bc[ ip + 1 ] ].length > 1
|
||||||
? "input.substr(peg$currPos, "
|
? "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) === "
|
: "input.charCodeAt(peg$currPos) === "
|
||||||
+ eval( ast.consts[ bc[ ip + 1 ] ] ).charCodeAt( 0 )
|
+ ast.literals[ bc[ ip + 1 ] ].charCodeAt( 0 )
|
||||||
, 1
|
, 1
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -722,15 +804,15 @@ function generateJS( ast, options ) {
|
||||||
case op.MATCH_STRING_IC: // MATCH_STRING_IC s, a, f, ...
|
case op.MATCH_STRING_IC: // MATCH_STRING_IC s, a, f, ...
|
||||||
compileCondition(
|
compileCondition(
|
||||||
"input.substr(peg$currPos, "
|
"input.substr(peg$currPos, "
|
||||||
+ eval( ast.consts[ bc[ ip + 1 ] ] ).length
|
+ ast.literals[ bc[ ip + 1 ] ].length
|
||||||
+ ").toLowerCase() === "
|
+ ").toLowerCase() === "
|
||||||
+ c( bc[ ip + 1 ] )
|
+ l( bc[ ip + 1 ] )
|
||||||
, 1
|
, 1
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.MATCH_REGEXP: // MATCH_REGEXP r, a, f, ...
|
case op.MATCH_CLASS: // MATCH_CLASS c, a, f, ...
|
||||||
compileCondition( c( bc[ ip + 1 ] ) + ".test(input.charAt(peg$currPos))", 1 );
|
compileCondition( r( bc[ ip + 1 ] ) + ".test(input.charAt(peg$currPos))", 1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.ACCEPT_N: // ACCEPT_N n
|
case op.ACCEPT_N: // ACCEPT_N n
|
||||||
|
@ -748,17 +830,17 @@ function generateJS( ast, options ) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.ACCEPT_STRING: // ACCEPT_STRING s
|
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(
|
parts.push(
|
||||||
eval( ast.consts[ bc[ ip + 1 ] ] ).length > 1
|
ast.literals[ bc[ ip + 1 ] ].length > 1
|
||||||
? "peg$currPos += " + eval( ast.consts[ bc[ ip + 1 ] ] ).length + ";"
|
? "peg$currPos += " + ast.literals[ bc[ ip + 1 ] ].length + ";"
|
||||||
: "peg$currPos++;"
|
: "peg$currPos++;"
|
||||||
);
|
);
|
||||||
ip += 2;
|
ip += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op.EXPECT: // EXPECT e
|
case op.EXPECT: // EXPECT e
|
||||||
parts.push( "if (peg$silentFails === 0) { peg$expect(" + c( bc[ ip + 1 ] ) + "); }" );
|
parts.push( "if (peg$silentFails === 0) { peg$expect(" + e( bc[ ip + 1 ] ) + "); }" );
|
||||||
ip += 2;
|
ip += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -104,7 +104,7 @@ Grammar
|
||||||
return new ast.Grammar(
|
return new ast.Grammar(
|
||||||
extractOptional(initializer, 0),
|
extractOptional(initializer, 0),
|
||||||
extractList(rules, 0),
|
extractList(rules, 0),
|
||||||
location(),
|
location()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function constsDetails( consts ) {
|
function constsDetails( literals, classes, expectations, functions ) {
|
||||||
|
|
||||||
return { consts: consts };
|
return {
|
||||||
|
literals: literals,
|
||||||
|
classes: classes,
|
||||||
|
expectations: expectations,
|
||||||
|
functions: functions
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,9 +39,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
"c = 'c'"
|
"c = 'c'"
|
||||||
].join( "\n" ), {
|
].join( "\n" ), {
|
||||||
rules: [
|
rules: [
|
||||||
{ bytecode: [ 23, 1, 18, 0, 2, 1, 22, 0, 3 ] },
|
{ bytecode: [ 23, 0, 18, 0, 2, 1, 22, 0, 3 ] },
|
||||||
{ bytecode: [ 23, 3, 18, 2, 2, 1, 22, 2, 3 ] },
|
{ bytecode: [ 23, 1, 18, 1, 2, 1, 22, 1, 3 ] },
|
||||||
{ bytecode: [ 23, 5, 18, 4, 2, 1, 22, 4, 3 ] }
|
{ bytecode: [ 23, 2, 18, 2, 2, 1, 22, 2, 3 ] }
|
||||||
]
|
]
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -48,14 +53,16 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
"a = 'a'",
|
"a = 'a'",
|
||||||
"b = 'b'",
|
"b = 'b'",
|
||||||
"c = 'c'"
|
"c = 'c'"
|
||||||
].join( "\n" ), constsDetails( [
|
].join( "\n" ), constsDetails(
|
||||||
"\"a\"",
|
[ "a", "b", "c" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"\"b\"",
|
[
|
||||||
"peg$literalExpectation(\"b\", false)",
|
{ type: "literal", value: "a", ignoreCase: false },
|
||||||
"\"c\"",
|
{ type: "literal", value: "b", ignoreCase: false },
|
||||||
"peg$literalExpectation(\"c\", false)"
|
{ type: "literal", value: "c", ignoreCase: false }
|
||||||
] ) );
|
],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -66,7 +73,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = 'a'", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = 'a'", bytecodeDetails( [
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -92,13 +99,13 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
expect( pass ).to.changeAST( grammar2, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar2, bytecodeDetails( [
|
||||||
23, 0, // EXPECT <0>
|
23, 0, // EXPECT <0>
|
||||||
28, // SILENT_FAILS_ON
|
28, // SILENT_FAILS_ON
|
||||||
18, 1, 2, 1, 22, 1, 3, // <expression>
|
18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
29 // SILENT_FAILS_OFF
|
29 // SILENT_FAILS_OFF
|
||||||
] ) );
|
] ) );
|
||||||
expect( pass ).to.changeAST( grammar3, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar3, bytecodeDetails( [
|
||||||
23, 0, // EXPECT <0>
|
23, 0, // EXPECT <0>
|
||||||
28, // SILENT_FAILS_ON
|
28, // SILENT_FAILS_ON
|
||||||
20, 1, 2, 1, 21, 1, 3, // <expression>
|
20, 0, 2, 1, 21, 1, 3, // <expression>
|
||||||
29 // SILENT_FAILS_OFF
|
29 // SILENT_FAILS_OFF
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -106,17 +113,24 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar1, constsDetails( [
|
expect( pass ).to.changeAST( grammar1, constsDetails(
|
||||||
"peg$otherExpectation(\"start\")"
|
[],
|
||||||
] ) );
|
[],
|
||||||
expect( pass ).to.changeAST( grammar2, constsDetails( [
|
[ { type: "rule", value: "start" } ],
|
||||||
"peg$otherExpectation(\"start\")",
|
[]
|
||||||
"\"a\""
|
) );
|
||||||
] ) );
|
expect( pass ).to.changeAST( grammar2, constsDetails(
|
||||||
expect( pass ).to.changeAST( grammar3, constsDetails( [
|
[ "a" ],
|
||||||
"peg$otherExpectation(\"start\")",
|
[],
|
||||||
"/^[a]/"
|
[ { type: "rule", value: "start" } ],
|
||||||
] ) );
|
[]
|
||||||
|
) );
|
||||||
|
expect( pass ).to.changeAST( grammar3, constsDetails(
|
||||||
|
[],
|
||||||
|
[ { value: [ "a" ], inverted: false, ignoreCase: false } ],
|
||||||
|
[ { type: "rule", value: "start" } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -140,13 +154,15 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar1, constsDetails( [] ), {}, { reportFailures: false } );
|
expect( pass ).to.changeAST( grammar1, constsDetails(
|
||||||
expect( pass ).to.changeAST( grammar2, constsDetails( [
|
[], [], [], []
|
||||||
"\"a\""
|
), {}, { reportFailures: false } );
|
||||||
] ), {}, { reportFailures: false } );
|
expect( pass ).to.changeAST( grammar2, constsDetails(
|
||||||
expect( pass ).to.changeAST( grammar3, constsDetails( [
|
[ "a" ], [], [], []
|
||||||
"/^[a]/"
|
), {}, { reportFailures: false } );
|
||||||
] ), {}, { reportFailures: false } );
|
expect( pass ).to.changeAST( grammar3, constsDetails(
|
||||||
|
[], [ { value: [ "a" ], inverted: false, ignoreCase: false } ], [], []
|
||||||
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -159,13 +175,13 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = 'a' / 'b' / 'c'", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = 'a' / 'b' / 'c'", bytecodeDetails( [
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <alternatives[0]>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <alternatives[0]>
|
||||||
14, 23, 0, // IF_ERROR
|
14, 23, 0, // IF_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
23, 3, 18, 2, 2, 1, 22, 2, 3, // <alternatives[1]>
|
23, 1, 18, 1, 2, 1, 22, 1, 3, // <alternatives[1]>
|
||||||
14, 10, 0, // IF_ERROR
|
14, 10, 0, // IF_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
23, 5, 18, 4, 2, 1, 22, 4, 3 // <alternatives[2]>
|
23, 2, 18, 2, 2, 1, 22, 2, 3 // <alternatives[2]>
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -182,10 +198,10 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
15, 6, 0, // IF_NOT_ERROR
|
15, 6, 0, // IF_NOT_ERROR
|
||||||
24, 1, // * LOAD_SAVED_POS
|
24, 1, // * LOAD_SAVED_POS
|
||||||
26, 2, 1, 0, // CALL
|
26, 0, 1, 0, // CALL <0>
|
||||||
9 // NIP
|
9 // NIP
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -193,11 +209,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"function() { code }"
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
] ) );
|
[ { predicate: false, params: [], body: " code " } ]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -211,10 +228,10 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
15, 7, 0, // IF_NOT_ERROR
|
15, 7, 0, // IF_NOT_ERROR
|
||||||
24, 1, // * LOAD_SAVED_POS
|
24, 1, // * LOAD_SAVED_POS
|
||||||
26, 2, 1, 1, 0, // CALL
|
26, 0, 1, 1, 0, // CALL <0>
|
||||||
9 // NIP
|
9 // NIP
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -222,11 +239,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"function(a) { code }"
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
] ) );
|
[ { predicate: false, params: [ "a" ], body: " code " } ]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -240,14 +258,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
||||||
15, 41, 3, // IF_NOT_ERROR
|
15, 41, 3, // IF_NOT_ERROR
|
||||||
23, 3, 18, 2, 2, 1, 22, 2, 3, // * <elements[1]>
|
23, 1, 18, 1, 2, 1, 22, 1, 3, // * <elements[1]>
|
||||||
15, 25, 4, // IF_NOT_ERROR
|
15, 25, 4, // IF_NOT_ERROR
|
||||||
23, 5, 18, 4, 2, 1, 22, 4, 3, // * <elements[2]>
|
23, 2, 18, 2, 2, 1, 22, 2, 3, // * <elements[2]>
|
||||||
15, 9, 4, // IF_NOT_ERROR
|
15, 9, 4, // IF_NOT_ERROR
|
||||||
24, 3, // * LOAD_SAVED_POS
|
24, 3, // * LOAD_SAVED_POS
|
||||||
26, 6, 4, 3, 2, 1, 0, // CALL <6>
|
26, 0, 4, 3, 2, 1, 0, // CALL <0>
|
||||||
8, 3, // * POP_N
|
8, 3, // * POP_N
|
||||||
7, // POP_CURR_POS
|
7, // POP_CURR_POS
|
||||||
3, // PUSH_FAILED
|
3, // PUSH_FAILED
|
||||||
|
@ -263,15 +281,16 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a", "b", "c" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"\"b\"",
|
[
|
||||||
"peg$literalExpectation(\"b\", false)",
|
{ type: "literal", value: "a", ignoreCase: false },
|
||||||
"\"c\"",
|
{ type: "literal", value: "b", ignoreCase: false },
|
||||||
"peg$literalExpectation(\"c\", false)",
|
{ type: "literal", value: "c", ignoreCase: false }
|
||||||
"function(a, b, c) { code }"
|
],
|
||||||
] ) );
|
[ { predicate: false, params: [ "a", "b", "c" ], body: " code " } ]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -287,11 +306,11 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
||||||
15, 35, 3, // IF_NOT_ERROR
|
15, 35, 3, // IF_NOT_ERROR
|
||||||
23, 3, 18, 2, 2, 1, 22, 2, 3, // * <elements[1]>
|
23, 1, 18, 1, 2, 1, 22, 1, 3, // * <elements[1]>
|
||||||
15, 19, 4, // IF_NOT_ERROR
|
15, 19, 4, // IF_NOT_ERROR
|
||||||
23, 5, 18, 4, 2, 1, 22, 4, 3, // * <elements[2]>
|
23, 2, 18, 2, 2, 1, 22, 2, 3, // * <elements[2]>
|
||||||
15, 3, 4, // IF_NOT_ERROR
|
15, 3, 4, // IF_NOT_ERROR
|
||||||
11, 3, // * WRAP
|
11, 3, // * WRAP
|
||||||
9, // NIP
|
9, // NIP
|
||||||
|
@ -310,14 +329,16 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a", "b", "c" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"\"b\"",
|
[
|
||||||
"peg$literalExpectation(\"b\", false)",
|
{ type: "literal", value: "a", ignoreCase: false },
|
||||||
"\"c\"",
|
{ type: "literal", value: "b", ignoreCase: false },
|
||||||
"peg$literalExpectation(\"c\", false)"
|
{ type: "literal", value: "c", ignoreCase: false }
|
||||||
] ) );
|
],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -328,7 +349,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = a:'a'", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = a:'a'", bytecodeDetails( [
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -341,7 +362,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = $'a'", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = $'a'", bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
15, 2, 1, // IF_NOT_ERROR
|
15, 2, 1, // IF_NOT_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
12, // TEXT
|
12, // TEXT
|
||||||
|
@ -361,7 +382,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
38, // EXPECT_NS_BEGIN
|
38, // EXPECT_NS_BEGIN
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
39, 0, // EXPECT_NS_END <false>
|
39, 0, // EXPECT_NS_END <false>
|
||||||
15, 3, 3, // IF_NOT_ERROR
|
15, 3, 3, // IF_NOT_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
|
@ -376,10 +397,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -394,7 +417,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
38, // EXPECT_NS_BEGIN
|
38, // EXPECT_NS_BEGIN
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
39, 1, // EXPECT_NS_END <true>
|
39, 1, // EXPECT_NS_END <true>
|
||||||
14, 3, 3, // IF_ERROR
|
14, 3, 3, // IF_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
|
@ -409,10 +432,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -425,7 +450,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
14, 2, 0, // IF_ERROR
|
14, 2, 0, // IF_ERROR
|
||||||
6, // * POP
|
6, // * POP
|
||||||
2 // PUSH_NULL
|
2 // PUSH_NULL
|
||||||
|
@ -435,10 +460,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -452,10 +479,10 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
4, // PUSH_EMPTY_ARRAY
|
4, // PUSH_EMPTY_ARRAY
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
16, 10, // WHILE_NOT_ERROR
|
16, 10, // WHILE_NOT_ERROR
|
||||||
10, // * APPEND
|
10, // * APPEND
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
6 // POP
|
6 // POP
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -463,10 +490,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -480,11 +509,11 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
4, // PUSH_EMPTY_ARRAY
|
4, // PUSH_EMPTY_ARRAY
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
15, 13, 3, // IF_NOT_ERROR
|
15, 13, 3, // IF_NOT_ERROR
|
||||||
16, 10, // * WHILE_NOT_ERROR
|
16, 10, // * WHILE_NOT_ERROR
|
||||||
10, // * APPEND
|
10, // * APPEND
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <expression>
|
||||||
6, // POP
|
6, // POP
|
||||||
6, // * POP
|
6, // * POP
|
||||||
6, // POP
|
6, // POP
|
||||||
|
@ -495,10 +524,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -511,17 +542,19 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
23, 0, 18, 0, 2, 1, 22, 0, 3 // <expression>
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -537,7 +570,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
25, // UPDATE_SAVED_POS
|
25, // UPDATE_SAVED_POS
|
||||||
26, 0, 0, 0, // CALL
|
26, 0, 0, 0, // CALL <0>
|
||||||
13, 2, 2, // IF
|
13, 2, 2, // IF
|
||||||
6, // * POP
|
6, // * POP
|
||||||
1, // PUSH_UNDEFINED
|
1, // PUSH_UNDEFINED
|
||||||
|
@ -551,7 +584,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST(
|
expect( pass ).to.changeAST(
|
||||||
grammar,
|
grammar,
|
||||||
constsDetails( [ "function() { code }" ] )
|
constsDetails( [], [], [], [ { predicate: true, params: [], body: " code " } ] )
|
||||||
);
|
);
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -566,14 +599,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
||||||
15, 57, 3, // IF_NOT_ERROR
|
15, 57, 3, // IF_NOT_ERROR
|
||||||
23, 3, 18, 2, 2, 1, 22, 2, 3, // * <elements[1]>
|
23, 1, 18, 1, 2, 1, 22, 1, 3, // * <elements[1]>
|
||||||
15, 41, 4, // IF_NOT_ERROR
|
15, 41, 4, // IF_NOT_ERROR
|
||||||
23, 5, 18, 4, 2, 1, 22, 4, 3, // * <elements[2]>
|
23, 2, 18, 2, 2, 1, 22, 2, 3, // * <elements[2]>
|
||||||
15, 25, 4, // IF_NOT_ERROR
|
15, 25, 4, // IF_NOT_ERROR
|
||||||
25, // * UPDATE_SAVED_POS
|
25, // * UPDATE_SAVED_POS
|
||||||
26, 6, 0, 3, 2, 1, 0, // CALL
|
26, 0, 0, 3, 2, 1, 0, // CALL <0>
|
||||||
13, 2, 2, // IF
|
13, 2, 2, // IF
|
||||||
6, // * POP
|
6, // * POP
|
||||||
1, // PUSH_UNDEFINED
|
1, // PUSH_UNDEFINED
|
||||||
|
@ -600,15 +633,16 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a", "b", "c" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"\"b\"",
|
[
|
||||||
"peg$literalExpectation(\"b\", false)",
|
{ type: "literal", value: "a", ignoreCase: false },
|
||||||
"\"c\"",
|
{ type: "literal", value: "b", ignoreCase: false },
|
||||||
"peg$literalExpectation(\"c\", false)",
|
{ type: "literal", value: "c", ignoreCase: false }
|
||||||
"function(a, b, c) { code }"
|
],
|
||||||
] ) );
|
[ { predicate: true, params: [ "a", "b", "c" ], body: " code " } ]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -626,7 +660,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
25, // UPDATE_SAVED_POS
|
25, // UPDATE_SAVED_POS
|
||||||
26, 0, 0, 0, // CALL
|
26, 0, 0, 0, // CALL <0>
|
||||||
13, 2, 2, // IF
|
13, 2, 2, // IF
|
||||||
6, // * POP
|
6, // * POP
|
||||||
3, // PUSH_FAILED
|
3, // PUSH_FAILED
|
||||||
|
@ -640,7 +674,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST(
|
expect( pass ).to.changeAST(
|
||||||
grammar,
|
grammar,
|
||||||
constsDetails( [ "function() { code }" ] )
|
constsDetails( [], [], [], [ { predicate: true, params: [], body: " code " } ] )
|
||||||
);
|
);
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -655,14 +689,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
5, // PUSH_CURR_POS
|
5, // PUSH_CURR_POS
|
||||||
23, 1, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
23, 0, 18, 0, 2, 1, 22, 0, 3, // <elements[0]>
|
||||||
15, 57, 3, // IF_NOT_ERROR
|
15, 57, 3, // IF_NOT_ERROR
|
||||||
23, 3, 18, 2, 2, 1, 22, 2, 3, // * <elements[1]>
|
23, 1, 18, 1, 2, 1, 22, 1, 3, // * <elements[1]>
|
||||||
15, 41, 4, // IF_NOT_ERROR
|
15, 41, 4, // IF_NOT_ERROR
|
||||||
23, 5, 18, 4, 2, 1, 22, 4, 3, // * <elements[2]>
|
23, 2, 18, 2, 2, 1, 22, 2, 3, // * <elements[2]>
|
||||||
15, 25, 4, // IF_NOT_ERROR
|
15, 25, 4, // IF_NOT_ERROR
|
||||||
25, // * UPDATE_SAVED_POS
|
25, // * UPDATE_SAVED_POS
|
||||||
26, 6, 0, 3, 2, 1, 0, // CALL
|
26, 0, 0, 3, 2, 1, 0, // CALL <0>
|
||||||
13, 2, 2, // IF
|
13, 2, 2, // IF
|
||||||
6, // * POP
|
6, // * POP
|
||||||
3, // PUSH_FAILED
|
3, // PUSH_FAILED
|
||||||
|
@ -689,15 +723,16 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a", "b", "c" ],
|
||||||
"peg$literalExpectation(\"a\", false)",
|
[],
|
||||||
"\"b\"",
|
[
|
||||||
"peg$literalExpectation(\"b\", false)",
|
{ type: "literal", value: "a", ignoreCase: false },
|
||||||
"\"c\"",
|
{ type: "literal", value: "b", ignoreCase: false },
|
||||||
"peg$literalExpectation(\"c\", false)",
|
{ type: "literal", value: "c", ignoreCase: false }
|
||||||
"function(a, b, c) { code }"
|
],
|
||||||
] ) );
|
[ { predicate: true, params: [ "a", "b", "c" ], body: " code " } ]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -736,14 +771,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
0, 0 // PUSH
|
0 // PUSH_EMPTY_STRING
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [ "\"\"" ] ) );
|
expect( pass ).to.changeAST( grammar, constsDetails( [], [], [], [] ) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -756,9 +791,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
23, 1, // EXPECT <1>
|
23, 0, // EXPECT <0>
|
||||||
18, 0, 2, 1, // MATCH_STRING <0>
|
18, 0, 2, 1, // MATCH_STRING <0>
|
||||||
22, 0, // * ACCEPT_STRING
|
22, 0, // * ACCEPT_STRING <0>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -766,10 +801,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"a\", false)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "a", ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -782,9 +819,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
23, 1, // EXPECT <1>
|
23, 0, // EXPECT <0>
|
||||||
19, 0, 2, 1, // MATCH_STRING_IC <0>
|
19, 0, 2, 1, // MATCH_STRING_IC <0>
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -792,10 +829,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\"",
|
[ "a" ],
|
||||||
"peg$literalExpectation(\"A\", true)"
|
[],
|
||||||
] ) );
|
[ { type: "literal", value: "A", ignoreCase: true } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -812,14 +851,14 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
0, 0 // PUSH
|
0 // PUSH_EMPTY_STRING
|
||||||
] ), {}, { reportFailures: false } );
|
] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [ "\"\"" ] ), {}, { reportFailures: false } );
|
expect( pass ).to.changeAST( grammar, constsDetails( [], [], [], [] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -833,7 +872,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
18, 0, 2, 1, // MATCH_STRING <0>
|
18, 0, 2, 1, // MATCH_STRING <0>
|
||||||
22, 0, // * ACCEPT_STRING
|
22, 0, // * ACCEPT_STRING <0>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ), {}, { reportFailures: false } );
|
] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
|
@ -841,9 +880,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\""
|
[ "a" ], [], [], []
|
||||||
] ), {}, { reportFailures: false } );
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -857,7 +896,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
19, 0, 2, 1, // MATCH_STRING_IC <0>
|
19, 0, 2, 1, // MATCH_STRING_IC <0>
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ), {}, { reportFailures: false } );
|
] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
|
@ -865,9 +904,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, constsDetails( [
|
expect( pass ).to.changeAST( grammar, constsDetails(
|
||||||
"\"a\""
|
[ "a" ], [], [], []
|
||||||
] ), {}, { reportFailures: false } );
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -884,9 +923,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = [a]", bytecodeDetails( [
|
||||||
23, 1, // EXPECT <1>
|
23, 0, // EXPECT <0>
|
||||||
20, 0, 2, 1, // MATCH_REGEXP <0>
|
20, 0, 2, 1, // MATCH_CLASS <0>
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -896,10 +935,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [a]", constsDetails(
|
||||||
"/^[a]/",
|
[],
|
||||||
"peg$classExpectation([\"a\"], false, false)"
|
[ { value: [ "a" ], inverted: false, ignoreCase: false } ],
|
||||||
] ) );
|
[ { type: "class", value: [ "a" ], inverted: false, ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -909,10 +950,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [^a]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [^a]", constsDetails(
|
||||||
"/^[^a]/",
|
[],
|
||||||
"peg$classExpectation([\"a\"], true, false)"
|
[ { value: [ "a" ], inverted: true, ignoreCase: false } ],
|
||||||
] ) );
|
[ { type: "class", value: [ "a" ], inverted: true, ignoreCase: false } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -922,10 +965,12 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]i", constsDetails( [
|
expect( pass ).to.changeAST( "start = [a]i", constsDetails(
|
||||||
"/^[a]/i",
|
[],
|
||||||
"peg$classExpectation([\"a\"], false, true)"
|
[ { value: [ "a" ], inverted: false, ignoreCase: true } ],
|
||||||
] ) );
|
[ { type: "class", value: [ "a" ], inverted: false, ignoreCase: true } ],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -935,10 +980,25 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [ab-def-hij-l]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [ab-def-hij-l]", constsDetails(
|
||||||
"/^[ab-def-hij-l]/",
|
[],
|
||||||
"peg$classExpectation([\"a\", [\"b\", \"d\"], \"e\", [\"f\", \"h\"], \"i\", [\"j\", \"l\"]], false, false)"
|
[
|
||||||
] ) );
|
{
|
||||||
|
value: [ "a", [ "b", "d" ], "e", [ "f", "h" ], "i", [ "j", "l" ] ],
|
||||||
|
inverted: false,
|
||||||
|
ignoreCase: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: "class",
|
||||||
|
value: [ "a", [ "b", "d" ], "e", [ "f", "h" ], "i", [ "j", "l" ] ],
|
||||||
|
inverted: false,
|
||||||
|
ignoreCase: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
) );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -951,8 +1011,8 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
it( "generates correct bytecode", function () {
|
it( "generates correct bytecode", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]", bytecodeDetails( [
|
expect( pass ).to.changeAST( "start = [a]", bytecodeDetails( [
|
||||||
20, 0, 2, 1, // MATCH_REGEXP <0>
|
20, 0, 2, 1, // MATCH_CLASS <0>
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ), {}, { reportFailures: false } );
|
] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
|
@ -962,9 +1022,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [a]", constsDetails(
|
||||||
"/^[a]/"
|
[], [ { value: [ "a" ], inverted: false, ignoreCase: false } ], [], []
|
||||||
] ), {}, { reportFailures: false } );
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -974,9 +1034,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [^a]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [^a]", constsDetails(
|
||||||
"/^[^a]/"
|
[], [ { value: [ "a" ], inverted: true, ignoreCase: false } ], [], []
|
||||||
] ), {}, { reportFailures: false } );
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -986,9 +1046,9 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [a]i", constsDetails( [
|
expect( pass ).to.changeAST( "start = [a]i", constsDetails(
|
||||||
"/^[a]/i"
|
[], [ { value: [ "a" ], inverted: false, ignoreCase: true } ], [], []
|
||||||
] ), {}, { reportFailures: false } );
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -998,9 +1058,18 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
it( "defines correct constants", function () {
|
it( "defines correct constants", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( "start = [ab-def-hij-l]", constsDetails( [
|
expect( pass ).to.changeAST( "start = [ab-def-hij-l]", constsDetails(
|
||||||
"/^[ab-def-hij-l]/"
|
[],
|
||||||
] ), {}, { reportFailures: false } );
|
[
|
||||||
|
{
|
||||||
|
value: [ "a", [ "b", "d" ], "e", [ "f", "h" ], "i", [ "j", "l" ] ],
|
||||||
|
inverted: false,
|
||||||
|
ignoreCase: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
), {}, { reportFailures: false } );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -1021,7 +1090,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
23, 0, // EXPECT <0>
|
23, 0, // EXPECT <0>
|
||||||
17, 2, 1, // MATCH_ANY
|
17, 2, 1, // MATCH_ANY
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ) );
|
] ) );
|
||||||
|
|
||||||
|
@ -1031,7 +1100,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST(
|
expect( pass ).to.changeAST(
|
||||||
grammar,
|
grammar,
|
||||||
constsDetails( [ "peg$anyExpectation()" ] )
|
constsDetails( [], [], [ { type: "any" } ], [] )
|
||||||
);
|
);
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
@ -1046,7 +1115,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
expect( pass ).to.changeAST( grammar, bytecodeDetails( [
|
||||||
17, 2, 1, // MATCH_ANY
|
17, 2, 1, // MATCH_ANY
|
||||||
21, 1, // * ACCEPT_N
|
21, 1, // * ACCEPT_N <1>
|
||||||
3 // * PUSH_FAILED
|
3 // * PUSH_FAILED
|
||||||
] ), {}, { reportFailures: false } );
|
] ), {}, { reportFailures: false } );
|
||||||
|
|
||||||
|
@ -1056,7 +1125,7 @@ describe( "compiler pass |generateBytecode|", function () {
|
||||||
|
|
||||||
expect( pass ).to.changeAST(
|
expect( pass ).to.changeAST(
|
||||||
grammar,
|
grammar,
|
||||||
constsDetails( [] ),
|
constsDetails( [], [], [], [] ),
|
||||||
{},
|
{},
|
||||||
{ reportFailures: false }
|
{ reportFailures: false }
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue