Optimize redundant fail checks (#400)
eliminate unnecessary checks for the result of parse, when it can be statically determined
This commit is contained in:
parent
f5699d63fb
commit
534dc53ac2
|
@ -9,6 +9,7 @@ const reportDuplicateRules = require( "./passes/report-duplicate-rules" );
|
|||
const reportInfiniteRecursion = require( "./passes/report-infinite-recursion" );
|
||||
const reportInfiniteRepetition = require( "./passes/report-infinite-repetition" );
|
||||
const reportUndefinedRules = require( "./passes/report-undefined-rules" );
|
||||
const inferenceMatchResult = require( "./passes/inference-match-result" );
|
||||
const visitor = require( "./visitor" );
|
||||
|
||||
function processOptions( options, defaults ) {
|
||||
|
@ -58,6 +59,7 @@ const compiler = {
|
|||
},
|
||||
generate: {
|
||||
calcReportFailures: calcReportFailures,
|
||||
inferenceMatchResult: inferenceMatchResult,
|
||||
generateBytecode: generateBytecode,
|
||||
generateJS: generateJS
|
||||
}
|
||||
|
|
|
@ -238,7 +238,10 @@ function generateBytecode( ast ) {
|
|||
|
||||
}
|
||||
|
||||
function buildCondition( condCode, thenCode, elseCode ) {
|
||||
function buildCondition( match, condCode, thenCode, elseCode ) {
|
||||
|
||||
if ( match > 0 ) return thenCode;
|
||||
if ( match < 0 ) return elseCode;
|
||||
|
||||
return condCode.concat(
|
||||
[ thenCode.length, elseCode.length ],
|
||||
|
@ -263,6 +266,7 @@ function generateBytecode( ast ) {
|
|||
|
||||
function buildSimplePredicate( expression, negative, context ) {
|
||||
|
||||
const match = expression.match|0;
|
||||
return buildSequence(
|
||||
[ op.PUSH_CURR_POS ],
|
||||
[ op.EXPECT_NS_BEGIN ],
|
||||
|
@ -274,6 +278,7 @@ function generateBytecode( ast ) {
|
|||
} ),
|
||||
[ op.EXPECT_NS_END, negative ? 1 : 0 ],
|
||||
buildCondition(
|
||||
negative ? -match : match,
|
||||
[ negative ? op.IF_ERROR : op.IF_NOT_ERROR ],
|
||||
buildSequence(
|
||||
[ op.POP ],
|
||||
|
@ -290,14 +295,15 @@ function generateBytecode( ast ) {
|
|||
|
||||
}
|
||||
|
||||
function buildSemanticPredicate( code, negative, context ) {
|
||||
function buildSemanticPredicate( node, negative, context ) {
|
||||
|
||||
const functionIndex = addFunctionConst( Object.keys( context.env ), code );
|
||||
const functionIndex = addFunctionConst( Object.keys( context.env ), node.code );
|
||||
|
||||
return buildSequence(
|
||||
[ op.UPDATE_SAVED_POS ],
|
||||
buildCall( functionIndex, 0, context.env, context.sp ),
|
||||
buildCondition(
|
||||
node.match|0,
|
||||
[ op.IF ],
|
||||
buildSequence( [ op.POP ], negative ? [ op.PUSH_FAILED ] : [ op.PUSH_UNDEFINED ] ),
|
||||
buildSequence( [ op.POP ], negative ? [ op.PUSH_UNDEFINED ] : [ op.PUSH_FAILED ] )
|
||||
|
@ -371,6 +377,8 @@ function generateBytecode( ast ) {
|
|||
alternatives.length < 2
|
||||
? []
|
||||
: buildCondition(
|
||||
// If alternative always match no need generate code for next alternatives
|
||||
-( alternatives[ 0 ].match|0 ),
|
||||
[ op.IF_ERROR ],
|
||||
buildSequence(
|
||||
[ op.POP ],
|
||||
|
@ -396,7 +404,10 @@ function generateBytecode( ast ) {
|
|||
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( Object.keys( env ), node.code )
|
||||
: null;
|
||||
|
||||
return emitCall === false
|
||||
? expressionCode
|
||||
|
@ -404,6 +415,7 @@ function generateBytecode( ast ) {
|
|||
[ op.PUSH_CURR_POS ],
|
||||
expressionCode,
|
||||
buildCondition(
|
||||
match,
|
||||
[ op.IF_NOT_ERROR ],
|
||||
buildSequence(
|
||||
[ op.LOAD_SAVED_POS, 1 ],
|
||||
|
@ -432,6 +444,7 @@ function generateBytecode( ast ) {
|
|||
reportFailures: context.reportFailures
|
||||
} ),
|
||||
buildCondition(
|
||||
elements[ 0 ].match|0,
|
||||
[ op.IF_NOT_ERROR ],
|
||||
buildElementsCode( elements.slice( 1 ), {
|
||||
sp: context.sp + 1,
|
||||
|
@ -507,6 +520,7 @@ function generateBytecode( ast ) {
|
|||
reportFailures: context.reportFailures
|
||||
} ),
|
||||
buildCondition(
|
||||
node.expression.match|0,
|
||||
[ op.IF_NOT_ERROR ],
|
||||
buildSequence( [ op.POP ], [ op.TEXT ] ),
|
||||
[ op.NIP ]
|
||||
|
@ -537,6 +551,8 @@ function generateBytecode( ast ) {
|
|||
reportFailures: context.reportFailures
|
||||
} ),
|
||||
buildCondition(
|
||||
// If expression always match no need replace FAILED to NULL
|
||||
-( node.expression.match|0 ),
|
||||
[ op.IF_ERROR ],
|
||||
buildSequence( [ op.POP ], [ op.PUSH_NULL ] ),
|
||||
[]
|
||||
|
@ -576,6 +592,7 @@ function generateBytecode( ast ) {
|
|||
[ op.PUSH_EMPTY_ARRAY ],
|
||||
expressionCode,
|
||||
buildCondition(
|
||||
node.expression.match|0,
|
||||
[ op.IF_NOT_ERROR ],
|
||||
buildSequence( buildAppendLoop( expressionCode ), [ op.POP ] ),
|
||||
buildSequence( [ op.POP ], [ op.POP ], [ op.PUSH_FAILED ] )
|
||||
|
@ -597,13 +614,13 @@ function generateBytecode( ast ) {
|
|||
|
||||
semantic_and( node, context ) {
|
||||
|
||||
return buildSemanticPredicate( node.code, false, context );
|
||||
return buildSemanticPredicate( node, false, context );
|
||||
|
||||
},
|
||||
|
||||
semantic_not( node, context ) {
|
||||
|
||||
return buildSemanticPredicate( node.code, true, context );
|
||||
return buildSemanticPredicate( node, true, context );
|
||||
|
||||
},
|
||||
|
||||
|
@ -617,9 +634,11 @@ function generateBytecode( ast ) {
|
|||
|
||||
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 ? addConst( `"${ js.stringEscape(
|
||||
node.ignoreCase ? node.value.toLowerCase() : node.value
|
||||
) }"` );
|
||||
) }"` ) : null;
|
||||
// Do not generate unused constant, if no need it
|
||||
const expectedIndex = context.reportFailures ? addConst(
|
||||
"peg$literalExpectation("
|
||||
|
@ -634,6 +653,7 @@ function generateBytecode( ast ) {
|
|||
return buildSequence(
|
||||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [],
|
||||
buildCondition(
|
||||
match,
|
||||
node.ignoreCase
|
||||
? [ op.MATCH_STRING_IC, stringIndex ]
|
||||
: [ op.MATCH_STRING, stringIndex ],
|
||||
|
@ -677,7 +697,8 @@ function generateBytecode( ast ) {
|
|||
.join( ", " )
|
||||
+ "]";
|
||||
|
||||
const regexpIndex = addConst( regexp );
|
||||
const match = node.match|0;
|
||||
const regexpIndex = match === 0 ? addConst( regexp ) : null;
|
||||
// Do not generate unused constant, if no need it
|
||||
const expectedIndex = context.reportFailures ? addConst(
|
||||
"peg$classExpectation("
|
||||
|
@ -690,6 +711,7 @@ function generateBytecode( ast ) {
|
|||
return buildSequence(
|
||||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [],
|
||||
buildCondition(
|
||||
match,
|
||||
[ op.MATCH_REGEXP, regexpIndex ],
|
||||
[ op.ACCEPT_N, 1 ],
|
||||
[ op.PUSH_FAILED ]
|
||||
|
@ -708,6 +730,7 @@ function generateBytecode( ast ) {
|
|||
return buildSequence(
|
||||
context.reportFailures ? [ op.EXPECT, expectedIndex ] : [],
|
||||
buildCondition(
|
||||
node.match|0,
|
||||
[ op.MATCH_ANY ],
|
||||
[ op.ACCEPT_N, 1 ],
|
||||
[ op.PUSH_FAILED ]
|
||||
|
|
173
lib/compiler/passes/inference-match-result.js
Normal file
173
lib/compiler/passes/inference-match-result.js
Normal file
|
@ -0,0 +1,173 @@
|
|||
"use strict";
|
||||
|
||||
const visitor = require( "../visitor" );
|
||||
const asts = require( "../asts" );
|
||||
const GrammarError = require( "../../grammar-error" );
|
||||
|
||||
// Inference match result of the rule. Can be:
|
||||
// -1: negative result, always fails
|
||||
// 0: neutral result, may be fail, may be match
|
||||
// 1: positive result, always match
|
||||
function inferenceMatchResult( ast ) {
|
||||
|
||||
let inference;
|
||||
function sometimesMatch( node ) {
|
||||
|
||||
node.match = 0;
|
||||
|
||||
return node.match;
|
||||
|
||||
}
|
||||
function alwaysMatch( node ) {
|
||||
|
||||
inference( node.expression );
|
||||
|
||||
node.match = 1;
|
||||
|
||||
return node.match;
|
||||
|
||||
}
|
||||
|
||||
function inferenceExpression( node ) {
|
||||
|
||||
node.match = inference( node.expression );
|
||||
|
||||
return node.match;
|
||||
|
||||
}
|
||||
function inferenceElements( elements, forChoice ) {
|
||||
|
||||
const length = elements.length;
|
||||
let always = 0;
|
||||
let never = 0;
|
||||
|
||||
for ( let i = 0; i < length; ++i ) {
|
||||
|
||||
const result = inference( elements[ i ] );
|
||||
|
||||
if ( result > 0 ) {
|
||||
|
||||
++always;
|
||||
|
||||
}
|
||||
if ( result < 0 ) {
|
||||
|
||||
++never;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( always === length ) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
if ( forChoice ) {
|
||||
|
||||
return never === length ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
return never > 0 ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
inference = visitor.build( {
|
||||
rule( node ) {
|
||||
|
||||
let oldResult;
|
||||
let count = 0;
|
||||
|
||||
if ( typeof node.match === "undefined" ) {
|
||||
|
||||
node.match = 0;
|
||||
do {
|
||||
|
||||
oldResult = node.match;
|
||||
node.match = inference( node.expression );
|
||||
// 6 == 3! -- permutations count for all transitions from one match
|
||||
// state to another.
|
||||
// After 6 iterations the cycle with guarantee begins
|
||||
// istanbul ignore next
|
||||
if ( ++count > 6 ) {
|
||||
|
||||
throw new GrammarError(
|
||||
"Infinity cycle detected when trying evaluate node match result",
|
||||
node.location
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
} while ( oldResult !== node.match );
|
||||
|
||||
}
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
named: inferenceExpression,
|
||||
choice( node ) {
|
||||
|
||||
node.match = inferenceElements( node.alternatives, true );
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
action: inferenceExpression,
|
||||
sequence( node ) {
|
||||
|
||||
node.match = inferenceElements( node.elements, false );
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
labeled: inferenceExpression,
|
||||
text: inferenceExpression,
|
||||
simple_and: inferenceExpression,
|
||||
simple_not( node ) {
|
||||
|
||||
node.match = -inference( node.expression );
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
optional: alwaysMatch,
|
||||
zero_or_more: alwaysMatch,
|
||||
one_or_more: inferenceExpression,
|
||||
group: inferenceExpression,
|
||||
semantic_and: sometimesMatch,
|
||||
semantic_not: sometimesMatch,
|
||||
rule_ref( node ) {
|
||||
|
||||
const rule = asts.findRule( ast, node.name );
|
||||
node.match = inference( rule );
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
literal( node ) {
|
||||
|
||||
// Empty literal always match on any input
|
||||
node.match = node.value.length === 0 ? 1 : 0;
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
class( node ) {
|
||||
|
||||
// Empty character class never match on any input
|
||||
node.match = node.parts.length === 0 ? -1 : 0;
|
||||
|
||||
return node.match;
|
||||
|
||||
},
|
||||
// |any| not match on empty input
|
||||
any: sometimesMatch
|
||||
} );
|
||||
|
||||
inference( ast );
|
||||
|
||||
}
|
||||
|
||||
module.exports = inferenceMatchResult;
|
234
lib/parser.js
234
lib/parser.js
|
@ -645,42 +645,30 @@ function peg$parse(input, options) {
|
|||
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parse__();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$currPos;
|
||||
s3 = peg$parseInitializer();
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s3 = [s3, s4];
|
||||
s2 = s3;
|
||||
} else {
|
||||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
s4 = peg$currPos;
|
||||
s5 = peg$parseRule();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parse__();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s5 = [s5, s6];
|
||||
s4 = s5;
|
||||
} else {
|
||||
peg$currPos = s4;
|
||||
s4 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s4;
|
||||
s4 = peg$FAILED;
|
||||
}
|
||||
if (s4 !== peg$FAILED) {
|
||||
while (s4 !== peg$FAILED) {
|
||||
s3.push(s4);
|
||||
|
@ -688,17 +676,12 @@ function peg$parse(input, options) {
|
|||
s5 = peg$parseRule();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parse__();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s5 = [s5, s6];
|
||||
s4 = s5;
|
||||
} else {
|
||||
peg$currPos = s4;
|
||||
s4 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s4;
|
||||
s4 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
|
@ -710,14 +693,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -751,26 +726,19 @@ function peg$parse(input, options) {
|
|||
s1 = peg$parseIdentifierName();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parseStringLiteral();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parse__();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s4 = [s4, s5];
|
||||
s3 = s4;
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
if (s3 === peg$FAILED) {
|
||||
s3 = null;
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c3); }
|
||||
if (input.charCodeAt(peg$currPos) === 61) {
|
||||
s4 = peg$c2;
|
||||
|
@ -780,7 +748,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parse__();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parseChoiceExpression();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parseEOS();
|
||||
|
@ -803,18 +770,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -828,7 +783,6 @@ function peg$parse(input, options) {
|
|||
s2 = [];
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c6); }
|
||||
if (input.charCodeAt(peg$currPos) === 47) {
|
||||
s5 = peg$c5;
|
||||
|
@ -838,7 +792,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parse__();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parseActionExpression();
|
||||
if (s7 !== peg$FAILED) {
|
||||
s4 = [s4, s5, s6, s7];
|
||||
|
@ -851,19 +804,10 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c6); }
|
||||
if (input.charCodeAt(peg$currPos) === 47) {
|
||||
s5 = peg$c5;
|
||||
|
@ -873,7 +817,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parse__();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parseActionExpression();
|
||||
if (s7 !== peg$FAILED) {
|
||||
s4 = [s4, s5, s6, s7];
|
||||
|
@ -886,26 +829,13 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c7(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -918,7 +848,6 @@ function peg$parse(input, options) {
|
|||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$currPos;
|
||||
s3 = peg$parse__();
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parseCodeBlock();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s3 = [s3, s4];
|
||||
|
@ -927,24 +856,15 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c8(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -958,7 +878,6 @@ function peg$parse(input, options) {
|
|||
s2 = [];
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parseLabeledExpression();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s4 = [s4, s5];
|
||||
|
@ -967,15 +886,10 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parseLabeledExpression();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s4 = [s4, s5];
|
||||
|
@ -984,22 +898,13 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c9(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -1011,7 +916,6 @@ function peg$parse(input, options) {
|
|||
s1 = peg$parseIdentifier();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c11); }
|
||||
if (input.charCodeAt(peg$currPos) === 58) {
|
||||
s3 = peg$c10;
|
||||
|
@ -1021,7 +925,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parsePrefixedExpression();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
|
@ -1038,14 +941,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parsePrefixedExpression();
|
||||
}
|
||||
|
@ -1060,7 +955,6 @@ function peg$parse(input, options) {
|
|||
s1 = peg$parsePrefixedOperator();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseSuffixedExpression();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
|
@ -1073,10 +967,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parseSuffixedExpression();
|
||||
}
|
||||
|
@ -1123,7 +1013,6 @@ function peg$parse(input, options) {
|
|||
s1 = peg$parsePrimaryExpression();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseSuffixedOperator();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
|
@ -1136,10 +1025,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parsePrimaryExpression();
|
||||
}
|
||||
|
@ -1202,11 +1087,9 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseChoiceExpression();
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c30); }
|
||||
if (input.charCodeAt(peg$currPos) === 41) {
|
||||
s5 = peg$c29;
|
||||
|
@ -1229,14 +1112,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1256,26 +1131,19 @@ function peg$parse(input, options) {
|
|||
peg$begin();
|
||||
s3 = peg$currPos;
|
||||
s4 = peg$parse__();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$currPos;
|
||||
s6 = peg$parseStringLiteral();
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parse__();
|
||||
if (s7 !== peg$FAILED) {
|
||||
s6 = [s6, s7];
|
||||
s5 = s6;
|
||||
} else {
|
||||
peg$currPos = s5;
|
||||
s5 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s5;
|
||||
s5 = peg$FAILED;
|
||||
}
|
||||
if (s5 === peg$FAILED) {
|
||||
s5 = null;
|
||||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c3); }
|
||||
if (input.charCodeAt(peg$currPos) === 61) {
|
||||
s6 = peg$c2;
|
||||
|
@ -1290,14 +1158,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
peg$end(true);
|
||||
if (s3 === peg$FAILED) {
|
||||
s2 = undefined;
|
||||
|
@ -1327,7 +1187,6 @@ function peg$parse(input, options) {
|
|||
s1 = peg$parseSemanticPredicateOperator();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse__();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseCodeBlock();
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
|
@ -1340,10 +1199,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -1593,7 +1448,6 @@ function peg$parse(input, options) {
|
|||
s3 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.substr(peg$currPos, 2) === peg$c52) {
|
||||
s3 = peg$c52;
|
||||
peg$currPos += 2;
|
||||
|
@ -1611,10 +1465,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -1701,7 +1551,6 @@ function peg$parse(input, options) {
|
|||
s3 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c54); }
|
||||
if (input.substr(peg$currPos, 2) === peg$c52) {
|
||||
s3 = peg$c52;
|
||||
|
@ -1720,10 +1569,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -1792,17 +1637,12 @@ function peg$parse(input, options) {
|
|||
s3 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s1 = [s1, s2];
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -1852,17 +1692,12 @@ function peg$parse(input, options) {
|
|||
s2.push(s3);
|
||||
s3 = peg$parseIdentifierPart();
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c59(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
peg$silentFails--;
|
||||
|
||||
return s0;
|
||||
|
@ -2140,17 +1975,12 @@ function peg$parse(input, options) {
|
|||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c71(s1, s2);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
peg$silentFails--;
|
||||
|
||||
return s0;
|
||||
|
@ -2175,7 +2005,6 @@ function peg$parse(input, options) {
|
|||
s2.push(s3);
|
||||
s3 = peg$parseDoubleStringCharacter();
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 34) {
|
||||
s3 = peg$c73;
|
||||
peg$currPos++;
|
||||
|
@ -2193,10 +2022,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 39) {
|
||||
|
@ -2212,7 +2037,6 @@ function peg$parse(input, options) {
|
|||
s2.push(s3);
|
||||
s3 = peg$parseSingleStringCharacter();
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 39) {
|
||||
s3 = peg$c75;
|
||||
peg$currPos++;
|
||||
|
@ -2230,10 +2054,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
peg$silentFails--;
|
||||
|
||||
|
@ -2406,7 +2226,6 @@ function peg$parse(input, options) {
|
|||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
s4 = peg$parseClassCharacterRange();
|
||||
if (s4 === peg$FAILED) {
|
||||
|
@ -2419,7 +2238,6 @@ function peg$parse(input, options) {
|
|||
s4 = peg$parseClassCharacter();
|
||||
}
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 93) {
|
||||
s4 = peg$c80;
|
||||
peg$currPos++;
|
||||
|
@ -2436,7 +2254,6 @@ function peg$parse(input, options) {
|
|||
if (s5 === peg$FAILED) {
|
||||
s5 = null;
|
||||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$c81(s2, s3, s5);
|
||||
} else {
|
||||
|
@ -2447,18 +2264,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
peg$silentFails--;
|
||||
|
||||
return s0;
|
||||
|
@ -2994,7 +2799,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parseCode();
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 125) {
|
||||
s3 = peg$c111;
|
||||
peg$currPos++;
|
||||
|
@ -3012,10 +2816,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 123) {
|
||||
|
@ -3116,7 +2916,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parseCode();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 125) {
|
||||
s5 = peg$c111;
|
||||
peg$currPos++;
|
||||
|
@ -3134,10 +2933,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
while (s2 !== peg$FAILED) {
|
||||
s1.push(s2);
|
||||
|
@ -3217,7 +3012,6 @@ function peg$parse(input, options) {
|
|||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parseCode();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 125) {
|
||||
s5 = peg$c111;
|
||||
peg$currPos++;
|
||||
|
@ -3235,17 +3029,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s2;
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s0 = input.substring(s0, peg$currPos);
|
||||
} else {
|
||||
s0 = s1;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
@ -4784,7 +4570,6 @@ function peg$parse(input, options) {
|
|||
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parse__();
|
||||
if (s1 !== peg$FAILED) {
|
||||
if (peg$silentFails === 0) { peg$expect(peg$c209); }
|
||||
if (input.charCodeAt(peg$currPos) === 59) {
|
||||
s2 = peg$c208;
|
||||
|
@ -4799,19 +4584,13 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parse_();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parseSingleLineComment();
|
||||
if (s2 === peg$FAILED) {
|
||||
s2 = null;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseLineTerminatorSequence();
|
||||
if (s3 !== peg$FAILED) {
|
||||
s1 = [s1, s2, s3];
|
||||
|
@ -4820,18 +4599,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parse__();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parseEOF();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s1 = [s1, s2];
|
||||
|
@ -4840,10 +4610,6 @@ function peg$parse(input, options) {
|
|||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
4
lib/typings/api.d.ts
vendored
4
lib/typings/api.d.ts
vendored
|
@ -98,6 +98,10 @@ declare namespace peg {
|
|||
|
||||
reportFailures?: boolean;
|
||||
|
||||
// Added by inference-match-result pass
|
||||
|
||||
match?: number;
|
||||
|
||||
}
|
||||
|
||||
interface Named extends INode {
|
||||
|
|
164
test/spec/unit/compiler/passes/inference-match-result.spec.js
Normal file
164
test/spec/unit/compiler/passes/inference-match-result.spec.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
"use strict";
|
||||
|
||||
const chai = require( "chai" );
|
||||
const helpers = require( "./helpers" );
|
||||
const pass = require( "pegjs-dev" ).compiler.passes.generate.inferenceMatchResult;
|
||||
|
||||
chai.use( helpers );
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe( "compiler pass |inferenceMatchResult|", function () {
|
||||
|
||||
it( "calculate |match| property for |any| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = . ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |literal| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = '' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = ''i ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = 'a' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = 'a'i ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |class| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = [] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = []i ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [a] ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [a]i ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [a-b] ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [a-b]i ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |sequence| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' 'b' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' '' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' 'b' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' '' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' [] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] 'b' ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] [] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |choice| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' / 'b' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' / '' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' / 'b' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' / '' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = 'a' / [] ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] / 'b' ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] / [] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for predicates correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = &. ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = &'' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = &[] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = !. ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = !'' ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = ![] ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = &{ code } ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = !{ code } ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |text| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = $. ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = $'' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = $[] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |action| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = . { code }", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' { code }", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] { code }", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |labeled| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = a:. ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = a:'' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = a:[] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |named| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start 'start' = . ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start 'start' = '' ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start 'start' = [] ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |optional| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = .? ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = ''? ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = []? ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |zero_or_more| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = .* ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = ''* ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = []* ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |one_or_more| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST( "start = .+ ", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = ''+ ", { rules: [ { match: 1 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = []+ ", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
it( "calculate |match| property for |rule_ref| correctly", function () {
|
||||
|
||||
expect( pass ).to.changeAST(
|
||||
[ "start = end", "end = . " ].join( "\n" ),
|
||||
{ rules: [ { match: 0 }, { match: 0 } ] },
|
||||
{}, {}
|
||||
);
|
||||
expect( pass ).to.changeAST(
|
||||
[ "start = end", "end = ''" ].join( "\n" ),
|
||||
{ rules: [ { match: 1 }, { match: 1 } ] },
|
||||
{}, {}
|
||||
);
|
||||
expect( pass ).to.changeAST(
|
||||
[ "start = end", "end = []" ].join( "\n" ),
|
||||
{ rules: [ { match: -1 }, { match: -1 } ] },
|
||||
{}, {}
|
||||
);
|
||||
|
||||
expect( pass ).to.changeAST( "start = . start", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = '' start", { rules: [ { match: 0 } ] }, {}, {} );
|
||||
expect( pass ).to.changeAST( "start = [] start", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
expect( pass ).to.changeAST( "start = . start []", { rules: [ { match: -1 } ] }, {}, {} );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
Loading…
Reference in a new issue