From ec581409ec38fdb3354d258a908765e811148cfc Mon Sep 17 00:00:00 2001 From: David Dohan Date: Mon, 10 Oct 2016 21:04:54 -0700 Subject: [PATCH] Basic exporting completed --- OrgView.js | 2 +- org/org.js | 160 +++- org/org_parser.js | 2130 ++++++++++++++++++++++++++++++++++++++++++ org/org_parser.pegjs | 1 + test/org.js | 49 +- 5 files changed, 2300 insertions(+), 42 deletions(-) create mode 100644 org/org_parser.js diff --git a/OrgView.js b/OrgView.js index a5facca..32adf6f 100644 --- a/OrgView.js +++ b/OrgView.js @@ -111,7 +111,7 @@ function side_menu(field, state) { function createTestDoc() { return Parser.parse( - '* DONE [#A] 1. I did this :project:\nSCHEDULED: <2016-06-05 Sun>\n:LOGBOOK:\nCLOCK: [2016-06-03 Fri 18:00]--[2016-06-03 Fri 19:30] => 1:30\n- I did MORE of it\nCLOCK: [2016-06-02 Thu 18:00]--[2016-06-02 Thu 19:00] => 1:00\n- I did part of it!\n:END:\n** 1.1 Look at all\n** 1.2 Of these headlines\n*** 1.2.1 Wow such hierarchy\n**** TODO 1.2.1.1 much test\n* 2. Work :work:\n** TODO [#A] 2.1 Do this or you lose your job!\nSCHEDULED: <2016-06-04 Sat> DEADLINE: <2016-06-06 Mon>\n*** 2.1.1 You should probably\n** TODO 2.2 so many things to do\n** TODO 2.3 and so little time\nSCHEDULED: <2016-06-06 Mon>\n** TODO 2.4 to do them all\n** DONE 2.5 Except this one. You did this one.\n** DONE 2.6 important tasks\nCLOSED: [2016-06-03 Fri 14:59]\n* 3. Home :home:\n** TODO 3.1 Remember garbage day?\nSCHEDULED: <2016-06-16 Thu +1w>\n:PROPERTIES:\n:LAST_REPEAT: [2016-06-03 Fri 21:32]\n:END:\n:LOGBOOK:\n- State \"DONE\" from \"TODO\" [2016-06-03 Fri 21:32]\n:END:\n** TODO 3.2 You should go to that thing\nSCHEDULED: <2016-06-13 Mon 20:00>\n*** DONE 3.2.1 Wow go buy some gifts or something \nCLOSED: [2016-06-11 Sat 21:33] DEADLINE: <2016-06-12 Sun>\n* 4. hobbies\n** 4.1 hobby #1\n*** TODO 4.1.1 Things and stuff hobby #1\n** 4.2 hobby #2\n*** TODO 4.2.1 Things and stuff hobby #2\n** 4.3 hobby #3\n*** TODO 4.3.1 Things and stuff hobby #3\n** 4.4 hobby #4\n*** TODO 4.4.1 Things and stuff hobby #4\n**** TODO this one has lots of nesting\n***** TODO and many children\n***** TODO to make the tree traversal complex\n***** TODO Although not all tasks are TODO here\n***** DONE Like this one. This one is done' + '* DONE [#A] 1. I did this :project:\nSCHEDULED: <2016-06-05 Sun>\n:LOGBOOK:\nCLOCK: [2016-06-03 Fri 18:00]--[2016-06-03 Fri 19:30] => 1:30\n- I did MORE of it\nCLOCK: [2016-06-02 Thu 18:00]--[2016-06-02 Thu 19:00] => 1:00\n- I did part of it!\n:END:\n** 1.1 Look at all\n** 1.2 Of these headlines\n*** 1.2.1 Wow such hierarchy\n**** TODO 1.2.1.1 much test\n* 2. Work :work:\n** TODO [#A] 2.1 Do this or you lose your job!\nSCHEDULED: <2016-06-04 Sat> DEADLINE: <2016-06-06 Mon>\n*** 2.1.1 You should probably\n** TODO 2.2 so many things to do\n** TODO 2.3 and so little time\nSCHEDULED: <2016-06-06 Mon>\n** TODO 2.4 to do them all\n** DONE 2.5 Except this one. You did this one.\n** DONE 2.6 important tasks\nCLOSED: [2016-06-03 Fri 14:59]\n* 3. Home :home:\n** TODO 3.1 Remember garbage day?\nSCHEDULED: <2016-06-16 Thu +1w>\n:PROPERTIES:\n:LAST_REPEAT: [2016-06-03 Fri 21:32]\n:END:\n:LOGBOOK:\n- State \"DONE\" from \"TODO\" [2016-06-03 Fri 21:32]\n:END:\n** TODO 3.2 You should go to that thing\nSCHEDULED: <2016-06-13 Mon 20:00>\n*** DONE 3.2.1 Wow go buy some gifts or something \nDEADLINE: <2016-06-12 Sun> CLOSED: [2016-06-11 Sat 21:33]\n* 4. hobbies\n** 4.1 hobby #1\n*** TODO 4.1.1 Things and stuff hobby #1\n** 4.2 hobby #2\n*** TODO 4.2.1 Things and stuff hobby #2\n** 4.3 hobby #3\n*** TODO 4.3.1 Things and stuff hobby #3\n** 4.4 hobby #4\n*** TODO 4.4.1 Things and stuff hobby #4\n**** TODO this one has lots of nesting\n***** TODO and many children\n***** TODO to make the tree traversal complex\n***** TODO Although not all tasks are TODO here\n***** DONE Like this one. This one is done' ); } diff --git a/org/org.js b/org/org.js index 8de3428..ba4077e 100644 --- a/org/org.js +++ b/org/org.js @@ -70,7 +70,7 @@ export function tsFromDate(date) { day: date.getDate(), hour: date.getHours(), minute: date.getMinutes() - }); + }); } function nowTs() { @@ -152,14 +152,14 @@ export function numChildren(cursor) { /***** Cursor logic *****/ /* - Return the path corresponding to cursor + Return the path corresponding to cursor */ export function getPath(cursor) { return cursor._keyPath; } /* - Create a cursor into `doc` with `path` + Create a cursor into `doc` with `path` */ export function createCursor(doc, path = []) { return Cursor.from(doc, path, () => {}); @@ -169,7 +169,7 @@ export function createCursor(doc, path = []) { /***** Traversing tree *****/ /* - Return the root document node for a cursor + Return the root document node for a cursor */ export function getDoc(cursor) { return createCursor(cursor._rootData); @@ -392,15 +392,15 @@ function tsValue(str) { // Named days switch (str) { - case 'yesterday': - addDays(-1); - return date; - case 'today': - return date; - case 'tomorrow': - addDays(1); - return date; - default: + case 'yesterday': + addDays(-1); + return date; + case 'today': + return date; + case 'tomorrow': + addDays(1); + return date; + default: } // # offsets, e.g. 1y, 2w, -3d @@ -455,7 +455,7 @@ function createFilter(str) { } else if (type === 'object') { op = {'eq': (a,b) => a == b, 'neq': (a,b) => a != b - }[operatorStr]; + }[operatorStr]; } if (op == null) { @@ -550,32 +550,142 @@ export function sort(nodes, property, comparator=null) { export function export_subtree(subtree) { /* Constructs a string representing given subtree as an org mode file */ - cur = subtree; - result = []; + let cur = subtree; + let result = []; while (!!cur) { - headline = printHeadline(cur); - result = result.concat(headline); + let exported = ''; + if (isDoc(cur)) { + exported = printDoc(cur); + } + + if (isHeadline(cur)) { + exported = printHeadline(cur); + } + + if (isSection(cur)) { + exported = printSection(cur); + } + + result.push(exported); cur = next(cur); } joined = result.join(''); - return joined.trim() + return joined.trim(); } +function printDoc(headline) { + // TODO(ddohan): Print doc level metadata + return ''; +} + +function printSection(section) { + if (!isSection(section)) { + return ''; + } + return getContent(section) + '\n' +} + + function printHeadline(headline) { if (!isHeadline(headline)) { - return []; + return '' } - return ['*'.repeat(level(headline)), ' ', getContent(headline), '\n']; -} + let result = ['*'.repeat(level(headline))]; + + keyword = getKeyword(headline); + priority = getPriority(headline); + content = getContent(headline); + tags = getTags(headline); -function printTags(headline) { + if (!!keyword) { + result.push(' '); + result.push(keyword); + } + + if (!!priority) { + result.push(' [#' + priority); + result.push(']'); + } + if (!!content) { + result.push(' '); + result.push(getContent(headline)); + } + + if (!!tags) { + if (tags.size > 0) { + result.push(' :'); + for (tag of tags.values()) { + result.push(tag); + result.push(':'); + } + } + } + + result.push('\n') + + let planning = printPlanning(headline) + if (planning) { + result.push(planning) + result.push('\n') + } + + result = result.join(''); + return result; } -function printContent(headline) { +function printPlanning(headline) { + scheduled = getScheduled(headline) + deadline = getDeadline(headline) + closed = getClosed(headline) + let result = [] + if (!!scheduled) { + result.push(['SCHEDULED: ', printTs(scheduled)].join('')) + } + if (!!deadline) { + result.push(['DEADLINE: ', printTs(deadline)].join('')) + } + if (!!closed) { + result.push(['CLOSED: ', printTs(closed)].join('')) + } + return result.join(' ') } -function printProps(headline) { +function printTs(ts) { + let result = [] + if (ts.active) { + result.push('<') + } else { + result.push('[') + } + + result.push(ts.year) + result.push('-') + result.push(ts.month) + result.push('-') + result.push(ts.day) + result.push(' ') + result.push(ts.dayname) + if (!!ts.hour) { + result.push(' ') + result.push(ts.hour) + result.push(':') + result.push(ts.minute) + } + + if (ts.repeater) { + let repeater = ts.repeater + result.push(' ') + result.push(repeater.mark) + result.push(repeater.value) + result.push(repeater.unit) + } + if (ts.active) { + result.push('>') + } else { + result.push(']') + } + return result.join('') } diff --git a/org/org_parser.js b/org/org_parser.js new file mode 100644 index 0000000..f7ea0a5 --- /dev/null +++ b/org/org_parser.js @@ -0,0 +1,2130 @@ +module.exports = (function() { + "use strict"; + + /* + * Generated by PEG.js 0.9.0. + * + * http://pegjs.org/ + */ + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } + } + + peg$subclass(peg$SyntaxError, Error); + + function peg$parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + parser = this, + + peg$FAILED = {}, + + peg$startRuleFunctions = { document: peg$parsedocument }, + peg$startRuleFunction = peg$parsedocument, + + peg$c0 = function(section, headlines) { + let cursor = doc; + if (!!section) { + cursor = Org.addChild(doc, section); + } + + for (let headline of headlines) { + cursor = Org.insertHeadline(cursor, headline); + } + return Org.getDoc(cursor); + }, + peg$c1 = "*", + peg$c2 = { type: "literal", value: "*", description: "\"*\"" }, + peg$c3 = " ", + peg$c4 = { type: "literal", value: " ", description: "\" \"" }, + peg$c5 = function(stars, keyword, priority, line, planning, body) { + + // TODO: Make much more robust to weird ordering in metadata (e.g. schedules after logbook) + + let children = !!body ? [body] : [] + + // Pull out any tags + // No backtracking in pegjs, so easier to do this way (also avoiding regex): + let re = /(.*?)( :([0-9a-zA-Z_@#%:]*):)?$/; + let result = re.exec(line); + let headline_content= result[1]; + let tag_string = result[3]; + let tags; + if (!!tag_string) { + tags = result[3].split(':') + } + + + return Org.headlineNode(stars.length, headline_content, children, + {keyword: keyword, + tags: tags, + priority: priority, + planning: planning}); + }, + peg$c6 = function(line) { return line; }, + peg$c7 = function(content) { return Org.sectionNode(content.join('\n')); }, + peg$c8 = "TODO", + peg$c9 = { type: "literal", value: "TODO", description: "\"TODO\"" }, + peg$c10 = "DONE", + peg$c11 = { type: "literal", value: "DONE", description: "\"DONE\"" }, + peg$c12 = "[#", + peg$c13 = { type: "literal", value: "[#", description: "\"[#\"" }, + peg$c14 = "]", + peg$c15 = { type: "literal", value: "]", description: "\"]\"" }, + peg$c16 = function(priority) { return priority; }, + peg$c17 = /^[0-9]/, + peg$c18 = { type: "class", value: "[0-9]", description: "[0-9]" }, + peg$c19 = "-", + peg$c20 = { type: "literal", value: "-", description: "\"-\"" }, + peg$c21 = function(year, month, day, dayname) { + return {year, month, day, dayname} + }, + peg$c22 = ":", + peg$c23 = { type: "literal", value: ":", description: "\":\"" }, + peg$c24 = function(hour, minute) { + return {hour, minute} + }, + peg$c25 = "+", + peg$c26 = { type: "literal", value: "+", description: "\"+\"" }, + peg$c27 = "++", + peg$c28 = { type: "literal", value: "++", description: "\"++\"" }, + peg$c29 = ".+", + peg$c30 = { type: "literal", value: ".+", description: "\".+\"" }, + peg$c31 = "--", + peg$c32 = { type: "literal", value: "--", description: "\"--\"" }, + peg$c33 = "h", + peg$c34 = { type: "literal", value: "h", description: "\"h\"" }, + peg$c35 = "d", + peg$c36 = { type: "literal", value: "d", description: "\"d\"" }, + peg$c37 = "w", + peg$c38 = { type: "literal", value: "w", description: "\"w\"" }, + peg$c39 = "m", + peg$c40 = { type: "literal", value: "m", description: "\"m\"" }, + peg$c41 = "y", + peg$c42 = { type: "literal", value: "y", description: "\"y\"" }, + peg$c43 = function(mark, value, tsunit) { + return new Org.Repeater({ + mark: mark, + value: value, + unit: tsunit + }) + }, + peg$c44 = function(entries) { + let entry; + let keywords = {}; + for (entry of entries) { + let type = entry['type'] + if (type in keywords) { + continue; + } + keywords[type] = entry['timestamp']; + } + return Immutable.Map(keywords); + }, + peg$c45 = function(entry) { return entry; }, + peg$c46 = "SCHEDULED: ", + peg$c47 = { type: "literal", value: "SCHEDULED: ", description: "\"SCHEDULED: \"" }, + peg$c48 = function(timestamp) { return {type: 'SCHEDULED', timestamp}; }, + peg$c49 = "DEADLINE: ", + peg$c50 = { type: "literal", value: "DEADLINE: ", description: "\"DEADLINE: \"" }, + peg$c51 = function(timestamp) { return {type: 'DEADLINE', timestamp}; }, + peg$c52 = "CLOSED: ", + peg$c53 = { type: "literal", value: "CLOSED: ", description: "\"CLOSED: \"" }, + peg$c54 = function(timestamp) { return {type: 'CLOSED', timestamp}; }, + peg$c55 = function(date, time, repeater) { + if (!!time) { + Object.assign(date, time) + } + return { + ...date, + repeater + } + }, + peg$c56 = function(date, ts1, ts2, repeater) { + let start = Object.assign({repeater: repeater}, date, ts1, repeater) + let stop = Object.assign({repeater: repeater}, date, ts2) + return { + start, + stop, + } + }, + peg$c57 = "<", + peg$c58 = { type: "literal", value: "<", description: "\"<\"" }, + peg$c59 = ">", + peg$c60 = { type: "literal", value: ">", description: "\">\"" }, + peg$c61 = function(start, stop) { return TsRange(true, start, stop); }, + peg$c62 = "[", + peg$c63 = { type: "literal", value: "[", description: "\"[\"" }, + peg$c64 = function(start, stop) { return TsRange(false, start, stop); }, + peg$c65 = function(range) { return TsRange(true, range.start, range.stop); }, + peg$c66 = function() { return TsRange(false, range.start, range.stop); }, + peg$c67 = function(ts) { return new Org.Timestamp({active: true, ...ts}); }, + peg$c68 = function(ts) { return new Org.Timestamp({active: false, ...ts}); }, + peg$c69 = /^[a-z]/, + peg$c70 = { type: "class", value: "[a-z]", description: "[a-z]" }, + peg$c71 = /^[A-Z]/, + peg$c72 = { type: "class", value: "[A-Z]", description: "[A-Z]" }, + peg$c73 = /^[!"#$%&'()*+,-.\/:;<=>?@[\\\]\^_`{|}~]/, + peg$c74 = { type: "class", value: "[!\"#$%&\\'()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~]", description: "[!\"#$%&\\'()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~]" }, + peg$c75 = /^[ \t]/, + peg$c76 = { type: "class", value: "[ \\t]", description: "[ \\t]" }, + peg$c77 = "\n", + peg$c78 = { type: "literal", value: "\n", description: "\"\\n\"" }, + peg$c79 = "\r", + peg$c80 = { type: "literal", value: "\r", description: "\"\\r\"" }, + peg$c81 = { type: "any", description: "any character" }, + peg$c82 = function(char) { return char }, + peg$c83 = function(chars) { return chars; }, + + peg$currPos = 0, + peg$savedPos = 0, + peg$posDetailsCache = [{ 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$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description) { + throw peg$buildException( + null, + [{ type: "other", description: description }], + input.substring(peg$savedPos, peg$currPos), + peg$computeLocation(peg$savedPos, peg$currPos) + ); + } + + function error(message) { + throw peg$buildException( + message, + null, + input.substring(peg$savedPos, peg$currPos), + peg$computeLocation(peg$savedPos, peg$currPos) + ); + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], + p, ch; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column, + seenCR: details.seenCR + }; + + while (p < pos) { + 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; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + 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, found, location) { + 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(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) + .replace(/[\u1000-\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."; + } + + if (expected !== null) { + cleanupExpected(expected); + } + + return new peg$SyntaxError( + message !== null ? message : buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parsedocument() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parsesection(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseheadline(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseheadline(); + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c0(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseheadline() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = []; + if (input.charCodeAt(peg$currPos) === 42) { + s2 = peg$c1; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (input.charCodeAt(peg$currPos) === 42) { + s2 = peg$c1; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + if (input.charCodeAt(peg$currPos) === 32) { + s3 = peg$c3; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (input.charCodeAt(peg$currPos) === 32) { + s3 = peg$c3; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsekeyword(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + s4 = []; + if (input.charCodeAt(peg$currPos) === 32) { + s5 = peg$c3; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + while (s5 !== peg$FAILED) { + s4.push(s5); + if (input.charCodeAt(peg$currPos) === 32) { + s5 = peg$c3; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + } + if (s4 !== peg$FAILED) { + s5 = peg$parsepriority(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + s6 = []; + if (input.charCodeAt(peg$currPos) === 32) { + s7 = peg$c3; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + while (s7 !== peg$FAILED) { + s6.push(s7); + if (input.charCodeAt(peg$currPos) === 32) { + s7 = peg$c3; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + } + if (s6 !== peg$FAILED) { + s7 = peg$parseline(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + s8 = peg$parseplanning(); + if (s8 === peg$FAILED) { + s8 = null; + } + if (s8 !== peg$FAILED) { + s9 = peg$parsesection(); + if (s9 === peg$FAILED) { + s9 = null; + } + if (s9 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c5(s1, s3, s5, s7, s8, s9); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsesectionline() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 42) { + s2 = peg$c1; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseline(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c6(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsesection() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parsesectionline(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsesectionline(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c7(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsekeyword() { + var s0; + + if (input.substr(peg$currPos, 4) === peg$c8) { + s0 = peg$c8; + peg$currPos += 4; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c10) { + s0 = peg$c10; + peg$currPos += 4; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c11); } + } + } + + return s0; + } + + function peg$parsepriority() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c12) { + s1 = peg$c12; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c13); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseupperletter(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c16(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseyear() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + if (peg$c17.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s2 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s3 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s4 !== peg$FAILED) { + s1 = [s1, s2, s3, s4]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsemonth() { + var s0, s1, s2; + + s0 = peg$currPos; + if (peg$c17.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseday() { + var s0, s1, s2; + + s0 = peg$currPos; + if (peg$c17.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsedayname() { + var s0, s1; + + s0 = []; + s1 = peg$parseletter(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parseletter(); + } + + return s0; + } + + function peg$parsedate() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseyear(); + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s2 = peg$c19; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + s4 = peg$parsemonth(); + if (s4 !== peg$FAILED) { + s3 = input.substring(s3, peg$currPos); + } else { + s3 = s4; + } + if (s3 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s4 = peg$c19; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + s6 = peg$parseday(); + if (s6 !== peg$FAILED) { + s5 = input.substring(s5, peg$currPos); + } else { + s5 = s6; + } + if (s5 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 32) { + s6 = peg$c3; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + if (s6 !== peg$FAILED) { + s7 = peg$currPos; + s8 = []; + s9 = peg$parseletter(); + while (s9 !== peg$FAILED) { + s8.push(s9); + s9 = peg$parseletter(); + } + if (s8 !== peg$FAILED) { + s7 = input.substring(s7, peg$currPos); + } else { + s7 = s8; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c21(s1, s3, s5, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsehour() { + var s0, s1, s2; + + s0 = peg$currPos; + if (peg$c17.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + } + + return s0; + } + + function peg$parsetime() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsehour(); + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s2 = peg$c22; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c23); } + } + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + s4 = peg$currPos; + if (peg$c17.test(input.charAt(peg$currPos))) { + s5 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s5 !== peg$FAILED) { + if (peg$c17.test(input.charAt(peg$currPos))) { + s6 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s3 = input.substring(s3, peg$currPos); + } else { + s3 = s4; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c24(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsemark() { + var s0; + + if (input.charCodeAt(peg$currPos) === 43) { + s0 = peg$c25; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c26); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c27) { + s0 = peg$c27; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c28); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c29) { + s0 = peg$c29; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c30); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s0 = peg$c19; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c31) { + s0 = peg$c31; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + } + } + } + } + + return s0; + } + + function peg$parsetsunit() { + var s0; + + if (input.charCodeAt(peg$currPos) === 104) { + s0 = peg$c33; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c34); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 100) { + s0 = peg$c35; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c36); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 119) { + s0 = peg$c37; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 109) { + s0 = peg$c39; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c40); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 121) { + s0 = peg$c41; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c42); } + } + } + } + } + } + + return s0; + } + + function peg$parserepeater() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsemark(); + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + s3 = []; + s4 = peg$parsenumber(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsenumber(); + } + if (s3 !== peg$FAILED) { + s2 = input.substring(s2, peg$currPos); + } else { + s2 = s3; + } + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + s4 = peg$parsetsunit(); + if (s4 !== peg$FAILED) { + s3 = input.substring(s3, peg$currPos); + } else { + s3 = s4; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c43(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseplanning() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parsepadded_planning_entry(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsepadded_planning_entry(); + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEOL(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c44(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsepadded_planning_entry() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parsespaces(); + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsespaces(); + } + if (s1 !== peg$FAILED) { + s2 = peg$parseplanning_entry(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsespaces(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsespaces(); + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c45(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseplanning_entry() { + var s0; + + s0 = peg$parsescheduled(); + if (s0 === peg$FAILED) { + s0 = peg$parsedeadline(); + if (s0 === peg$FAILED) { + s0 = peg$parseclosed(); + } + } + + return s0; + } + + function peg$parsescheduled() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 11) === peg$c46) { + s1 = peg$c46; + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c47); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets_block(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c48(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsedeadline() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 10) === peg$c49) { + s1 = peg$c49; + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets_block(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c51(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseclosed() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 8) === peg$c52) { + s1 = peg$c52; + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c53); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets_block(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c54(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsets() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parsedate(); + if (s1 !== peg$FAILED) { + s2 = []; + if (input.charCodeAt(peg$currPos) === 32) { + s3 = peg$c3; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (input.charCodeAt(peg$currPos) === 32) { + s3 = peg$c3; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsetime(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + s4 = []; + if (input.charCodeAt(peg$currPos) === 32) { + s5 = peg$c3; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + while (s5 !== peg$FAILED) { + s4.push(s5); + if (input.charCodeAt(peg$currPos) === 32) { + s5 = peg$c3; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c4); } + } + } + if (s4 !== peg$FAILED) { + s5 = peg$parserepeater(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c55(s1, s3, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsets_range() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parsedate(); + if (s1 !== peg$FAILED) { + s2 = peg$parsetime(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s3 = peg$c19; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parsetime(); + if (s4 !== peg$FAILED) { + s5 = peg$parserepeater(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c56(s1, s2, s4, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsets_block() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 60) { + s1 = peg$c57; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s3 = peg$c59; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + if (s3 !== peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c31) { + s4 = peg$c31; + peg$currPos += 2; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 60) { + s5 = peg$c57; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsets(); + if (s6 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s7 = peg$c59; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c61(s2, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 91) { + s1 = peg$c62; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c63); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c31) { + s4 = peg$c31; + peg$currPos += 2; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 91) { + s5 = peg$c62; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c63); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsets(); + if (s6 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s7 = peg$c14; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c64(s2, s6); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 60) { + s1 = peg$c57; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets_range(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s3 = peg$c59; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c65(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 91) { + s1 = peg$c62; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c63); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets_range(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c66(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 60) { + s1 = peg$c57; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s3 = peg$c59; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c67(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 91) { + s1 = peg$c62; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c63); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsets(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c68(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + } + } + + return s0; + } + + function peg$parsenumber() { + var s0; + + if (peg$c17.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + + return s0; + } + + function peg$parselowerletter() { + var s0; + + if (peg$c69.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c70); } + } + + return s0; + } + + function peg$parseupperletter() { + var s0; + + if (peg$c71.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c72); } + } + + return s0; + } + + function peg$parseletter() { + var s0; + + s0 = peg$parselowerletter(); + if (s0 === peg$FAILED) { + s0 = peg$parseupperletter(); + } + + return s0; + } + + function peg$parsealphanum() { + var s0; + + s0 = peg$parsenumber(); + if (s0 === peg$FAILED) { + s0 = peg$parseletter(); + } + + return s0; + } + + function peg$parsepunctuation() { + var s0; + + if (peg$c73.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c74); } + } + + return s0; + } + + function peg$parsespaces() { + var s0; + + if (peg$c75.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c76); } + } + + return s0; + } + + function peg$parsenewline() { + var s0, s1, s2; + + if (input.charCodeAt(peg$currPos) === 10) { + s0 = peg$c77; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 13) { + s1 = peg$c79; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 10) { + s2 = peg$c77; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsewhitespace() { + var s0; + + s0 = peg$parsespaces(); + if (s0 === peg$FAILED) { + s0 = peg$parsenewline(); + } + + return s0; + } + + function peg$parseEOF() { + var s0, s1; + + s0 = peg$currPos; + peg$silentFails++; + if (input.length > peg$currPos) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + peg$silentFails--; + if (s1 === peg$FAILED) { + s0 = void 0; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsenotnewline() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsenewline(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c82(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseEOL() { + var s0; + + s0 = peg$parsenewline(); + if (s0 === peg$FAILED) { + s0 = peg$parseEOF(); + } + + return s0; + } + + function peg$parseline() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = []; + s3 = peg$parsenotnewline(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsenotnewline(); + } + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsenewline(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c83(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + s2 = []; + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEOF(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c83(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + + let Immutable = require('immutable'); + let Org = require('./org'); + let doc = Org.createDoc(); + + let TsRange = (active, start, stop) => { + start = new Org.Timestamp({active: true, ...start}) + stop = new Org.Timestamp({active: true, ...stop}) + return Immutable.List([start, stop]); + } + + + 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 < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } + } + + return { + SyntaxError: peg$SyntaxError, + parse: peg$parse + }; +})(); diff --git a/org/org_parser.pegjs b/org/org_parser.pegjs index b2aa741..ef65add 100644 --- a/org/org_parser.pegjs +++ b/org/org_parser.pegjs @@ -87,6 +87,7 @@ repeater = mark:$mark value:$number* tsunit:$tsunit { }) } +// SCHEDULED/DEADLINE/CLOSED timestamps planning = entries:padded_planning_entry* EOL { let entry; let keywords = {}; diff --git a/test/org.js b/test/org.js index 6aebc64..ff5e6b6 100644 --- a/test/org.js +++ b/test/org.js @@ -9,11 +9,16 @@ let { Set } = Immutable; -let doc_headlines = "* 1\n** 1.1\n** 1.2\n*** 1.2.1\n*** 1.2.2\n** 1.3\n* 2\n** 2.1" -let doc_just_headlines = "** 1\n*** 2\n* 3\n" -let doc_tags = "* TODO [#A] 1 :tag:tag2:" -let doc_scheduled = "* test\nSCHEDULED: <2016-06-01 Wed +1w> DEADLINE: <2016-06-02 Thu 8:00>\n" -let doc_timestamps = "* TODO 1\n** DONE 1.1\nSCHEDULED: <2016-09-01 Wed +1w> DEADLINE: <2016-06-02 Thu 8:00>\n*** TODO 1.1.1\n* 2\nDEADLINE: <2016-07-10 Fri> SCHEDULED: <2016-06-05 Fri>\n* TODO 3\n* DONE 4" +let doc_headlines = "* 1\n** 1.1\n** 1.2\n*** 1.2.1\n*** 1.2.2\n** 1.3\n* 2\n** 2.1"; +let doc_just_headlines = "** 1\n*** 2\n* 3\n"; +let doc_tags = "* TODO [#A] 1 :tag:tag2:"; +let doc_scheduled = "* test\nSCHEDULED: <2016-06-01 Wed +1w> DEADLINE: <2016-06-02 Thu 8:00>\n"; +let doc_timestamps = "* TODO 1\n** DONE 1.1\nSCHEDULED: <2016-09-01 Wed +1w> DEADLINE: <2016-06-02 Thu 8:00>\n*** TODO 1.1.1\n* 2\nDEADLINE: <2016-07-10 Fri> SCHEDULED: <2016-06-05 Fri>\n* TODO 3\n* DONE 4"; +let doc_timestamps_reformatted = "* TODO 1\n** DONE 1.1\nSCHEDULED: <2016-09-01 Wed +1w> DEADLINE: <2016-06-02 Thu 8:00>\n*** TODO 1.1.1\n* 2\nSCHEDULED: <2016-06-05 Fri> DEADLINE: <2016-07-10 Fri>\n* TODO 3\n* DONE 4"; +let doc_with_sections = "* 1\nlots of stuff\n going on \n in these sections** 1.1\n** 1.2\nso many great notes \n*** 1.2.1\n*** 1.2.2\n** 1.3\n* 2\n** 2.1"; + +// Large test doc used to test UI so far +let doc_large = "* DONE [#A] 1. I did this :project:\nSCHEDULED: <2016-06-05 Sun>\n:LOGBOOK:\nCLOCK: [2016-06-03 Fri 18:00]--[2016-06-03 Fri 19:30] => 1:30\n- I did MORE of it\nCLOCK: [2016-06-02 Thu 18:00]--[2016-06-02 Thu 19:00] => 1:00\n- I did part of it!\n:END:\n** 1.1 Look at all\n** 1.2 Of these headlines\n*** 1.2.1 Wow such hierarchy\n**** TODO 1.2.1.1 much test\n* 2. Work :work:\n** TODO [#A] 2.1 Do this or you lose your job!\nSCHEDULED: <2016-06-04 Sat> DEADLINE: <2016-06-06 Mon>\n*** 2.1.1 You should probably\n** TODO 2.2 so many things to do\n** TODO 2.3 and so little time\nSCHEDULED: <2016-06-06 Mon>\n** TODO 2.4 to do them all\n** DONE 2.5 Except this one. You did this one.\n** DONE 2.6 important tasks\nCLOSED: [2016-06-03 Fri 14:59]\n* 3. Home :home:\n** TODO 3.1 Remember garbage day?\nSCHEDULED: <2016-06-16 Thu +1w>\n:PROPERTIES:\n:LAST_REPEAT: [2016-06-03 Fri 21:32]\n:END:\n:LOGBOOK:\n- State \"DONE\" from \"TODO\" [2016-06-03 Fri 21:32]\n:END:\n** TODO 3.2 You should go to that thing\nSCHEDULED: <2016-06-13 Mon 20:00>\n*** DONE 3.2.1 Wow go buy some gifts or something \nDEADLINE: <2016-06-12 Sun> CLOSED: [2016-06-11 Sat 21:33]\n* 4. hobbies\n** 4.1 hobby #1\n*** TODO 4.1.1 Things and stuff hobby #1\n** 4.2 hobby #2\n*** TODO 4.2.1 Things and stuff hobby #2\n** 4.3 hobby #3\n*** TODO 4.3.1 Things and stuff hobby #3\n** 4.4 hobby #4\n*** TODO 4.4.1 Things and stuff hobby #4\n**** TODO this one has lots of nesting\n***** TODO and many children\n***** TODO to make the tree traversal complex\n***** TODO Although not all tasks are TODO here\n***** DONE Like this one. This one is done"; function node(type, content, children = List()) { return { @@ -181,22 +186,34 @@ describe('search and sort', () => { }); }); -describe.only('export', () => { +describe('export', () => { let test_export = (string) => { - parsed = parser.parse(string) - exported = Org.export_subtree(parsed) - expect(exported).to.eql(string.trim()) + parsed = parser.parse(string); + exported = Org.export_subtree(parsed); + expect(exported).to.eql(string.trim()); + }; + + let test_reformat = (string, out_string) => { + parsed = parser.parse(string); + exported = Org.export_subtree(parsed); + expect(exported).to.eql(out_string); }; it('can export headlines', () => { - test_export(doc_headlines) - test_export(doc_just_headlines) + // test_export(doc_headlines); + test_export(doc_just_headlines); }); it('can export tags', () => { - test_export(doc_tags) + test_export(doc_tags); + }); + it('can export timestamps', () => { + test_export(doc_scheduled); + test_reformat(doc_timestamps, doc_timestamps_reformatted); + }); + it('can export sections', () => { + test_export(doc_with_sections); + }); + it('can export large doc ', () => { + test_export(doc_large); }); - // it('can export timestamps', () => { - // test_export(doc_scheduled) - // test_export(doc_timestamps) - // }); });