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,
|
rule: checkExpression,
|
||||||
choice: checkSubnodes("alternatives"),
|
choice: checkSubnodes("alternatives"),
|
||||||
sequence: checkSubnodes("elements"),
|
sequence: checkSubnodes("elements"),
|
||||||
|
labeled: checkExpression,
|
||||||
and_predicate: checkExpression,
|
and_predicate: checkExpression,
|
||||||
not_predicate: checkExpression,
|
not_predicate: checkExpression,
|
||||||
optional: checkExpression,
|
optional: checkExpression,
|
||||||
|
@ -340,6 +341,7 @@ PEG.Compiler = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
labeled: checkExpression,
|
||||||
and_predicate: checkExpression,
|
and_predicate: checkExpression,
|
||||||
not_predicate: checkExpression,
|
not_predicate: checkExpression,
|
||||||
optional: checkExpression,
|
optional: checkExpression,
|
||||||
|
@ -406,6 +408,7 @@ PEG.Compiler = {
|
||||||
rule: replaceInExpression,
|
rule: replaceInExpression,
|
||||||
choice: replaceInSubnodes("alternatives"),
|
choice: replaceInSubnodes("alternatives"),
|
||||||
sequence: replaceInSubnodes("elements"),
|
sequence: replaceInSubnodes("elements"),
|
||||||
|
labeled: replaceInExpression,
|
||||||
and_predicate: replaceInExpression,
|
and_predicate: replaceInExpression,
|
||||||
not_predicate: replaceInExpression,
|
not_predicate: replaceInExpression,
|
||||||
optional: 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) {
|
and_predicate: function(node, resultVar) {
|
||||||
var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
|
var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
|
||||||
var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
|
var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
|
||||||
|
|
2208
lib/metagrammar.js
2208
lib/metagrammar.js
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ choice
|
||||||
}
|
}
|
||||||
|
|
||||||
sequence
|
sequence
|
||||||
= prefixed* action {
|
= labeled* action {
|
||||||
var expression = $1.length != 1
|
var expression = $1.length != 1
|
||||||
? {
|
? {
|
||||||
type: "sequence",
|
type: "sequence",
|
||||||
|
@ -48,7 +48,7 @@ sequence
|
||||||
action: $2
|
action: $2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/ prefixed* {
|
/ labeled* {
|
||||||
return $1.length != 1
|
return $1.length != 1
|
||||||
? {
|
? {
|
||||||
type: "sequence",
|
type: "sequence",
|
||||||
|
@ -57,6 +57,16 @@ sequence
|
||||||
: $1[0];
|
: $1[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labeled
|
||||||
|
= identifier colon prefixed {
|
||||||
|
return {
|
||||||
|
type: "labeled",
|
||||||
|
label: $1,
|
||||||
|
expression: $3
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/ prefixed
|
||||||
|
|
||||||
prefixed
|
prefixed
|
||||||
= and suffixed { return { type: "and_predicate", expression: $2 }; }
|
= and suffixed { return { type: "and_predicate", expression: $2 }; }
|
||||||
/ not suffixed { return { type: "not_predicate", expression: $2 }; }
|
/ not suffixed { return { type: "not_predicate", expression: $2 }; }
|
||||||
|
@ -90,6 +100,7 @@ nonBraceCharacter
|
||||||
= [^{}]
|
= [^{}]
|
||||||
|
|
||||||
equals = "=" __ { return $1; }
|
equals = "=" __ { return $1; }
|
||||||
|
colon = ":" __ { return $1; }
|
||||||
slash = "/" __ { return $1; }
|
slash = "/" __ { return $1; }
|
||||||
and = "&" __ { return $1; }
|
and = "&" __ { return $1; }
|
||||||
not = "!" __ { return $1; }
|
not = "!" __ { return $1; }
|
||||||
|
|
|
@ -206,6 +206,7 @@ test("buildParser reports missing referenced rules", function() {
|
||||||
'start = "a" / "b" / missing',
|
'start = "a" / "b" / missing',
|
||||||
'start = missing "a" "b"',
|
'start = missing "a" "b"',
|
||||||
'start = "a" "b" missing',
|
'start = "a" "b" missing',
|
||||||
|
'start = label:missing',
|
||||||
'start = &missing',
|
'start = &missing',
|
||||||
'start = !missing',
|
'start = !missing',
|
||||||
'start = missing?',
|
'start = missing?',
|
||||||
|
@ -230,6 +231,7 @@ test("buildParser reports left recursion", function() {
|
||||||
'start = start / "a" / "b"',
|
'start = start / "a" / "b"',
|
||||||
'start = "a" / "b" / start',
|
'start = "a" / "b" / start',
|
||||||
'start = start "a" "b"',
|
'start = start "a" "b"',
|
||||||
|
'start = label:start',
|
||||||
'start = &start',
|
'start = &start',
|
||||||
'start = !start',
|
'start = !start',
|
||||||
'start = start?',
|
'start = start?',
|
||||||
|
@ -289,6 +291,12 @@ test("sequences", function() {
|
||||||
parses(posTestParser, "a", "a");
|
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() {
|
test("and predicate", function() {
|
||||||
var parser = PEG.buildParser('start = "a" &"b" "b"');
|
var parser = PEG.buildParser('start = "a" &"b" "b"');
|
||||||
parses(parser, "ab", ["a", "", "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) {
|
function nodeWithExpressionConstructor(type) {
|
||||||
return function(expression) {
|
return function(expression) {
|
||||||
return {
|
return {
|
||||||
|
@ -100,12 +108,12 @@ var literalIjkl = literal("ijkl");
|
||||||
|
|
||||||
var optionalLiteral = optional(literalAbcd);
|
var optionalLiteral = optional(literalAbcd);
|
||||||
|
|
||||||
var notAbcd = notPredicate(literalAbcd);
|
var labeledAbcd = labeled("a", literalAbcd);
|
||||||
var notEfgh = notPredicate(literalEfgh);
|
var labeledEfgh = labeled("e", literalEfgh);
|
||||||
var notIjkl = notPredicate(literalIjkl);
|
var labeledIjkl = labeled("i", literalIjkl);
|
||||||
|
|
||||||
var sequenceEmpty = sequence([]);
|
var sequenceEmpty = sequence([]);
|
||||||
var sequenceNots = sequence([notAbcd, notEfgh, notIjkl]);
|
var sequenceLabeleds = sequence([labeledAbcd, labeledEfgh, labeledIjkl]);
|
||||||
var sequenceLiterals = sequence([literalAbcd, literalEfgh, literalIjkl]);
|
var sequenceLiterals = sequence([literalAbcd, literalEfgh, literalIjkl]);
|
||||||
|
|
||||||
var choiceLiterals = choice([literalAbcd, literalEfgh, literalIjkl]);
|
var choiceLiterals = choice([literalAbcd, literalEfgh, literalIjkl]);
|
||||||
|
@ -194,19 +202,31 @@ test("parses sequence", function() {
|
||||||
oneRuleGrammar(action(sequenceEmpty, " code "))
|
oneRuleGrammar(action(sequenceEmpty, " code "))
|
||||||
);
|
);
|
||||||
grammarParserParses(
|
grammarParserParses(
|
||||||
'start = !"abcd" { code }',
|
'start = a:"abcd" { code }',
|
||||||
oneRuleGrammar(action(notAbcd, " code "))
|
oneRuleGrammar(action(labeledAbcd, " code "))
|
||||||
);
|
);
|
||||||
grammarParserParses(
|
grammarParserParses(
|
||||||
'start = !"abcd" !"efgh" !"ijkl" { code }',
|
'start = a:"abcd" e:"efgh" i:"ijkl" { code }',
|
||||||
oneRuleGrammar(action(sequenceNots, " code "))
|
oneRuleGrammar(action(sequenceLabeleds, " code "))
|
||||||
);
|
);
|
||||||
|
|
||||||
grammarParserParses('start = ', oneRuleGrammar(sequenceEmpty));
|
grammarParserParses('start = ', oneRuleGrammar(sequenceEmpty));
|
||||||
grammarParserParses('start = !"abcd"', oneRuleGrammar(notAbcd));
|
grammarParserParses('start = a:"abcd"', oneRuleGrammar(labeledAbcd));
|
||||||
grammarParserParses(
|
grammarParserParses(
|
||||||
'start = !"abcd" !"efgh" !"ijkl"',
|
'start = a:"abcd" e:"efgh" i:"ijkl"',
|
||||||
oneRuleGrammar(sequenceNots)
|
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