[Pkg-mozext-commits] [greasemonkey] 01/45: Parse metadata lines via a formal grammar.
David Prévot
taffit at moszumanska.debian.org
Mon Nov 3 20:59:18 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository greasemonkey.
commit ad82f7c5123ceb64fcfd68fea2b017862f6eb7be
Author: Anthony Lieuallen <arantius at gmail.com>
Date: Mon Aug 25 15:58:47 2014 -0400
Parse metadata lines via a formal grammar.
And a parser generator.
Refs #1996
---
modules/parseScript.js | 155 +++++-----
modules/stats.js | 15 -
modules/util/parseMetaLine.js | 695 ++++++++++++++++++++++++++++++++++++++++++
peg.txt | 85 ++++++
4 files changed, 856 insertions(+), 94 deletions(-)
diff --git a/modules/parseScript.js b/modules/parseScript.js
index f2b363d..e6ac7e6 100644
--- a/modules/parseScript.js
+++ b/modules/parseScript.js
@@ -1,5 +1,4 @@
-var EXPORTED_SYMBOLS = [
- 'extractMeta', 'parse', 'gLineSplitRegexp', 'gMetaLineRegexp'];
+var EXPORTED_SYMBOLS = ['extractMeta', 'parse'];
Components.utils.import('resource://greasemonkey/script.js');
Components.utils.import('resource://greasemonkey/scriptIcon.js');
@@ -10,15 +9,15 @@ Components.utils.import('resource://greasemonkey/util.js');
var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
-var gLineSplitRegexp = /.+/g;
var gAllMetaRegexp = new RegExp(
- '^(\u00EF\u00BB\u00BF)?// ==UserScript==([\\s\\S]*?)^// ==/UserScript==', 'm');
-var gMetaLineRegexp = new RegExp('// @([^\\s:]+)(?::([a-zA-Z-]+))?(?:\\s+(.*))?');
+ '^(\u00EF\u00BB\u00BF)?// ==UserScript==([\\s\\S]*?)^// ==/UserScript==',
+ 'm');
var gStringBundle = Components
.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService)
.createBundle("chrome://greasemonkey/locale/greasemonkey.properties");
+
/** Get just the stuff between ==UserScript== lines. */
function extractMeta(aSource) {
var meta = aSource.match(gAllMetaRegexp);
@@ -26,9 +25,10 @@ function extractMeta(aSource) {
return '';
}
+
/** Parse the source of a script; produce Script object. */
function parse(aSource, aUri, aFailWhenMissing, aNoMetaOk) {
- var meta = extractMeta(aSource).match(gLineSplitRegexp);
+ var meta = extractMeta(aSource).match(/.+/g);
if (aFailWhenMissing && !meta && !aNoMetaOk) return null;
var script = new Script();
@@ -48,124 +48,120 @@ function parse(aSource, aUri, aFailWhenMissing, aNoMetaOk) {
}
var resourceNames = {};
- if (meta) for (var i = 0, metaLine = ''; metaLine = meta[i]; i++) {
- metaLine = metaLine.replace(/\s+$/, '');
-
- var match = metaLine.match(gMetaLineRegexp);
- if (!match) continue;
-
- var header = match[1];
- var locale = match[2];
- var value = match[3] || null;
+ for (var i = 0, metaLine = ''; metaLine = meta[i]; i++) {
+ try {
+ var data = GM_util.parseMetaLine(metaLine.replace(/\s+$/, ''));
+ } catch (e) {
+ // Ignore invalid/unsupported meta lines.
+ continue;
+ }
- switch (header) {
+ switch (data.keyword) {
case 'description':
case 'name':
+ var locale = data.locale.replace(/^:/, '');
+
if (locale) {
- if (!script._locales[locale])
+ if (!script._locales[locale]) {
script._locales[locale] = {};
+ }
+ script._locales[locale][keyword] = data.value;
+ }
+
+ script['_' + data.keyword] = data.value;
- script._locales[locale][header] = value;
- break;
+ break;
+
+ case 'resource':
+ var name = data.value1;
+ var url = data.value2;
+
+ resourceNames[name] = true;
+
+ try {
+ var resUri = GM_util.uriFromUrl(url, aUri);
+ var scriptResource = new ScriptResource(script);
+ scriptResource._name = name;
+ scriptResource._downloadURL = resUri.spec;
+ script._resources.push(scriptResource);
+ script._rawMeta += data.keyword + '\0'
+ + name + '\0'
+ + resUri.spec + '\0';
+ } catch (e) {
+ script.parseErrors.push(
+ gStringBundle.GetStringFromName('parse.resource-failed')
+ .replace('%1', name).replace('%2', url)
+ );
}
- // fall-through if no locale given
+
+ break;
+
case 'namespace':
case 'version':
- case 'updateMetaStatus':
- script['_' + header] = value;
+ script['_' + data.keyword] = data.value;
+ break;
+ case 'exclude':
+ script._excludes.push(data.value);
+ break;
+ case 'grant':
+ script._grants.push(data.value);
+ break;
+ case 'include':
+ script._includes.push(data.value);
+ break;
+ case 'run-at':
+ script._runAt = data.value;
break;
case 'installURL':
- header = 'downloadURL';
+ data.keyword = 'downloadURL';
case 'downloadURL':
case 'updateURL':
try {
- var uri = GM_util.uriFromUrl(value, aUri);
- script[header] = uri.spec;
+ var uri = GM_util.uriFromUrl(data.value, aUri);
+ script[data.keyword] = uri.spec;
} catch (e) {
- dump('Failed to parse ' + header + ' "' + value + '":\n' + e + '\n');
+ dump('Failed to parse ' + data.keyword
+ + ' "' + data.value + '":\n' + e + '\n');
}
break;
- case 'exclude':
- script._excludes.push(value);
- break;
- case 'grant':
- script._grants.push(value);
- break;
case 'icon':
try {
- script.icon.setMetaVal(value);
- script._rawMeta += header + '\0' + value + '\0';
+ script.icon.setMetaVal(data.value);
+ script._rawMeta += data.keyword + '\0' + data.value + '\0';
} catch (e) {
script.parseErrors.push(e.message);
}
break;
- case 'include':
- script._includes.push(value);
- break;
+
case 'match':
try {
- var match = new MatchPattern(value);
+ var match = new MatchPattern(data.value);
script._matches.push(match);
} catch (e) {
script.parseErrors.push(
gStringBundle.GetStringFromName('parse.ignoring-match')
- .replace('%1', value).replace('%2', e)
+ .replace('%1', data.value).replace('%2', e)
);
}
break;
+
case 'require':
try {
- var reqUri = GM_util.uriFromUrl(value, aUri);
+ var reqUri = GM_util.uriFromUrl(data.value, aUri);
var scriptRequire = new ScriptRequire(script);
scriptRequire._downloadURL = reqUri.spec;
script._requires.push(scriptRequire);
- script._rawMeta += header + '\0' + value + '\0';
+ script._rawMeta += data.keyword + '\0' + data.value + '\0';
} catch (e) {
+ dump('require err:'+e+'\n');
script.parseErrors.push(
gStringBundle.GetStringFromName('parse.require-failed')
- .replace('%1', value)
+ .replace('%1', data.value)
);
}
break;
- case 'resource':
- var res = value.match(/(\S+)\s+(.*)/);
- if (res === null) {
- script.parseErrors.push(
- gStringBundle.GetStringFromName('parse.resource-syntax')
- .replace('%1', value)
- );
- break;
- }
-
- var resName = res[1];
- if (resourceNames[resName]) {
- script.parseErrors.push(
- gStringBundle.GetStringFromName('parse.resource-duplicate')
- .replace('%1', resName)
- );
- break;
- }
- resourceNames[resName] = true;
-
- try {
- var resUri = GM_util.uriFromUrl(res[2], aUri);
- var scriptResource = new ScriptResource(script);
- scriptResource._name = resName;
- scriptResource._downloadURL = resUri.spec;
- script._resources.push(scriptResource);
- script._rawMeta += header + '\0' + resName + '\0' + resUri.spec + '\0';
- } catch (e) {
- script.parseErrors.push(
- gStringBundle.GetStringFromName('parse.resource-failed')
- .replace('%1', resName).replace('%2', res[2])
- );
- }
- break;
- case 'run-at':
- script._runAt = value;
- break;
}
}
@@ -173,6 +169,7 @@ function parse(aSource, aUri, aFailWhenMissing, aNoMetaOk) {
return script;
}
+
function setDefaults(script) {
if (!script.updateURL && script.downloadURL) {
script.updateURL = script.downloadURL;
diff --git a/modules/stats.js b/modules/stats.js
index e3dd84e..997d0f6 100644
--- a/modules/stats.js
+++ b/modules/stats.js
@@ -109,18 +109,6 @@ function getStatsObj() {
for (var i = 0, script = null; script = scripts[i]; i++) {
var valueStats = GM_ScriptStorage(script).getStats();
- var explicitGrants = [];
- var imperatives = [];
- var metaLines = extractMeta(script.textContent).match(gLineSplitRegexp);
- for (var j = 0, metaLine = null; metaLine = metaLines[j]; j++) {
- var m = gMetaLineRegexp.exec(metaLine);
- if (!m) continue;
- imperatives[imperatives.length] = m[1];
- if ('grant' == m[1]) {
- explicitGrants[explicitGrants.length] = m[2];
- }
- }
-
var downloadUri = GM_util.uriFromUrl(script.downloadURL);
var domain = null;
try {
@@ -135,10 +123,7 @@ function getStatsObj() {
var scriptStat = {
'enabled': script.enabled,
- 'explicitGrants': explicitGrants,
'id': script.id,
- 'imperatives': imperatives,
- 'implicitGrants': script.grants,
'installScheme': downloadUri.scheme,
'installDomain': domain,
'installTime': script.installDate.toISOString(),
diff --git a/modules/util/parseMetaLine.js b/modules/util/parseMetaLine.js
new file mode 100644
index 0000000..121ab32
--- /dev/null
+++ b/modules/util/parseMetaLine.js
@@ -0,0 +1,695 @@
+const EXPORTED_SYMBOLS = ['SyntaxError', 'parseMetaLine'];
+
+/*
+ * Generated by PEG.js 0.8.0.
+ *
+ * http://pegjs.majda.cz/
+ */
+
+function peg$subclass(child, parent) {
+ function ctor() { this.constructor = child; }
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor();
+}
+
+function SyntaxError(message, expected, found, offset, line, column) {
+ this.message = message;
+ this.expected = expected;
+ this.found = found;
+ this.offset = offset;
+ this.line = line;
+ this.column = column;
+
+ this.name = "SyntaxError";
+}
+
+peg$subclass(SyntaxError, Error);
+
+function parseMetaLine(input) {
+ var options = arguments.length > 1 ? arguments[1] : {},
+
+ peg$FAILED = {},
+
+ peg$startRuleFunctions = { line: peg$parseline },
+ peg$startRuleFunction = peg$parseline,
+
+ peg$c0 = peg$FAILED,
+ peg$c1 = "// @",
+ peg$c2 = { type: "literal", value: "// @", description: "\"// @\"" },
+ peg$c3 = null,
+ peg$c4 = "\n",
+ peg$c5 = { type: "literal", value: "\n", description: "\"\\n\"" },
+ peg$c6 = function(meta) { return meta; },
+ peg$c7 = [],
+ peg$c8 = /^[ \t\n]/,
+ peg$c9 = { type: "class", value: "[ \\t\\n]", description: "[ \\t\\n]" },
+ peg$c10 = /^[^ \t\n]/,
+ peg$c11 = { type: "class", value: "[^ \\t\\n]", description: "[^ \\t\\n]" },
+ peg$c12 = function(val) { return val.join('');},
+ peg$c13 = /^[^\n]/,
+ peg$c14 = { type: "class", value: "[^\\n]", description: "[^\\n]" },
+ peg$c15 = "downloadURL",
+ peg$c16 = { type: "literal", value: "downloadURL", description: "\"downloadURL\"" },
+ peg$c17 = "exclude",
+ peg$c18 = { type: "literal", value: "exclude", description: "\"exclude\"" },
+ peg$c19 = "grant",
+ peg$c20 = { type: "literal", value: "grant", description: "\"grant\"" },
+ peg$c21 = "icon",
+ peg$c22 = { type: "literal", value: "icon", description: "\"icon\"" },
+ peg$c23 = "include",
+ peg$c24 = { type: "literal", value: "include", description: "\"include\"" },
+ peg$c25 = "installURL",
+ peg$c26 = { type: "literal", value: "installURL", description: "\"installURL\"" },
+ peg$c27 = "match",
+ peg$c28 = { type: "literal", value: "match", description: "\"match\"" },
+ peg$c29 = "namespace",
+ peg$c30 = { type: "literal", value: "namespace", description: "\"namespace\"" },
+ peg$c31 = "require",
+ peg$c32 = { type: "literal", value: "require", description: "\"require\"" },
+ peg$c33 = "run-at",
+ peg$c34 = { type: "literal", value: "run-at", description: "\"run-at\"" },
+ peg$c35 = "updateURL",
+ peg$c36 = { type: "literal", value: "updateURL", description: "\"updateURL\"" },
+ peg$c37 = "version",
+ peg$c38 = { type: "literal", value: "version", description: "\"version\"" },
+ peg$c39 = function(keyword, value) { return {keyword:keyword, value:value}; },
+ peg$c40 = "resource",
+ peg$c41 = { type: "literal", value: "resource", description: "\"resource\"" },
+ peg$c42 = function(keyword, value1, value2) { return {keyword:keyword, value1:value1, value2:value2}; },
+ peg$c43 = "description",
+ peg$c44 = { type: "literal", value: "description", description: "\"description\"" },
+ peg$c45 = "name",
+ peg$c46 = { type: "literal", value: "name", description: "\"name\"" },
+ peg$c47 = ":",
+ peg$c48 = { type: "literal", value: ":", description: "\":\"" },
+ peg$c49 = /^[a-zA-Z\-]/,
+ peg$c50 = { type: "class", value: "[a-zA-Z\\-]", description: "[a-zA-Z\\-]" },
+ peg$c51 = function(keyword, locale, value) { return {keyword:keyword, locale:locale, value:value}; },
+
+ peg$currPos = 0,
+ peg$reportedPos = 0,
+ peg$cachedPos = 0,
+ peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
+ peg$maxFailPos = 0,
+ peg$maxFailExpected = [],
+ peg$silentFails = 0,
+
+ peg$result;
+
+ if ("startRule" in options) {
+ if (!(options.startRule in peg$startRuleFunctions)) {
+ throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
+ }
+
+ peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
+ }
+
+ function text() {
+ return input.substring(peg$reportedPos, peg$currPos);
+ }
+
+ function offset() {
+ return peg$reportedPos;
+ }
+
+ function line() {
+ return peg$computePosDetails(peg$reportedPos).line;
+ }
+
+ function column() {
+ return peg$computePosDetails(peg$reportedPos).column;
+ }
+
+ function expected(description) {
+ throw peg$buildException(
+ null,
+ [{ type: "other", description: description }],
+ peg$reportedPos
+ );
+ }
+
+ function error(message) {
+ throw peg$buildException(message, null, peg$reportedPos);
+ }
+
+ function peg$computePosDetails(pos) {
+ function advance(details, startPos, endPos) {
+ var p, ch;
+
+ for (p = startPos; p < endPos; p++) {
+ ch = input.charAt(p);
+ if (ch === "\n") {
+ if (!details.seenCR) { details.line++; }
+ details.column = 1;
+ details.seenCR = false;
+ } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
+ details.line++;
+ details.column = 1;
+ details.seenCR = true;
+ } else {
+ details.column++;
+ details.seenCR = false;
+ }
+ }
+ }
+
+ if (peg$cachedPos !== pos) {
+ if (peg$cachedPos > pos) {
+ peg$cachedPos = 0;
+ peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
+ }
+ advance(peg$cachedPosDetails, peg$cachedPos, pos);
+ peg$cachedPos = pos;
+ }
+
+ return peg$cachedPosDetails;
+ }
+
+ function peg$fail(expected) {
+ if (peg$currPos < peg$maxFailPos) { return; }
+
+ if (peg$currPos > peg$maxFailPos) {
+ peg$maxFailPos = peg$currPos;
+ peg$maxFailExpected = [];
+ }
+
+ peg$maxFailExpected.push(expected);
+ }
+
+ function peg$buildException(message, expected, pos) {
+ function cleanupExpected(expected) {
+ var i = 1;
+
+ expected.sort(function(a, b) {
+ if (a.description < b.description) {
+ return -1;
+ } else if (a.description > b.description) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+
+ while (i < expected.length) {
+ if (expected[i - 1] === expected[i]) {
+ expected.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ function buildMessage(expected, found) {
+ function stringEscape(s) {
+ function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
+
+ return s
+ .replace(/\\/g, '\\\\')
+ .replace(/"/g, '\\"')
+ .replace(/\x08/g, '\\b')
+ .replace(/\t/g, '\\t')
+ .replace(/\n/g, '\\n')
+ .replace(/\f/g, '\\f')
+ .replace(/\r/g, '\\r')
+ .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
+ .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
+ .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
+ .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
+ }
+
+ var expectedDescs = new Array(expected.length),
+ expectedDesc, foundDesc, i;
+
+ for (i = 0; i < expected.length; i++) {
+ expectedDescs[i] = expected[i].description;
+ }
+
+ expectedDesc = expected.length > 1
+ ? expectedDescs.slice(0, -1).join(", ")
+ + " or "
+ + expectedDescs[expected.length - 1]
+ : expectedDescs[0];
+
+ foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
+
+ return "Expected " + expectedDesc + " but " + foundDesc + " found.";
+ }
+
+ var posDetails = peg$computePosDetails(pos),
+ found = pos < input.length ? input.charAt(pos) : null;
+
+ if (expected !== null) {
+ cleanupExpected(expected);
+ }
+
+ return new SyntaxError(
+ message !== null ? message : buildMessage(expected, found),
+ expected,
+ found,
+ pos,
+ posDetails.line,
+ posDetails.column
+ );
+ }
+
+ function peg$parseline() {
+ var s0, s1, s2, s3;
+
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 4) === peg$c1) {
+ s1 = peg$c1;
+ peg$currPos += 4;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c2); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsekeyword1();
+ if (s2 === peg$FAILED) {
+ s2 = peg$parsekeyword2();
+ if (s2 === peg$FAILED) {
+ s2 = peg$parsekeywordLocale();
+ }
+ }
+ if (s2 !== peg$FAILED) {
+ if (input.charCodeAt(peg$currPos) === 10) {
+ s3 = peg$c4;
+ peg$currPos++;
+ } else {
+ s3 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c5); }
+ }
+ if (s3 === peg$FAILED) {
+ s3 = peg$c3;
+ }
+ if (s3 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c6(s2);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+
+ return s0;
+ }
+
+ function peg$parsewhitespace() {
+ var s0, s1;
+
+ s0 = [];
+ if (peg$c8.test(input.charAt(peg$currPos))) {
+ s1 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c9); }
+ }
+ if (s1 !== peg$FAILED) {
+ while (s1 !== peg$FAILED) {
+ s0.push(s1);
+ if (peg$c8.test(input.charAt(peg$currPos))) {
+ s1 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c9); }
+ }
+ }
+ } else {
+ s0 = peg$c0;
+ }
+
+ return s0;
+ }
+
+ function peg$parsenon_whitespace() {
+ var s0, s1, s2;
+
+ s0 = peg$currPos;
+ s1 = [];
+ if (peg$c10.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
+ }
+ if (s2 !== peg$FAILED) {
+ while (s2 !== peg$FAILED) {
+ s1.push(s2);
+ if (peg$c10.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c11); }
+ }
+ }
+ } else {
+ s1 = peg$c0;
+ }
+ if (s1 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c12(s1);
+ }
+ s0 = s1;
+
+ return s0;
+ }
+
+ function peg$parsenon_newline() {
+ var s0, s1, s2;
+
+ s0 = peg$currPos;
+ s1 = [];
+ if (peg$c13.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c14); }
+ }
+ if (s2 !== peg$FAILED) {
+ while (s2 !== peg$FAILED) {
+ s1.push(s2);
+ if (peg$c13.test(input.charAt(peg$currPos))) {
+ s2 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s2 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c14); }
+ }
+ }
+ } else {
+ s1 = peg$c0;
+ }
+ if (s1 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c12(s1);
+ }
+ s0 = s1;
+
+ return s0;
+ }
+
+ function peg$parsekeyword1() {
+ var s0, s1, s2, s3;
+
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 11) === peg$c15) {
+ s1 = peg$c15;
+ peg$currPos += 11;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c16); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c17) {
+ s1 = peg$c17;
+ peg$currPos += 7;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c18); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c19) {
+ s1 = peg$c19;
+ peg$currPos += 5;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c20); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c21) {
+ s1 = peg$c21;
+ peg$currPos += 4;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c22); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c23) {
+ s1 = peg$c23;
+ peg$currPos += 7;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c24); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 10) === peg$c25) {
+ s1 = peg$c25;
+ peg$currPos += 10;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c26); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 5) === peg$c27) {
+ s1 = peg$c27;
+ peg$currPos += 5;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c28); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c29) {
+ s1 = peg$c29;
+ peg$currPos += 9;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c30); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c31) {
+ s1 = peg$c31;
+ peg$currPos += 7;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c32); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 6) === peg$c33) {
+ s1 = peg$c33;
+ peg$currPos += 6;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c34); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 9) === peg$c35) {
+ s1 = peg$c35;
+ peg$currPos += 9;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c36); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 7) === peg$c37) {
+ s1 = peg$c37;
+ peg$currPos += 7;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c38); }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsewhitespace();
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parsenon_newline();
+ if (s3 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c39(s1, s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+
+ return s0;
+ }
+
+ function peg$parsekeyword2() {
+ var s0, s1, s2, s3, s4, s5;
+
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 8) === peg$c40) {
+ s1 = peg$c40;
+ peg$currPos += 8;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c41); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$parsewhitespace();
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parsenon_whitespace();
+ if (s3 !== peg$FAILED) {
+ s4 = peg$parsewhitespace();
+ if (s4 !== peg$FAILED) {
+ s5 = peg$parsenon_newline();
+ if (s5 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c42(s1, s3, s5);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+
+ return s0;
+ }
+
+ function peg$parsekeywordLocale() {
+ var s0, s1, s2, s3, s4, s5, s6;
+
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 11) === peg$c43) {
+ s1 = peg$c43;
+ peg$currPos += 11;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c44); }
+ }
+ if (s1 === peg$FAILED) {
+ if (input.substr(peg$currPos, 4) === peg$c45) {
+ s1 = peg$c45;
+ peg$currPos += 4;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c46); }
+ }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = peg$currPos;
+ s3 = peg$currPos;
+ if (input.charCodeAt(peg$currPos) === 58) {
+ s4 = peg$c47;
+ peg$currPos++;
+ } else {
+ s4 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c48); }
+ }
+ if (s4 !== peg$FAILED) {
+ s5 = [];
+ if (peg$c49.test(input.charAt(peg$currPos))) {
+ s6 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s6 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c50); }
+ }
+ if (s6 !== peg$FAILED) {
+ while (s6 !== peg$FAILED) {
+ s5.push(s6);
+ if (peg$c49.test(input.charAt(peg$currPos))) {
+ s6 = input.charAt(peg$currPos);
+ peg$currPos++;
+ } else {
+ s6 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c50); }
+ }
+ }
+ } else {
+ s5 = peg$c0;
+ }
+ if (s5 !== peg$FAILED) {
+ s4 = [s4, s5];
+ s3 = s4;
+ } else {
+ peg$currPos = s3;
+ s3 = peg$c0;
+ }
+ } else {
+ peg$currPos = s3;
+ s3 = peg$c0;
+ }
+ if (s3 === peg$FAILED) {
+ s3 = peg$c3;
+ }
+ if (s3 !== peg$FAILED) {
+ s3 = input.substring(s2, peg$currPos);
+ }
+ s2 = s3;
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parsewhitespace();
+ if (s3 !== peg$FAILED) {
+ s4 = peg$parsenon_newline();
+ if (s4 !== peg$FAILED) {
+ peg$reportedPos = s0;
+ s1 = peg$c51(s1, s2, s4);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$c0;
+ }
+
+ return s0;
+ }
+
+ peg$result = peg$startRuleFunction();
+
+ if (peg$result !== peg$FAILED && peg$currPos === input.length) {
+ return peg$result;
+ } else {
+ if (peg$result !== peg$FAILED && peg$currPos < input.length) {
+ peg$fail({ type: "end", description: "end of input" });
+ }
+
+ throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
+ }
+}
diff --git a/peg.txt b/peg.txt
new file mode 100644
index 0000000..7dc4fa5
--- /dev/null
+++ b/peg.txt
@@ -0,0 +1,85 @@
+// PEG grammar for parsing user script metadata
+// http://pegjs.majda.cz/online
+
+/*
+Test value:
+
+// ==UserScript==
+// @name Metadata Test
+// @name:de Auf deutsch bitte!
+// @namespace test
+// @description Test value including all metas.
+// @version 1.2.3
+// @icon http://example.com/favicon.ico
+// @include http://example.com/*
+// @match http://example.net/*
+// @exclude http://example.com/foo
+// @run-at document-start
+// @grant none
+// @downloadURL http://example.org/foo.user.js
+// @updateURL http://example.org/foo.meta.js
+// @require http://example.net/library.js
+// @resource css http://example.net/library.css
+// ==/UserScript==
+
+*/
+
+/*
+// Uncomment to parse an entire metadata block.
+// I.E for testing/development.
+meta =
+ "// ==UserScript==\n"
+ lines:line*
+ "// ==/UserScript==" ("\n"?)
+ { return lines; }
+*/
+
+line =
+ "// @"
+ meta:(keyword1 / keyword2 / keywordLocale)
+ "\n"?
+ { return meta; }
+
+whitespace = [ \t\n]+
+non_whitespace =
+ val:[^ \t\n]+ { return val.join('');}
+non_newline =
+ val:[^\n]+ { return val.join('');}
+
+keyword1 =
+ keyword:(
+ "downloadURL" /
+ "exclude" /
+ "grant" /
+ "icon" /
+ "include" /
+ "installURL" /
+ "match" /
+ "namespace" /
+ "require" /
+ "run-at" /
+ "updateURL" /
+ "version"
+ )
+ whitespace
+ value:non_newline
+ { return {keyword:keyword, value:value}; }
+
+keyword2 =
+ keyword:("resource")
+ whitespace
+ value1:non_whitespace
+ whitespace
+ value2:non_newline
+ { return {keyword:keyword, value1:value1, value2:value2}; }
+
+keywordLocale
+ = keyword:(
+ "description" /
+ "name"
+ )
+ locale:$(":" [a-zA-Z-]+)?
+ whitespace
+ value:non_newline
+ { return {keyword:keyword, locale:locale, value:value}; }
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/greasemonkey.git
More information about the Pkg-mozext-commits
mailing list