Browse Source

PEG.js grammar: Make rules with operators more generic

redux
David Majda 8 years ago
parent
commit
6f2510e49e
  1. 1489
      lib/parser.js
  2. 28
      spec/parser.spec.js
  3. 74
      src/parser.pegjs

1489
lib/parser.js
File diff suppressed because it is too large
View File

28
spec/parser.spec.js

@ -292,24 +292,30 @@ describe("PEG.js grammar parser", function() {
/* Canonical PrefixedExpression is "!\"abcd\"". */
it("parses PrefixedExpression", function() {
expect('start = $"abcd"?' ).toParseAs(oneRuleGrammar(textOptionalLiteral));
expect('start = $\n"abcd"?' ).toParseAs(oneRuleGrammar(textOptionalLiteral));
expect('start = &"abcd"?' ).toParseAs(oneRuleGrammar(simpleAndOptionalLiteral));
expect('start = &\n"abcd"?' ).toParseAs(oneRuleGrammar(simpleAndOptionalLiteral));
expect('start = !"abcd"?' ).toParseAs(oneRuleGrammar(simpleNotOptionalLiteral));
expect('start = !\n"abcd"?' ).toParseAs(oneRuleGrammar(simpleNotOptionalLiteral));
expect('start = "abcd"?' ).toParseAs(oneRuleGrammar(optionalLiteral));
});
/* Canonical PrefixedOperator is "!". */
it("parses PrefixedOperator", function() {
expect('start = $"abcd"?' ).toParseAs(oneRuleGrammar(textOptionalLiteral));
expect('start = &"abcd"?' ).toParseAs(oneRuleGrammar(simpleAndOptionalLiteral));
expect('start = !"abcd"?' ).toParseAs(oneRuleGrammar(simpleNotOptionalLiteral));
});
/* Canonical SuffixedExpression is "\"abcd\"?". */
it("parses SuffixedExpression", function() {
expect('start = "abcd"?' ).toParseAs(oneRuleGrammar(optionalLiteral));
expect('start = "abcd"\n?').toParseAs(oneRuleGrammar(optionalLiteral));
expect('start = "abcd"' ).toParseAs(literalGrammar("abcd"));
});
/* Canonical SuffixedOperator is "?". */
it("parses SuffixedExpression", function() {
expect('start = "abcd"?' ).toParseAs(oneRuleGrammar(optionalLiteral));
expect('start = "abcd"*' ).toParseAs(oneRuleGrammar(zeroOrMoreLiteral));
expect('start = "abcd"\n*').toParseAs(oneRuleGrammar(zeroOrMoreLiteral));
expect('start = "abcd"+' ).toParseAs(oneRuleGrammar(oneOrMoreLiteral));
expect('start = "abcd"\n+').toParseAs(oneRuleGrammar(oneOrMoreLiteral));
expect('start = "abcd"' ).toParseAs(literalGrammar("abcd"));
});
/* Canonical PrimaryExpression is "\"abcd\"". */
@ -331,12 +337,16 @@ describe("PEG.js grammar parser", function() {
/* Canonical SemanticPredicateExpression is "\"abcd\"". */
it("parses SemanticPredicateExpression", function() {
expect('start = &{ code }' ).toParseAs(oneRuleGrammar(semanticAnd));
expect('start = &\n{ code }').toParseAs(oneRuleGrammar(semanticAnd));
expect('start = !{ code }' ).toParseAs(oneRuleGrammar(semanticNot));
expect('start = !\n{ code }').toParseAs(oneRuleGrammar(semanticNot));
});
/* Canonical SemanticPredicateOperator is "!". */
it("parses SemanticPredicateExpression", function() {
expect('start = &{ code }').toParseAs(oneRuleGrammar(semanticAnd));
expect('start = !{ code }').toParseAs(oneRuleGrammar(semanticNot));
});
/* The SourceCharacter rule is not tested. */
/* Canonical WhiteSpace is " ". */

74
src/parser.pegjs

@ -12,6 +12,23 @@
*/
{
var OPS_TO_PREFIXED_TYPES = {
"$": "text",
"&": "simple_and",
"!": "simple_not"
};
var OPS_TO_SUFFIXED_TYPES = {
"?": "optional",
"*": "zero_or_more",
"+": "one_or_more"
};
var OPS_TO_SEMANTIC_PREDICATE_TYPES = {
"&": "semantic_and",
"!": "semantic_not"
};
function extractOptional(optional, index) {
return optional ? optional[index] : null;
}
@ -101,47 +118,27 @@ LabeledExpression
/ PrefixedExpression
PrefixedExpression
= "$" __ expression:SuffixedExpression {
return {
type: "text",
expression: expression
};
}
/ "&" __ expression:SuffixedExpression {
return {
type: "simple_and",
expression: expression
};
}
/ "!" __ expression:SuffixedExpression {
return {
type: "simple_not",
expression: expression
};
= operator:PrefixedOperator __ expression:SuffixedExpression {
return { type: OPS_TO_PREFIXED_TYPES[operator], expression: expression };
}
/ SuffixedExpression
PrefixedOperator
= "$"
/ "&"
/ "!"
SuffixedExpression
= expression:PrimaryExpression __ "?" {
return {
type: "optional",
expression: expression
};
}
/ expression:PrimaryExpression __ "*" {
return {
type: "zero_or_more",
expression: expression
};
}
/ expression:PrimaryExpression __ "+" {
return {
type: "one_or_more",
expression: expression
};
= expression:PrimaryExpression __ operator:SuffixedOperator {
return { type: OPS_TO_SUFFIXED_TYPES[operator], expression: expression };
}
/ PrimaryExpression
SuffixedOperator
= "?"
/ "*"
/ "+"
PrimaryExpression
= LiteralMatcher
/ CharacterClassMatcher
@ -156,8 +153,13 @@ RuleReferenceExpression
}
SemanticPredicateExpression
= "&" __ code:CodeBlock { return { type: "semantic_and", code: code }; }
/ "!" __ code:CodeBlock { return { type: "semantic_not", code: code }; }
= operator:SemanticPredicateOperator __ code:CodeBlock {
return { type: OPS_TO_SEMANTIC_PREDICATE_TYPES[operator], code: code };
}
SemanticPredicateOperator
= "&"
/ "!"
/* "Lexical" elements */

Loading…
Cancel
Save