Allow labeled expressions in the metagrammar (without any meaning yet)
This commit is contained in:
parent
409ddf2ae8
commit
52704593cd
|
@ -275,6 +275,7 @@ PEG.Compiler = {
|
|||
rule: checkExpression,
|
||||
choice: checkSubnodes("alternatives"),
|
||||
sequence: checkSubnodes("elements"),
|
||||
labeled: checkExpression,
|
||||
and_predicate: checkExpression,
|
||||
not_predicate: checkExpression,
|
||||
optional: checkExpression,
|
||||
|
@ -340,6 +341,7 @@ PEG.Compiler = {
|
|||
}
|
||||
},
|
||||
|
||||
labeled: checkExpression,
|
||||
and_predicate: checkExpression,
|
||||
not_predicate: checkExpression,
|
||||
optional: checkExpression,
|
||||
|
@ -406,6 +408,7 @@ PEG.Compiler = {
|
|||
rule: replaceInExpression,
|
||||
choice: replaceInSubnodes("alternatives"),
|
||||
sequence: replaceInSubnodes("elements"),
|
||||
labeled: replaceInExpression,
|
||||
and_predicate: replaceInExpression,
|
||||
not_predicate: replaceInExpression,
|
||||
optional: replaceInExpression,
|
||||
|
@ -596,6 +599,10 @@ PEG.Compiler = {
|
|||
);
|
||||
},
|
||||
|
||||
labeled: function(node, resultVar) {
|
||||
return PEG.Compiler.compileNode(node.expression, resultVar);
|
||||
},
|
||||
|
||||
and_predicate: function(node, resultVar) {
|
||||
var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
|
||||
var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
|
||||
|
|
2238
lib/metagrammar.js
2238
lib/metagrammar.js
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ choice
|
|||
}
|
||||
|
||||
sequence
|
||||
= prefixed* action {
|
||||
= labeled* action {
|
||||
var expression = $1.length != 1
|
||||
? {
|
||||
type: "sequence",
|
||||
|
@ -48,7 +48,7 @@ sequence
|
|||
action: $2
|
||||
};
|
||||
}
|
||||
/ prefixed* {
|
||||
/ labeled* {
|
||||
return $1.length != 1
|
||||
? {
|
||||
type: "sequence",
|
||||
|
@ -57,6 +57,16 @@ sequence
|
|||
: $1[0];
|
||||
}
|
||||
|
||||
labeled
|
||||
= identifier colon prefixed {
|
||||
return {
|
||||
type: "labeled",
|
||||
label: $1,
|
||||
expression: $3
|
||||
};
|
||||
}
|
||||
/ prefixed
|
||||
|
||||
prefixed
|
||||
= and suffixed { return { type: "and_predicate", expression: $2 }; }
|
||||
/ not suffixed { return { type: "not_predicate", expression: $2 }; }
|
||||
|
@ -90,6 +100,7 @@ nonBraceCharacter
|
|||
= [^{}]
|
||||
|
||||
equals = "=" __ { return $1; }
|
||||
colon = ":" __ { return $1; }
|
||||
slash = "/" __ { return $1; }
|
||||
and = "&" __ { return $1; }
|
||||
not = "!" __ { return $1; }
|
||||
|
|
|
@ -206,6 +206,7 @@ test("buildParser reports missing referenced rules", function() {
|
|||
'start = "a" / "b" / missing',
|
||||
'start = missing "a" "b"',
|
||||
'start = "a" "b" missing',
|
||||
'start = label:missing',
|
||||
'start = &missing',
|
||||
'start = !missing',
|
||||
'start = missing?',
|
||||
|
@ -230,6 +231,7 @@ test("buildParser reports left recursion", function() {
|
|||
'start = start / "a" / "b"',
|
||||
'start = "a" / "b" / start',
|
||||
'start = start "a" "b"',
|
||||
'start = label:start',
|
||||
'start = &start',
|
||||
'start = !start',
|
||||
'start = start?',
|
||||
|
@ -289,6 +291,12 @@ test("sequences", function() {
|
|||
parses(posTestParser, "a", "a");
|
||||
});
|
||||
|
||||
test("labels", function() {
|
||||
var parser = PEG.buildParser('start = label:"a"');
|
||||
parses(parser, "a", "a");
|
||||
doesNotParse(parser, "b");
|
||||
});
|
||||
|
||||
test("and predicate", function() {
|
||||
var parser = PEG.buildParser('start = "a" &"b" "b"');
|
||||
parses(parser, "ab", ["a", "", "b"]);
|
||||
|
|
|
@ -43,6 +43,14 @@ function sequence(elements) {
|
|||
};
|
||||
}
|
||||
|
||||
function labeled(label, expression) {
|
||||
return {
|
||||
type: "labeled",
|
||||
label: label,
|
||||
expression: expression
|
||||
};
|
||||
}
|
||||
|
||||
function nodeWithExpressionConstructor(type) {
|
||||
return function(expression) {
|
||||
return {
|
||||
|
@ -100,12 +108,12 @@ var literalIjkl = literal("ijkl");
|
|||
|
||||
var optionalLiteral = optional(literalAbcd);
|
||||
|
||||
var notAbcd = notPredicate(literalAbcd);
|
||||
var notEfgh = notPredicate(literalEfgh);
|
||||
var notIjkl = notPredicate(literalIjkl);
|
||||
var labeledAbcd = labeled("a", literalAbcd);
|
||||
var labeledEfgh = labeled("e", literalEfgh);
|
||||
var labeledIjkl = labeled("i", literalIjkl);
|
||||
|
||||
var sequenceEmpty = sequence([]);
|
||||
var sequenceNots = sequence([notAbcd, notEfgh, notIjkl]);
|
||||
var sequenceLabeleds = sequence([labeledAbcd, labeledEfgh, labeledIjkl]);
|
||||
var sequenceLiterals = sequence([literalAbcd, literalEfgh, literalIjkl]);
|
||||
|
||||
var choiceLiterals = choice([literalAbcd, literalEfgh, literalIjkl]);
|
||||
|
@ -194,19 +202,31 @@ test("parses sequence", function() {
|
|||
oneRuleGrammar(action(sequenceEmpty, " code "))
|
||||
);
|
||||
grammarParserParses(
|
||||
'start = !"abcd" { code }',
|
||||
oneRuleGrammar(action(notAbcd, " code "))
|
||||
'start = a:"abcd" { code }',
|
||||
oneRuleGrammar(action(labeledAbcd, " code "))
|
||||
);
|
||||
grammarParserParses(
|
||||
'start = !"abcd" !"efgh" !"ijkl" { code }',
|
||||
oneRuleGrammar(action(sequenceNots, " code "))
|
||||
'start = a:"abcd" e:"efgh" i:"ijkl" { code }',
|
||||
oneRuleGrammar(action(sequenceLabeleds, " code "))
|
||||
);
|
||||
|
||||
grammarParserParses('start = ', oneRuleGrammar(sequenceEmpty));
|
||||
grammarParserParses('start = !"abcd"', oneRuleGrammar(notAbcd));
|
||||
grammarParserParses('start = a:"abcd"', oneRuleGrammar(labeledAbcd));
|
||||
grammarParserParses(
|
||||
'start = !"abcd" !"efgh" !"ijkl"',
|
||||
oneRuleGrammar(sequenceNots)
|
||||
'start = a:"abcd" e:"efgh" i:"ijkl"',
|
||||
oneRuleGrammar(sequenceLabeleds)
|
||||
);
|
||||
});
|
||||
|
||||
/* Canonical labeled is "label:\"abcd\"". */
|
||||
test("parses labeled", function() {
|
||||
grammarParserParses(
|
||||
'start = label:!"abcd"',
|
||||
oneRuleGrammar(labeled("label", notPredicate(literalAbcd)))
|
||||
);
|
||||
grammarParserParses(
|
||||
'start = !"abcd"',
|
||||
oneRuleGrammar(notPredicate(literalAbcd))
|
||||
);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue