2011-02-13 12:22:56 +01:00
|
|
|
(function() {
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-08-18 21:07:04 +02:00
|
|
|
module("PEG.parser");
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-06-08 09:15:09 +02:00
|
|
|
function initializer(code) {
|
|
|
|
return {
|
|
|
|
type: "initializer",
|
|
|
|
code: code
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function rule(name, displayName, expression) {
|
|
|
|
return {
|
|
|
|
type: "rule",
|
|
|
|
name: name,
|
|
|
|
displayName: displayName,
|
|
|
|
expression: expression
|
|
|
|
};
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function choice(alternatives) {
|
|
|
|
return {
|
|
|
|
type: "choice",
|
|
|
|
alternatives: alternatives
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function sequence(elements) {
|
|
|
|
return {
|
|
|
|
type: "sequence",
|
|
|
|
elements: elements
|
|
|
|
};
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-05-23 19:29:53 +02:00
|
|
|
function labeled(label, expression) {
|
|
|
|
return {
|
|
|
|
type: "labeled",
|
|
|
|
label: label,
|
|
|
|
expression: expression
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function nodeWithExpressionConstructor(type) {
|
|
|
|
return function(expression) {
|
2010-05-21 18:54:52 +02:00
|
|
|
return {
|
2010-05-21 19:00:00 +02:00
|
|
|
type: type,
|
|
|
|
expression: expression
|
2010-05-21 18:54:52 +02:00
|
|
|
};
|
2011-09-14 12:56:59 +02:00
|
|
|
};
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-06-08 14:49:13 +02:00
|
|
|
function nodeWithCodeConstructor(type) {
|
|
|
|
return function(code) {
|
|
|
|
return {
|
|
|
|
type: type,
|
|
|
|
code: code
|
|
|
|
};
|
2011-09-14 12:56:59 +02:00
|
|
|
};
|
2010-06-08 14:49:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var simpleAnd = nodeWithExpressionConstructor("simple_and");
|
|
|
|
var simpleNot = nodeWithExpressionConstructor("simple_not");
|
|
|
|
|
|
|
|
var semanticAnd = nodeWithCodeConstructor("semantic_and");
|
|
|
|
var semanticNot = nodeWithCodeConstructor("semantic_not");
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var optional = nodeWithExpressionConstructor("optional");
|
|
|
|
var zeroOrMore = nodeWithExpressionConstructor("zero_or_more");
|
|
|
|
var oneOrMore = nodeWithExpressionConstructor("one_or_more");
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-06-07 16:47:17 +02:00
|
|
|
function action(expression, code) {
|
2010-05-21 19:00:00 +02:00
|
|
|
return {
|
|
|
|
type: "action",
|
|
|
|
expression: expression,
|
2010-06-07 16:47:17 +02:00
|
|
|
code: code
|
2010-05-21 18:54:52 +02:00
|
|
|
};
|
2011-09-14 12:56:59 +02:00
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function ruleRef(name) {
|
|
|
|
return {
|
|
|
|
type: "rule_ref",
|
|
|
|
name: name
|
|
|
|
};
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2011-09-30 11:17:47 +02:00
|
|
|
function literal(value, ignoreCase) {
|
2010-05-21 19:00:00 +02:00
|
|
|
return {
|
2011-09-30 11:17:47 +02:00
|
|
|
type: "literal",
|
|
|
|
value: value,
|
|
|
|
ignoreCase: ignoreCase
|
2010-05-21 19:00:00 +02:00
|
|
|
};
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function any() {
|
|
|
|
return { type: "any" };
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2011-09-30 11:45:36 +02:00
|
|
|
function klass(inverted, ignoreCase, parts, rawText) {
|
2010-05-21 19:00:00 +02:00
|
|
|
return {
|
2011-09-30 11:45:36 +02:00
|
|
|
type: "class",
|
|
|
|
inverted: inverted,
|
|
|
|
ignoreCase: ignoreCase,
|
|
|
|
parts: parts,
|
|
|
|
rawText: rawText
|
2010-05-21 19:00:00 +02:00
|
|
|
};
|
|
|
|
}
|
2010-05-21 18:54:52 +02:00
|
|
|
|
2011-09-30 11:17:47 +02:00
|
|
|
var literalAbcd = literal("abcd", false);
|
|
|
|
var literalEfgh = literal("efgh", false);
|
|
|
|
var literalIjkl = literal("ijkl", false);
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var optionalLiteral = optional(literalAbcd);
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-23 19:29:53 +02:00
|
|
|
var labeledAbcd = labeled("a", literalAbcd);
|
|
|
|
var labeledEfgh = labeled("e", literalEfgh);
|
|
|
|
var labeledIjkl = labeled("i", literalIjkl);
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var sequenceEmpty = sequence([]);
|
2010-05-23 19:29:53 +02:00
|
|
|
var sequenceLabeleds = sequence([labeledAbcd, labeledEfgh, labeledIjkl]);
|
2010-05-21 19:00:00 +02:00
|
|
|
var sequenceLiterals = sequence([literalAbcd, literalEfgh, literalIjkl]);
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var choiceLiterals = choice([literalAbcd, literalEfgh, literalIjkl]);
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function oneRuleGrammar(expression) {
|
2010-06-08 09:15:09 +02:00
|
|
|
return {
|
2010-06-08 12:46:16 +02:00
|
|
|
type: "grammar",
|
2010-06-08 09:15:09 +02:00
|
|
|
initializer: null,
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [rule("start", null, expression)],
|
2010-06-08 11:03:28 +02:00
|
|
|
startRule: "start"
|
2010-06-08 09:15:09 +02:00
|
|
|
};
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2011-09-30 11:17:47 +02:00
|
|
|
var simpleGrammar = oneRuleGrammar(literal("abcd", false));
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
function identifierGrammar(identifier) {
|
|
|
|
return oneRuleGrammar(ruleRef(identifier));
|
|
|
|
}
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2011-09-14 12:56:59 +02:00
|
|
|
var literal_ = literal;
|
2010-05-21 19:00:00 +02:00
|
|
|
function literalGrammar(literal) {
|
2011-09-30 11:17:47 +02:00
|
|
|
return oneRuleGrammar(literal_(literal, false));
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-22 10:13:48 +02:00
|
|
|
function classGrammar(inverted, parts, rawText) {
|
2011-09-30 11:45:36 +02:00
|
|
|
return oneRuleGrammar(klass(inverted, false, parts, rawText));
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var anyGrammar = oneRuleGrammar(any());
|
2010-03-13 15:18:57 +01:00
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
var action_ = action;
|
|
|
|
function actionGrammar(action) {
|
2011-09-30 11:17:47 +02:00
|
|
|
return oneRuleGrammar(action_(literal("a", false), action));
|
2010-03-13 15:18:57 +01:00
|
|
|
}
|
|
|
|
|
2010-06-08 09:15:09 +02:00
|
|
|
var initializerGrammar = {
|
2010-06-08 12:46:16 +02:00
|
|
|
type: "grammar",
|
2010-06-08 09:15:09 +02:00
|
|
|
initializer: initializer(" code "),
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [rule("a", null, literalAbcd)],
|
2010-06-08 11:03:28 +02:00
|
|
|
startRule: "a"
|
2010-06-08 09:15:09 +02:00
|
|
|
};
|
|
|
|
|
2011-09-30 16:49:50 +02:00
|
|
|
var namedRuleGrammar = {
|
|
|
|
type: "grammar",
|
|
|
|
initializer: null,
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [rule("start", "abcd", literalAbcd)],
|
2011-09-30 16:49:50 +02:00
|
|
|
startRule: "start"
|
|
|
|
};
|
|
|
|
|
2010-06-07 10:59:14 +02:00
|
|
|
/* Canonical grammar is "a: \"abcd\"; b: \"efgh\"; c: \"ijkl\";". */
|
2010-05-21 19:00:00 +02:00
|
|
|
test("parses grammar", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-06-08 09:15:09 +02:00
|
|
|
'a = "abcd"',
|
|
|
|
{
|
2010-06-08 12:46:16 +02:00
|
|
|
type: "grammar",
|
2010-06-08 09:15:09 +02:00
|
|
|
initializer: null,
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [rule("a", null, literalAbcd)],
|
2010-06-08 11:03:28 +02:00
|
|
|
startRule: "a"
|
2010-06-08 09:15:09 +02:00
|
|
|
}
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('{ code }; a = "abcd"', initializerGrammar);
|
|
|
|
parserParses(
|
2010-06-07 10:59:14 +02:00
|
|
|
'a = "abcd"; b = "efgh"; c = "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
{
|
2010-06-08 12:46:16 +02:00
|
|
|
type: "grammar",
|
2010-06-08 09:15:09 +02:00
|
|
|
initializer: null,
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [
|
|
|
|
rule("a", null, literalAbcd),
|
|
|
|
rule("b", null, literalEfgh),
|
|
|
|
rule("c", null, literalIjkl)
|
|
|
|
],
|
2010-06-08 11:03:28 +02:00
|
|
|
startRule: "a"
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2010-06-08 09:15:09 +02:00
|
|
|
/* Canonical initializer is "{ code }". */
|
|
|
|
test("parses initializer", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('{ code }a = "abcd"', initializerGrammar);
|
|
|
|
parserParses('{ code };a = "abcd"', initializerGrammar);
|
2010-06-08 09:15:09 +02:00
|
|
|
});
|
|
|
|
|
2010-05-21 19:00:00 +02:00
|
|
|
/* Canonical rule is "a: \"abcd\"". */
|
|
|
|
test("parses rule", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start = "abcd" / "efgh" / "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
oneRuleGrammar(choiceLiterals)
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start "start rule" = "abcd" / "efgh" / "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
{
|
2010-06-08 12:46:16 +02:00
|
|
|
type: "grammar",
|
2010-06-08 09:15:09 +02:00
|
|
|
initializer: null,
|
2012-03-04 17:29:32 +01:00
|
|
|
rules: [rule("start", "start rule", choiceLiterals)],
|
2010-06-08 11:03:28 +02:00
|
|
|
startRule: "start"
|
2010-05-21 19:00:00 +02:00
|
|
|
}
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-06-07 10:59:14 +02:00
|
|
|
'start = "abcd" / "efgh" / "ijkl";',
|
|
|
|
oneRuleGrammar(choiceLiterals)
|
|
|
|
);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical expression is "\"abcd\" / \"efgh\" / \"ijkl\"". */
|
|
|
|
test("parses expression", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start = "abcd" / "efgh" / "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
oneRuleGrammar(choiceLiterals)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical choice is "\"abcd\" / \"efgh\" / \"ijkl\"". */
|
|
|
|
test("parses choice", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start = "abcd" "efgh" "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
oneRuleGrammar(sequenceLiterals)
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start = "abcd" "efgh" "ijkl" / "abcd" "efgh" "ijkl" / "abcd" "efgh" "ijkl"',
|
2010-05-21 19:00:00 +02:00
|
|
|
oneRuleGrammar(choice([
|
|
|
|
sequenceLiterals,
|
|
|
|
sequenceLiterals,
|
|
|
|
sequenceLiterals
|
|
|
|
]))
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical sequence is "\"abcd\" \"efgh\" \"ijkl\"". */
|
|
|
|
test("parses sequence", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
'start = { code }',
|
2010-05-21 19:00:00 +02:00
|
|
|
oneRuleGrammar(action(sequenceEmpty, " code "))
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 19:29:53 +02:00
|
|
|
'start = a:"abcd" { code }',
|
|
|
|
oneRuleGrammar(action(labeledAbcd, " code "))
|
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 19:29:53 +02:00
|
|
|
'start = a:"abcd" e:"efgh" i:"ijkl" { code }',
|
|
|
|
oneRuleGrammar(action(sequenceLabeleds, " code "))
|
2010-05-21 19:00:00 +02:00
|
|
|
);
|
2010-05-23 19:29:53 +02:00
|
|
|
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = ', oneRuleGrammar(sequenceEmpty));
|
|
|
|
parserParses('start = a:"abcd"', oneRuleGrammar(labeledAbcd));
|
|
|
|
parserParses(
|
2010-05-23 19:29:53 +02:00
|
|
|
'start = a:"abcd" e:"efgh" i:"ijkl"',
|
|
|
|
oneRuleGrammar(sequenceLabeleds)
|
2010-05-21 19:00:00 +02:00
|
|
|
);
|
2010-05-23 19:29:53 +02:00
|
|
|
});
|
2010-05-21 19:00:00 +02:00
|
|
|
|
2010-05-23 19:29:53 +02:00
|
|
|
/* Canonical labeled is "label:\"abcd\"". */
|
|
|
|
test("parses labeled", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses(
|
2010-05-23 19:29:53 +02:00
|
|
|
'start = label:!"abcd"',
|
2010-06-08 14:49:13 +02:00
|
|
|
oneRuleGrammar(labeled("label", simpleNot(literalAbcd)))
|
2010-05-23 19:29:53 +02:00
|
|
|
);
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = !"abcd"', oneRuleGrammar(simpleNot(literalAbcd)));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical prefixed is "!\"abcd\"". */
|
|
|
|
test("parses prefixed", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = &{ code }', oneRuleGrammar(semanticAnd(" code ")));
|
|
|
|
parserParses('start = &"abcd"?', oneRuleGrammar(simpleAnd(optionalLiteral)));
|
|
|
|
parserParses('start = !{ code }', oneRuleGrammar(semanticNot(" code ")));
|
|
|
|
parserParses('start = !"abcd"?', oneRuleGrammar(simpleNot(optionalLiteral)));
|
|
|
|
parserParses('start = "abcd"?', oneRuleGrammar(optionalLiteral));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical suffixed is "\"abcd\"?". */
|
|
|
|
test("parses suffixed", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "abcd"?', oneRuleGrammar(optionalLiteral));
|
|
|
|
parserParses('start = "abcd"*', oneRuleGrammar(zeroOrMore(literalAbcd)));
|
|
|
|
parserParses('start = "abcd"+', oneRuleGrammar(oneOrMore(literalAbcd)));
|
|
|
|
parserParses('start = "abcd"', literalGrammar("abcd"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical primary is "\"abcd\"". */
|
|
|
|
test("parses primary", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = a', identifierGrammar("a"));
|
|
|
|
parserParses('start = "abcd"', literalGrammar("abcd"));
|
|
|
|
parserParses('start = .', anyGrammar);
|
|
|
|
parserParses('start = [a-d]', classGrammar(false, [["a", "d"]], "[a-d]"));
|
|
|
|
parserParses('start = ("abcd")', literalGrammar("abcd"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical action is "{ code }". */
|
|
|
|
test("parses action", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "a" { code }', actionGrammar(" code "));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical braced is "{ code }". */
|
|
|
|
test("parses braced", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "a" {}', actionGrammar(""));
|
|
|
|
parserParses('start = "a" {a}', actionGrammar("a"));
|
|
|
|
parserParses('start = "a" {{a}}', actionGrammar("{a}"));
|
|
|
|
parserParses('start = "a" {aaa}', actionGrammar("aaa"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Trivial character rules are not tested. */
|
|
|
|
|
|
|
|
/* Canonical identifier is "a". */
|
|
|
|
test("parses identifier", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = a', identifierGrammar("a"));
|
|
|
|
parserParses('start = z', identifierGrammar("z"));
|
|
|
|
parserParses('start = A', identifierGrammar("A"));
|
|
|
|
parserParses('start = Z', identifierGrammar("Z"));
|
|
|
|
parserParses('start = _', identifierGrammar("_"));
|
|
|
|
parserParses('start = $', identifierGrammar("$"));
|
|
|
|
parserParses('start = aa', identifierGrammar("aa"));
|
|
|
|
parserParses('start = az', identifierGrammar("az"));
|
|
|
|
parserParses('start = aA', identifierGrammar("aA"));
|
|
|
|
parserParses('start = aZ', identifierGrammar("aZ"));
|
|
|
|
parserParses('start = a0', identifierGrammar("a0"));
|
|
|
|
parserParses('start = a9', identifierGrammar("a9"));
|
|
|
|
parserParses('start = a_', identifierGrammar("a_"));
|
|
|
|
parserParses('start = a$', identifierGrammar("a$"));
|
|
|
|
parserParses('start = abcd', identifierGrammar("abcd"));
|
|
|
|
|
|
|
|
parserParses('start = a\n', identifierGrammar("a"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical literal is "\"abcd\"". */
|
|
|
|
test("parses literal", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "abcd"', literalGrammar("abcd"));
|
2011-09-30 11:17:47 +02:00
|
|
|
parserParses("start = 'abcd'", literalGrammar("abcd"));
|
|
|
|
parserParses('start = "abcd"i', oneRuleGrammar(literal("abcd", true)));
|
2011-09-30 16:44:44 +02:00
|
|
|
|
|
|
|
parserParses('start = "abcd"\n', literalGrammar("abcd"));
|
2011-09-30 10:17:33 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical string is "\"abcd\"". */
|
|
|
|
test("parses string", function() {
|
2011-09-30 16:49:50 +02:00
|
|
|
parserParses('start "abcd" = "abcd"', namedRuleGrammar);
|
|
|
|
parserParses('start \'abcd\' = "abcd"', namedRuleGrammar);
|
2011-09-30 16:44:44 +02:00
|
|
|
|
2011-09-30 16:49:50 +02:00
|
|
|
parserParses('start "abcd"\n= "abcd"', namedRuleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
2011-09-30 10:17:33 +02:00
|
|
|
/* Canonical doubleQuotedString is "\"abcd\"". */
|
|
|
|
test("parses doubleQuotedString", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = ""', literalGrammar(""));
|
|
|
|
parserParses('start = "a"', literalGrammar("a"));
|
|
|
|
parserParses('start = "abc"', literalGrammar("abc"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical doubleQuotedCharacter is "a". */
|
|
|
|
test("parses doubleQuotedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "a"', literalGrammar("a"));
|
|
|
|
parserParses('start = "\\n"', literalGrammar("\n"));
|
test/parser-test.js: Replace "\0" with "\x00"
Fixes the following JSHint errors:
./test/parser-test.js: line 353, col 54, Bad escapement.
./test/parser-test.js: line 384, col 54, Bad escapement.
./test/parser-test.js: line 436, col 60, Bad escapement.
./test/parser-test.js: line 437, col 60, Bad escapement.
./test/parser-test.js: line 472, col 50, Bad escapement.
2011-09-14 13:00:04 +02:00
|
|
|
parserParses('start = "\\0"', literalGrammar("\x00"));
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\x00"', literalGrammar("\x00"));
|
|
|
|
parserParses('start = "\\u0120"', literalGrammar("\u0120"));
|
|
|
|
parserParses('start = "\\\n"', literalGrammar("\n"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical simpleDoubleQuotedCharacter is "a". */
|
|
|
|
test("parses simpleDoubleQuotedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "a"', literalGrammar("a"));
|
|
|
|
parserParses('start = "\'"', literalGrammar("'"));
|
|
|
|
parserDoesNotParse('start = """');
|
|
|
|
parserDoesNotParse('start = "\\"');
|
|
|
|
parserDoesNotParse('start = "\n"');
|
|
|
|
parserDoesNotParse('start = "\r"');
|
|
|
|
parserDoesNotParse('start = "\u2028"');
|
|
|
|
parserDoesNotParse('start = "\u2029"');
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
2011-09-30 10:17:33 +02:00
|
|
|
/* Canonical singleQuotedString is "'abcd'". */
|
|
|
|
test("parses singleQuotedString", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = ''", literalGrammar(""));
|
|
|
|
parserParses("start = 'a'", literalGrammar("a"));
|
|
|
|
parserParses("start = 'abc'", literalGrammar("abc"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical singleQuotedCharacter is "a". */
|
|
|
|
test("parses singleQuotedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = 'a'", literalGrammar("a"));
|
|
|
|
parserParses("start = '\\n'", literalGrammar("\n"));
|
test/parser-test.js: Replace "\0" with "\x00"
Fixes the following JSHint errors:
./test/parser-test.js: line 353, col 54, Bad escapement.
./test/parser-test.js: line 384, col 54, Bad escapement.
./test/parser-test.js: line 436, col 60, Bad escapement.
./test/parser-test.js: line 437, col 60, Bad escapement.
./test/parser-test.js: line 472, col 50, Bad escapement.
2011-09-14 13:00:04 +02:00
|
|
|
parserParses("start = '\\0'", literalGrammar("\x00"));
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = '\\x00'", literalGrammar("\x00"));
|
|
|
|
parserParses("start = '\\u0120'", literalGrammar("\u0120"));
|
|
|
|
parserParses("start = '\\\n'", literalGrammar("\n"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical simpleSingleQuotedCharacter is "a". */
|
|
|
|
test("parses simpleSingleQuotedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = 'a'", literalGrammar("a"));
|
|
|
|
parserParses("start = '\"'", literalGrammar("\""));
|
|
|
|
parserDoesNotParse("start = '''");
|
|
|
|
parserDoesNotParse("start = '\\'");
|
|
|
|
parserDoesNotParse("start = '\n'");
|
|
|
|
parserDoesNotParse("start = '\r'");
|
|
|
|
parserDoesNotParse("start = '\u2028'");
|
|
|
|
parserDoesNotParse("start = '\u2029'");
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical class is "[a-d]". */
|
|
|
|
test("parses class", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = []", classGrammar(false, [], "[]"));
|
|
|
|
parserParses("start = [a-d]", classGrammar(false, [["a", "d"]], "[a-d]"));
|
|
|
|
parserParses("start = [^a-d]", classGrammar(true, [["a", "d"]], "[^a-d]"));
|
|
|
|
parserParses("start = [a]", classGrammar(false, ["a"], "[a]"));
|
|
|
|
parserParses(
|
2010-05-23 10:41:43 +02:00
|
|
|
"start = [a-de-hi-l]",
|
2010-05-22 10:13:48 +02:00
|
|
|
classGrammar(false, [["a", "d"], ["e", "h"], ["i", "l"]], "[a-de-hi-l]")
|
|
|
|
);
|
2011-09-30 11:45:36 +02:00
|
|
|
parserParses(
|
|
|
|
"start = [a-d]i",
|
|
|
|
oneRuleGrammar(klass(false, true, [["a", "d"]], "[a-d]i"))
|
|
|
|
);
|
2010-05-21 19:00:00 +02:00
|
|
|
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [a-d]\n", classGrammar(false, [["a", "d"]], "[a-d]"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical classCharacterRange is "a-d". */
|
|
|
|
test("parses classCharacterRange", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [a-d]", classGrammar(false, [["a", "d"]], "[a-d]"));
|
|
|
|
parserParses("start = [a-a]", classGrammar(false, [["a", "a"]], "[a-a]"));
|
|
|
|
parserDoesNotParse("start = [b-a]");
|
|
|
|
parserDoesNotParseWithMessage(
|
2010-05-23 10:41:43 +02:00
|
|
|
"start = [b-a]",
|
2010-05-31 16:30:02 +02:00
|
|
|
"Invalid character range: b-a."
|
|
|
|
);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical classCharacter is "a". */
|
|
|
|
test("parses classCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [a]", classGrammar(false, ["a"], "[a]"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical bracketDelimitedCharacter is "a". */
|
|
|
|
test("parses bracketDelimitedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [a]", classGrammar(false, ["a"], "[a]"));
|
|
|
|
parserParses("start = [\\n]", classGrammar(false, ["\n"], "[\\n]"));
|
test/parser-test.js: Replace "\0" with "\x00"
Fixes the following JSHint errors:
./test/parser-test.js: line 353, col 54, Bad escapement.
./test/parser-test.js: line 384, col 54, Bad escapement.
./test/parser-test.js: line 436, col 60, Bad escapement.
./test/parser-test.js: line 437, col 60, Bad escapement.
./test/parser-test.js: line 472, col 50, Bad escapement.
2011-09-14 13:00:04 +02:00
|
|
|
parserParses("start = [\\0]", classGrammar(false, ["\x00"], "[\\0]"));
|
|
|
|
parserParses("start = [\\x00]", classGrammar(false, ["\x00"], "[\\0]"));
|
2010-11-20 16:58:47 +01:00
|
|
|
parserParses("start = [\\u0120]", classGrammar(false, ["\u0120"], "[\\u0120]"));
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [\\\n]", classGrammar(false, ["\n"], "[\\n]"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical simpleBracketDelimiedCharacter is "a". */
|
|
|
|
test("parses simpleBracketDelimitedCharacter", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses("start = [a]", classGrammar(false, ["a"], "[a]"));
|
|
|
|
parserParses("start = [[]", classGrammar(false, ["["], "[[]"));
|
|
|
|
parserDoesNotParse("start = []]");
|
|
|
|
parserDoesNotParse("start = [\\]");
|
|
|
|
parserDoesNotParse("start = [\n]");
|
|
|
|
parserDoesNotParse("start = [\r]");
|
|
|
|
parserDoesNotParse("start = [\u2028]");
|
|
|
|
parserDoesNotParse("start = [\u2029]");
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical simpleEscapeSequence is "\\n". */
|
|
|
|
test("parses simpleEscapeSequence", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\\'"', literalGrammar("'"));
|
|
|
|
parserParses('start = "\\""', literalGrammar("\""));
|
|
|
|
parserParses('start = "\\\\"', literalGrammar("\\"));
|
|
|
|
parserParses('start = "\\b"', literalGrammar("\b"));
|
|
|
|
parserParses('start = "\\f"', literalGrammar("\f"));
|
|
|
|
parserParses('start = "\\n"', literalGrammar("\n"));
|
|
|
|
parserParses('start = "\\r"', literalGrammar("\r"));
|
|
|
|
parserParses('start = "\\t"', literalGrammar("\t"));
|
2010-05-21 19:00:00 +02:00
|
|
|
/* IE does not recognize "\v". */
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\v"', literalGrammar("\x0B"));
|
2010-05-21 19:00:00 +02:00
|
|
|
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\a"', literalGrammar("a"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical zeroEscapeSequence is "\\0". */
|
|
|
|
test("parses zeroEscapeSequence", function() {
|
test/parser-test.js: Replace "\0" with "\x00"
Fixes the following JSHint errors:
./test/parser-test.js: line 353, col 54, Bad escapement.
./test/parser-test.js: line 384, col 54, Bad escapement.
./test/parser-test.js: line 436, col 60, Bad escapement.
./test/parser-test.js: line 437, col 60, Bad escapement.
./test/parser-test.js: line 472, col 50, Bad escapement.
2011-09-14 13:00:04 +02:00
|
|
|
parserParses('start = "\\0"', literalGrammar("\x00"));
|
2010-08-18 21:07:04 +02:00
|
|
|
parserDoesNotParse('start = "\\00"');
|
|
|
|
parserDoesNotParse('start = "\\09"');
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical hexEscapeSequence is "\\x00". */
|
|
|
|
test("parses hexEscapeSequence", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\x00"', literalGrammar("\x00"));
|
|
|
|
parserParses('start = "\\x09"', literalGrammar("\x09"));
|
|
|
|
parserParses('start = "\\x0a"', literalGrammar("\x0a"));
|
|
|
|
parserParses('start = "\\x0f"', literalGrammar("\x0f"));
|
|
|
|
parserParses('start = "\\x0A"', literalGrammar("\x0A"));
|
|
|
|
parserParses('start = "\\x0F"', literalGrammar("\x0F"));
|
|
|
|
parserDoesNotParse('start = "\\x0"');
|
|
|
|
parserParses('start = "\\x000"', literalGrammar("\x000"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical unicodeEscapeSequence is "\\u0120". */
|
|
|
|
test("parses unicodeEscapeSequence", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\u0120"', literalGrammar("\u0120"));
|
|
|
|
parserParses('start = "\\u0129"', literalGrammar("\u0129"));
|
|
|
|
parserParses('start = "\\u012a"', literalGrammar("\u012a"));
|
|
|
|
parserParses('start = "\\u012f"', literalGrammar("\u012f"));
|
|
|
|
parserParses('start = "\\u012A"', literalGrammar("\u012A"));
|
|
|
|
parserParses('start = "\\u012F"', literalGrammar("\u012F"));
|
|
|
|
parserDoesNotParse('start = "\\u012"');
|
|
|
|
parserParses('start = "\\u01234"', literalGrammar("\u01234"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical eolEscapeSequence is "\\\n". */
|
|
|
|
test("parses eolEscapeSequence", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start = "\\\n"', literalGrammar("\n"));
|
|
|
|
parserParses('start = "\\\r\n"', literalGrammar("\r\n"));
|
|
|
|
parserParses('start = "\\\r"', literalGrammar("\r"));
|
|
|
|
parserParses('start = "\\\u2028"', literalGrammar("\u2028"));
|
|
|
|
parserParses('start = "\\\u2029"', literalGrammar("\u2029"));
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical __ is "\n". */
|
|
|
|
test("parses __", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start ="abcd"', simpleGrammar);
|
|
|
|
parserParses('start = "abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/* comment */"abcd"', simpleGrammar);
|
|
|
|
parserParses('start = "abcd"', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Trivial character class rules are not tested. */
|
|
|
|
|
2011-09-14 12:54:08 +02:00
|
|
|
// Canonical comment is "\/* comment *\/".
|
2010-05-21 19:00:00 +02:00
|
|
|
test("parses comment", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start =// comment\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/* comment */"abcd"', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
/* Canonical singleLineComment is "// comment". */
|
|
|
|
test("parses singleLineComment", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start =//\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =//a\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =//aaa\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start = "abcd"//', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
2011-09-14 12:54:08 +02:00
|
|
|
// Canonical multiLineComment is "\/* comment *\/".
|
2010-05-21 19:00:00 +02:00
|
|
|
test("parses multiLineComment", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start =/**/"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/*a*/"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/*aaa*/"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/*\n*/"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/***/"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =/*a/*/"abcd"', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
|
2010-08-18 21:07:04 +02:00
|
|
|
parserDoesNotParse('start =/*"abcd"');
|
|
|
|
parserDoesNotParse('start =/*/"abcd"');
|
|
|
|
parserDoesNotParse('start =/*/**/*/"abcd"');
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical eol is "\n". */
|
|
|
|
test("parses eol", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start =\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\r\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\r"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\u2028"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\u2029"abcd"', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
/* Canonical eolChar is "\n". */
|
|
|
|
test("parses eolChar", function() {
|
2010-08-18 21:07:04 +02:00
|
|
|
parserParses('start =\n"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\r"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\u2028"abcd"', simpleGrammar);
|
|
|
|
parserParses('start =\u2029"abcd"', simpleGrammar);
|
2010-05-21 19:00:00 +02:00
|
|
|
});
|
|
|
|
|
2011-02-13 12:22:56 +01:00
|
|
|
})();
|