Home Identifier Source Repository

src/lib/parse-hanson-string.js

"use strict";
var _extends = Object.assign || function(target) {
	for (var i = 1; i < arguments.length; i++) {
		var source = arguments[i];
		for (var key in source) {
			if (Object.prototype.hasOwnProperty.call(source, key)) {
				target[key] = source[key];
			}
		}
	}
	return target;
};
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 = {
				Start: peg$parseStart
			},
			peg$startRuleFunction = peg$parseStart,
			peg$c0 = {
				type: "other",
				description: "expression"
			},
			peg$c1 = function peg$c1(expr) {
				return expr;
			},
			peg$c2 = "s",
			peg$c3 = {
				type: "literal",
				value: "s",
				description: "\"s\""
			},
			peg$c4 = "course",
			peg$c5 = {
				type: "literal",
				value: "course",
				description: "\"course\""
			},
			peg$c6 = "where",
			peg$c7 = {
				type: "literal",
				value: "where",
				description: "\"where\""
			},
			peg$c8 = function peg$c8(count, where) {
				return {
					$type: 'where',
					$count: count,
					$where: where
				};
			},
			peg$c9 = "only",
			peg$c10 = {
				type: "literal",
				value: "only",
				description: "\"only\""
			},
			peg$c11 = "courses",
			peg$c12 = {
				type: "literal",
				value: "courses",
				description: "\"courses\""
			},
			peg$c13 = function peg$c13(where) {
				return {
					$where: where
				};
			},
			peg$c14 = "from",
			peg$c15 = {
				type: "literal",
				value: "from",
				description: "\"from\""
			},
			peg$c16 = function peg$c16(of) {
				return {
					$of: of
				};
			},
			peg$c17 = function peg$c17(filter) {
				return _extends({}, filter, {
					$type: 'filter'
				});
			},
			peg$c18 = "occurrence",
			peg$c19 = {
				type: "literal",
				value: "occurrence",
				description: "\"occurrence\""
			},
			peg$c20 = "of",
			peg$c21 = {
				type: "literal",
				value: "of",
				description: "\"of\""
			},
			peg$c22 = function peg$c22(count, course) {
				return {
					$type: 'occurrence',
					$count: count,
					$course: course.$course
				};
			},
			peg$c23 = "{",
			peg$c24 = {
				type: "literal",
				value: "{",
				description: "\"{\""
			},
			peg$c25 = "}",
			peg$c26 = {
				type: "literal",
				value: "}",
				description: "\"}\""
			},
			peg$c27 = function peg$c27(q) {
				return q;
			},
			peg$c28 = {
				type: "other",
				description: "qualification-or"
			},
			peg$c29 = "|",
			peg$c30 = {
				type: "literal",
				value: "|",
				description: "\"|\""
			},
			peg$c31 = function peg$c31(lhs, rhs) {
				return {
					$type: 'boolean',
					$or: [lhs].concat('$or' in rhs ? rhs.$or : [rhs])
				};
			},
			peg$c32 = {
				type: "other",
				description: "qualification-and"
			},
			peg$c33 = "&",
			peg$c34 = {
				type: "literal",
				value: "&",
				description: "\"&\""
			},
			peg$c35 = function peg$c35(lhs, rhs) {
				return {
					$type: 'boolean',
					$and: [lhs].concat('$and' in rhs ? rhs.$and : [rhs])
				};
			},
			peg$c36 = function peg$c36(key, op, f, q) {
				return _extends({}, f, {
					$where: q
				});
			},
			peg$c37 = function peg$c37(key, op, value) {
				return {
					$type: 'qualification',
					$key: key,
					$operator: op,
					$value: value
				};
			},
			peg$c38 = function peg$c38(value) {
				return value;
			},
			peg$c39 = function peg$c39(lhs, rhs) {
				return {
					$type: 'boolean',
					$or: [lhs].concat(rhs.$or ? rhs.$or : [rhs])
				};
			},
			peg$c40 = function peg$c40(lhs, rhs) {
				return {
					$type: 'boolean',
					$and: [lhs].concat(rhs.$and ? rhs.$and : [rhs])
				};
			},
			peg$c41 = function peg$c41(num) {
				return num;
			},
			peg$c42 = /^[a-z0-9_\-]/i,
			peg$c43 = {
				type: "class",
				value: "[a-z0-9_\\-]i",
				description: "[a-z0-9_\\-]i"
			},
			peg$c44 = function peg$c44(word) {
				return word.join('');
			},
			peg$c45 = function peg$c45(name, prop) {
				return {
					$name: name,
					$prop: prop,
					$type: 'function'
				};
			},
			peg$c46 = "<=",
			peg$c47 = {
				type: "literal",
				value: "<=",
				description: "\"<=\""
			},
			peg$c48 = function peg$c48() {
				return '$lte';
			},
			peg$c49 = "<",
			peg$c50 = {
				type: "literal",
				value: "<",
				description: "\"<\""
			},
			peg$c51 = function peg$c51() {
				return '$lt';
			},
			peg$c52 = "==",
			peg$c53 = {
				type: "literal",
				value: "==",
				description: "\"==\""
			},
			peg$c54 = "=",
			peg$c55 = {
				type: "literal",
				value: "=",
				description: "\"=\""
			},
			peg$c56 = function peg$c56() {
				return '$eq';
			},
			peg$c57 = ">=",
			peg$c58 = {
				type: "literal",
				value: ">=",
				description: "\">=\""
			},
			peg$c59 = function peg$c59() {
				return '$gte';
			},
			peg$c60 = ">",
			peg$c61 = {
				type: "literal",
				value: ">",
				description: "\">\""
			},
			peg$c62 = function peg$c62() {
				return '$gt';
			},
			peg$c63 = "!=",
			peg$c64 = {
				type: "literal",
				value: "!=",
				description: "\"!=\""
			},
			peg$c65 = function peg$c65() {
				return '$ne';
			},
			peg$c66 = {
				type: "other",
				description: "whitespace"
			},
			peg$c67 = /^[ \n\t\r]/,
			peg$c68 = {
				type: "class",
				value: "[ \\n\\t\\r]",
				description: "[ \\n\\t\\r]"
			},
			peg$c69 = function peg$c69(count) {
				return {
					$operator: '$gte',
					$num: count
				};
			},
			peg$c70 = "at most",
			peg$c71 = {
				type: "literal",
				value: "at most",
				description: "\"at most\""
			},
			peg$c72 = function peg$c72(count) {
				return {
					$operator: '$lte',
					$num: count
				};
			},
			peg$c73 = "exactly",
			peg$c74 = {
				type: "literal",
				value: "exactly",
				description: "\"exactly\""
			},
			peg$c75 = function peg$c75(count) {
				return {
					$operator: '$eq',
					$num: count
				};
			},
			peg$c76 = "zero",
			peg$c77 = {
				type: "literal",
				value: "zero",
				description: "\"zero\""
			},
			peg$c78 = "one",
			peg$c79 = {
				type: "literal",
				value: "one",
				description: "\"one\""
			},
			peg$c80 = "two",
			peg$c81 = {
				type: "literal",
				value: "two",
				description: "\"two\""
			},
			peg$c82 = "three",
			peg$c83 = {
				type: "literal",
				value: "three",
				description: "\"three\""
			},
			peg$c84 = "four",
			peg$c85 = {
				type: "literal",
				value: "four",
				description: "\"four\""
			},
			peg$c86 = "five",
			peg$c87 = {
				type: "literal",
				value: "five",
				description: "\"five\""
			},
			peg$c88 = "six",
			peg$c89 = {
				type: "literal",
				value: "six",
				description: "\"six\""
			},
			peg$c90 = "seven",
			peg$c91 = {
				type: "literal",
				value: "seven",
				description: "\"seven\""
			},
			peg$c92 = "eight",
			peg$c93 = {
				type: "literal",
				value: "eight",
				description: "\"eight\""
			},
			peg$c94 = "nine",
			peg$c95 = {
				type: "literal",
				value: "nine",
				description: "\"nine\""
			},
			peg$c96 = "ten",
			peg$c97 = {
				type: "literal",
				value: "ten",
				description: "\"ten\""
			},
			peg$c98 = function peg$c98(num) {
				if (num === 'zero') {
					return 0;
				} else if (num === 'one') {
					return 1;
				} else if (num === 'two') {
					return 2;
				} else if (num === 'three') {
					return 3;
				} else if (num === 'four') {
					return 4;
				} else if (num === 'five') {
					return 5;
				} else if (num === 'six') {
					return 6;
				} else if (num === 'seven') {
					return 7;
				} else if (num === 'eight') {
					return 8;
				} else if (num === 'nine') {
					return 9;
				} else if (num === 'ten') {
					return 10;
				}
			},
			peg$c99 = "!",
			peg$c100 = {
				type: "literal",
				value: "!",
				description: "\"!\""
			},
			peg$c101 = function peg$c101(value) {
				return {
					$type: 'boolean',
					$not: value
				};
			},
			peg$c102 = ",",
			peg$c103 = {
				type: "literal",
				value: ",",
				description: "\",\""
			},
			peg$c104 = function peg$c104(val, second) {
				return second;
			},
			peg$c105 = function peg$c105(val, rest) {
				return [val].concat(rest);
			},
			peg$c106 = function peg$c106(of) {
				return flatten(of);
			},
			peg$c107 = "all",
			peg$c108 = {
				type: "literal",
				value: "all",
				description: "\"all\""
			},
			peg$c109 = function peg$c109() {
				return {
					$operator: '$eq',
					$was: 'all'
				};
			},
			peg$c110 = "any",
			peg$c111 = {
				type: "literal",
				value: "any",
				description: "\"any\""
			},
			peg$c112 = function peg$c112() {
				return {
					$operator: '$gte',
					$num: 1,
					$was: 'any'
				};
			},
			peg$c113 = "none",
			peg$c114 = {
				type: "literal",
				value: "none",
				description: "\"none\""
			},
			peg$c115 = function peg$c115() {
				return {
					$operator: '$eq',
					$num: 0,
					$was: 'none'
				};
			},
			peg$c116 = function peg$c116(count, of) {
				if (count.$was === 'all') {
					count.$num = of.length;
				}
				if (of.length < count.$num) {
					throw new Error("you requested " + count.$num + " items, but only gave " + of.length + " options (" + JSON.stringify(of) + ").");
				}
				return {
					$type: 'of',
					$count: count,
					$of: of
				};
			},
			peg$c117 = function peg$c117(reqs) {
				return flatten(reqs);
			},
			peg$c118 = "credit",
			peg$c119 = {
				type: "literal",
				value: "credit",
				description: "\"credit\""
			},
			peg$c120 = "department",
			peg$c121 = {
				type: "literal",
				value: "department",
				description: "\"department\""
			},
			peg$c122 = "children",
			peg$c123 = {
				type: "literal",
				value: "children",
				description: "\"children\""
			},
			peg$c124 = function peg$c124(count, what, where) {
				return {
					$from: 'children-where',
					$where: where,
					$children: '$all'
				};
			},
			peg$c125 = function peg$c125(count, what) {
				return {
					$from: 'children',
					$children: '$all'
				};
			},
			peg$c126 = "filter",
			peg$c127 = {
				type: "literal",
				value: "filter",
				description: "\"filter\""
			},
			peg$c128 = function peg$c128(count, what, where) {
				return {
					$from: 'filter-where',
					$where: where
				};
			},
			peg$c129 = function peg$c129(count, what) {
				return {
					$from: 'filter'
				};
			},
			peg$c130 = function peg$c130(count, what, where) {
				return {
					$from: 'where',
					$where: where
				};
			},
			peg$c131 = function peg$c131(count, what, c, w) {
				return {
					$from: 'children-where',
					$where: w,
					$children: c
				};
			},
			peg$c132 = function peg$c132(count, what, children) {
				return {
					$from: 'children',
					$children: children
				};
			},
			peg$c133 = function peg$c133(count, what, child) {
				return {
					$from: 'children',
					$children: [child]
				};
			},
			peg$c134 = function peg$c134(count, what, from) {
				if (from.$from === 'where' && what === 'department') {
					throw new Error('cannot use a modifier with "departments from courses where {}"');
				}
				if (from.$from === 'children-where' && what !== 'course') {
					throw new Error('must use "courses from" with "children where"');
				}
				return _extends({}, from, {
					$type: 'modifier',
					$count: count,
					$what: what
				});
			},
			peg$c135 = /^[A-Z0-9]/,
			peg$c136 = {
				type: "class",
				value: "[A-Z0-9]",
				description: "[A-Z0-9]"
			},
			peg$c137 = /^[A-Za-z0-9_\- \/'.]/,
			peg$c138 = {
				type: "class",
				value: "[A-Za-z0-9_\\- /'.]",
				description: "[A-Za-z0-9_\\- /'.]"
			},
			peg$c139 = function peg$c139(initial, rest) {
				return initial + rest.join('');
			},
			peg$c140 = function peg$c140(title) {
				return title.trim();
			},
			peg$c141 = {
				type: "other",
				description: "requirement reference"
			},
			peg$c142 = function peg$c142(a, t) {
				return " (" + t + ")";
			},
			peg$c143 = function peg$c143(a, b) {
				return "" + a + (b || '');
			},
			peg$c144 = function peg$c144(title) {
				if (options.abbreviations && title in options.abbreviations) {
					title = options.abbreviations[title];
				} else if (options.titles && title in options.titles) {
					title = options.titles[title];
				}
				return {
					$type: 'reference',
					$requirement: title
				};
			},
			peg$c145 = ".",
			peg$c146 = {
				type: "literal",
				value: ".",
				description: "\".\""
			},
			peg$c147 = function peg$c147(dept, num, section, year, semester) {
				return {
					semester: semester
				};
			},
			peg$c148 = function peg$c148(dept, num, section, year, sub) {
				return _extends({}, sub, {
					year: year
				});
			},
			peg$c149 = function peg$c149(dept, num, section, sub) {
				return _extends({}, sub, {
					section: section
				});
			},
			peg$c150 = function peg$c150(dept, num, details) {
				return {
					$type: 'course',
					$course: _extends({}, details, dept || fetchDept(), num)
				};
			},
			peg$c151 = function peg$c151(c1, c2) {
				return c1 + c2;
			},
			peg$c152 = function peg$c152(dept1, chars) {
				return {
					dept: chars.join(''),
					type: 'joined'
				};
			},
			peg$c153 = "/",
			peg$c154 = {
				type: "literal",
				value: "/",
				description: "\"/\""
			},
			peg$c155 = function peg$c155(dept1, l1, l2) {
				return {
					dept: l1 + l2,
					type: 'seperate'
				};
			},
			peg$c156 = function peg$c156(dept1, part2) {
				var type = part2.type;
				var dept2 = part2.dept;
				var department = undefined;
				if (type === 'joined') {
					department = {
						department: [dept1 + dept2]
					};
				} else if (type === 'seperate') {
					department = {
						department: [expandDepartment(dept1), expandDepartment(dept2)]
					};
				}
				storeDept(department);
				return department;
			},
			peg$c157 = {
				type: "other",
				description: "course number"
			},
			peg$c158 = function peg$c158(nums) {
				return {
					number: parseInt(nums.join(''))
				};
			},
			peg$c159 = "XX",
			peg$c160 = {
				type: "literal",
				value: "XX",
				description: "\"XX\""
			},
			peg$c161 = function peg$c161(num) {
				return {
					level: num * 100
				};
			},
			peg$c162 = "I",
			peg$c163 = {
				type: "literal",
				value: "I",
				description: "\"I\""
			},
			peg$c164 = "L",
			peg$c165 = {
				type: "literal",
				value: "L",
				description: "\"L\""
			},
			peg$c166 = function peg$c166(num, international, lab) {
				var result = {};
				if (international) {
					result.international = true;
				}
				if (lab) {
					result.type = 'Lab';
				}
				return _extends({}, result, num);
			},
			peg$c167 = function peg$c167() {
				throw new SyntaxError('A course section must be either an uppercase letter [A-Z] or an asterisk [*].');
			},
			peg$c168 = function peg$c168(nums) {
				return parseInt(nums.join(''));
			},
			peg$c169 = function peg$c169() {
				throw new SyntaxError('A course year must be either a four-digit year [e.g. 1994] or an asterisk [*].');
			},
			peg$c170 = /^[1-5]/,
			peg$c171 = {
				type: "class",
				value: "[1-5]",
				description: "[1-5]"
			},
			peg$c172 = function peg$c172(num) {
				return parseInt(num);
			},
			peg$c173 = function peg$c173() {
				throw new SyntaxError('A course semester must be either a number between 1 [Fall] and 5 [Summer Session 2], or an asterisk [*].');
			},
			peg$c174 = {
				type: "any",
				description: "any character"
			},
			peg$c175 = /^[A-Z]/,
			peg$c176 = {
				type: "class",
				value: "[A-Z]",
				description: "[A-Z]"
			},
			peg$c177 = function peg$c177(char) {
				return char;
			},
			peg$c178 = "*",
			peg$c179 = {
				type: "literal",
				value: "*",
				description: "\"*\""
			},
			peg$c180 = /^[a-z]/i,
			peg$c181 = {
				type: "class",
				value: "[a-z]i",
				description: "[a-z]i"
			},
			peg$c182 = function peg$c182(chars) {
				return chars.join('');
			},
			peg$c183 = function peg$c183(digits) {
				return parseInt(digits.join(''));
			},
			peg$c184 = /^[0-9]/,
			peg$c185 = {
				type: "class",
				value: "[0-9]",
				description: "[0-9]"
			},
			peg$c186 = "(",
			peg$c187 = {
				type: "literal",
				value: "(",
				description: "\"(\""
			},
			peg$c188 = ")",
			peg$c189 = {
				type: "literal",
				value: ")",
				description: "\")\""
			},
			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$parseStart() {
			var s0;
			s0 = peg$parseOr();
			return s0;
		}

		function peg$parseExpression() {
			var s0, s1, s2, s3;
			peg$silentFails++;
			s0 = peg$currPos;
			s1 = peg$parse_();
			if (s1 !== peg$FAILED) {
				s2 = peg$parseNot();
				if (s2 === peg$FAILED) {
					s2 = peg$parseParenthetical();
					if (s2 === peg$FAILED) {
						s2 = peg$parseCourse();
						if (s2 === peg$FAILED) {
							s2 = peg$parseWhere();
							if (s2 === peg$FAILED) {
								s2 = peg$parseFilter();
								if (s2 === peg$FAILED) {
									s2 = peg$parseOccurrence();
									if (s2 === peg$FAILED) {
										s2 = peg$parseOf();
										if (s2 === peg$FAILED) {
											s2 = peg$parseModifier();
											if (s2 === peg$FAILED) {
												s2 = peg$parseReference();
											}
										}
									}
								}
							}
						}
					}
				}
				if (s2 !== peg$FAILED) {
					s3 = peg$parse_();
					if (s3 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c1(s2);
						s0 = s1;
					} else {
						peg$currPos = s0;
						s0 = peg$FAILED;
					}
				} else {
					peg$currPos = s0;
					s0 = peg$FAILED;
				}
			} else {
				peg$currPos = s0;
				s0 = peg$FAILED;
			}
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c0);
				}
			}
			return s0;
		}

		function peg$parseOptionalS() {
			var s0;
			if (input.charCodeAt(peg$currPos) === 115) {
				s0 = peg$c2;
				peg$currPos++;
			} else {
				s0 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c3);
				}
			}
			if (s0 === peg$FAILED) {
				s0 = null;
			}
			return s0;
		}

		function peg$parseWhere() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8;
			s0 = peg$currPos;
			s1 = peg$parseCounter();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 6) === peg$c4) {
						s3 = peg$c4;
						peg$currPos += 6;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c5);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parseOptionalS();
						if (s4 !== peg$FAILED) {
							s5 = peg$parse_();
							if (s5 !== peg$FAILED) {
								if (input.substr(peg$currPos, 5) === peg$c6) {
									s6 = peg$c6;
									peg$currPos += 5;
								} else {
									s6 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c7);
									}
								}
								if (s6 !== peg$FAILED) {
									s7 = peg$parse_();
									if (s7 !== peg$FAILED) {
										s8 = peg$parseQualifier();
										if (s8 !== peg$FAILED) {
											peg$savedPos = s0;
											s1 = peg$c8(s1, s8);
											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;
			}
			return s0;
		}

		function peg$parseFilter() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8;
			s0 = peg$currPos;
			if (input.substr(peg$currPos, 4) === peg$c9) {
				s1 = peg$c9;
				peg$currPos += 4;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c10);
				}
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 7) === peg$c11) {
						s3 = peg$c11;
						peg$currPos += 7;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c12);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$currPos;
							if (input.substr(peg$currPos, 5) === peg$c6) {
								s6 = peg$c6;
								peg$currPos += 5;
							} else {
								s6 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c7);
								}
							}
							if (s6 !== peg$FAILED) {
								s7 = peg$parse_();
								if (s7 !== peg$FAILED) {
									s8 = peg$parseQualifier();
									if (s8 !== peg$FAILED) {
										peg$savedPos = s5;
										s6 = peg$c13(s8);
										s5 = s6;
									} else {
										peg$currPos = s5;
										s5 = peg$FAILED;
									}
								} else {
									peg$currPos = s5;
									s5 = peg$FAILED;
								}
							} else {
								peg$currPos = s5;
								s5 = peg$FAILED;
							}
							if (s5 === peg$FAILED) {
								s5 = peg$currPos;
								if (input.substr(peg$currPos, 4) === peg$c14) {
									s6 = peg$c14;
									peg$currPos += 4;
								} else {
									s6 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c15);
									}
								}
								if (s6 !== peg$FAILED) {
									s7 = peg$parse_();
									if (s7 !== peg$FAILED) {
										s8 = peg$parseOfList();
										if (s8 !== peg$FAILED) {
											peg$savedPos = s5;
											s6 = peg$c16(s8);
											s5 = s6;
										} else {
											peg$currPos = s5;
											s5 = peg$FAILED;
										}
									} else {
										peg$currPos = s5;
										s5 = peg$FAILED;
									}
								} else {
									peg$currPos = s5;
									s5 = peg$FAILED;
								}
							}
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c17(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$parseOccurrence() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8;
			s0 = peg$currPos;
			s1 = peg$parseCounter();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 10) === peg$c18) {
						s3 = peg$c18;
						peg$currPos += 10;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c19);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parseOptionalS();
						if (s4 !== peg$FAILED) {
							s5 = peg$parse_();
							if (s5 !== peg$FAILED) {
								if (input.substr(peg$currPos, 2) === peg$c20) {
									s6 = peg$c20;
									peg$currPos += 2;
								} else {
									s6 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c21);
									}
								}
								if (s6 !== peg$FAILED) {
									s7 = peg$parse_();
									if (s7 !== peg$FAILED) {
										s8 = peg$parseCourse();
										if (s8 !== peg$FAILED) {
											peg$savedPos = s0;
											s1 = peg$c22(s1, s8);
											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;
			}
			return s0;
		}

		function peg$parseQualifier() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			if (input.charCodeAt(peg$currPos) === 123) {
				s1 = peg$c23;
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c24);
				}
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOrQualification();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							if (input.charCodeAt(peg$currPos) === 125) {
								s5 = peg$c25;
								peg$currPos++;
							} else {
								s5 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c26);
								}
							}
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c27(s3);
								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$parseOrQualification() {
			var s0, s1, s2, s3, s4, s5;
			peg$silentFails++;
			s0 = peg$currPos;
			s1 = peg$parseAndQualification();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 124) {
						s3 = peg$c29;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c30);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseOrQualification();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c31(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseAndQualification();
			}
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c28);
				}
			}
			return s0;
		}

		function peg$parseAndQualification() {
			var s0, s1, s2, s3, s4, s5;
			peg$silentFails++;
			s0 = peg$currPos;
			s1 = peg$parseParentheticalQualification();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 38) {
						s3 = peg$c33;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c34);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseAndQualification();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c35(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseParentheticalQualification();
			}
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c32);
				}
			}
			return s0;
		}

		function peg$parseParentheticalQualification() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseOpenParen();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOrQualification();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseCloseParen();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c27(s3);
								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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseQualification();
			}
			return s0;
		}

		function peg$parseQualification() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14;
			s0 = peg$currPos;
			s1 = peg$parseWord();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOperator();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$currPos;
							s6 = peg$parseFunction();
							if (s6 !== peg$FAILED) {
								s7 = peg$parse_();
								if (s7 !== peg$FAILED) {
									if (input.substr(peg$currPos, 4) === peg$c14) {
										s8 = peg$c14;
										peg$currPos += 4;
									} else {
										s8 = peg$FAILED;
										if (peg$silentFails === 0) {
											peg$fail(peg$c15);
										}
									}
									if (s8 !== peg$FAILED) {
										s9 = peg$parse_();
										if (s9 !== peg$FAILED) {
											if (input.substr(peg$currPos, 7) === peg$c11) {
												s10 = peg$c11;
												peg$currPos += 7;
											} else {
												s10 = peg$FAILED;
												if (peg$silentFails === 0) {
													peg$fail(peg$c12);
												}
											}
											if (s10 !== peg$FAILED) {
												s11 = peg$parse_();
												if (s11 !== peg$FAILED) {
													if (input.substr(peg$currPos, 5) === peg$c6) {
														s12 = peg$c6;
														peg$currPos += 5;
													} else {
														s12 = peg$FAILED;
														if (peg$silentFails === 0) {
															peg$fail(peg$c7);
														}
													}
													if (s12 !== peg$FAILED) {
														s13 = peg$parse_();
														if (s13 !== peg$FAILED) {
															s14 = peg$parseQualifier();
															if (s14 !== peg$FAILED) {
																peg$savedPos = s5;
																s6 = peg$c36(s1, s3, s6, s14);
																s5 = s6;
															} else {
																peg$currPos = s5;
																s5 = peg$FAILED;
															}
														} else {
															peg$currPos = s5;
															s5 = peg$FAILED;
														}
													} else {
														peg$currPos = s5;
														s5 = peg$FAILED;
													}
												} else {
													peg$currPos = s5;
													s5 = peg$FAILED;
												}
											} else {
												peg$currPos = s5;
												s5 = peg$FAILED;
											}
										} else {
											peg$currPos = s5;
											s5 = peg$FAILED;
										}
									} else {
										peg$currPos = s5;
										s5 = peg$FAILED;
									}
								} else {
									peg$currPos = s5;
									s5 = peg$FAILED;
								}
							} else {
								peg$currPos = s5;
								s5 = peg$FAILED;
							}
							if (s5 === peg$FAILED) {
								s5 = peg$parseQualificationValue();
								if (s5 === peg$FAILED) {
									s5 = peg$parseParentheticalQualificationValue();
								}
							}
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c37(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$parseParentheticalQualificationValue() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseOpenParen();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOrQualificationValue();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseCloseParen();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c38(s3);
								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$parseOrQualificationValue() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseAndQualificationValue();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 124) {
						s3 = peg$c29;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c30);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseOrQualificationValue();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c39(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseAndQualificationValue();
			}
			return s0;
		}

		function peg$parseAndQualificationValue() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseQualificationValue();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 38) {
						s3 = peg$c33;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c34);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseAndQualificationValue();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c40(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseQualificationValue();
			}
			return s0;
		}

		function peg$parseQualificationValue() {
			var s0, s1, s2;
			s0 = peg$currPos;
			s1 = peg$parseInteger();
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c41(s1);
			}
			s0 = s1;
			if (s0 === peg$FAILED) {
				s0 = peg$currPos;
				s1 = [];
				if (peg$c42.test(input.charAt(peg$currPos))) {
					s2 = input.charAt(peg$currPos);
					peg$currPos++;
				} else {
					s2 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c43);
					}
				}
				if (s2 !== peg$FAILED) {
					while (s2 !== peg$FAILED) {
						s1.push(s2);
						if (peg$c42.test(input.charAt(peg$currPos))) {
							s2 = input.charAt(peg$currPos);
							peg$currPos++;
						} else {
							s2 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c43);
							}
						}
					}
				} else {
					s1 = peg$FAILED;
				}
				if (s1 !== peg$FAILED) {
					peg$savedPos = s0;
					s1 = peg$c44(s1);
				}
				s0 = s1;
			}
			return s0;
		}

		function peg$parseFunction() {
			var s0, s1, s2, s3, s4, s5, s6, s7;
			s0 = peg$currPos;
			s1 = peg$parseWord();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOpenParen();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseWord();
							if (s5 !== peg$FAILED) {
								s6 = peg$parse_();
								if (s6 !== peg$FAILED) {
									s7 = peg$parseCloseParen();
									if (s7 !== peg$FAILED) {
										peg$savedPos = s0;
										s1 = peg$c45(s1, 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;
					}
				} else {
					peg$currPos = s0;
					s0 = peg$FAILED;
				}
			} else {
				peg$currPos = s0;
				s0 = peg$FAILED;
			}
			return s0;
		}

		function peg$parseOperator() {
			var s0, s1;
			s0 = peg$currPos;
			if (input.substr(peg$currPos, 2) === peg$c46) {
				s1 = peg$c46;
				peg$currPos += 2;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c47);
				}
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c48();
			}
			s0 = s1;
			if (s0 === peg$FAILED) {
				s0 = peg$currPos;
				if (input.charCodeAt(peg$currPos) === 60) {
					s1 = peg$c49;
					peg$currPos++;
				} else {
					s1 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c50);
					}
				}
				if (s1 !== peg$FAILED) {
					peg$savedPos = s0;
					s1 = peg$c51();
				}
				s0 = s1;
				if (s0 === peg$FAILED) {
					s0 = peg$currPos;
					if (input.substr(peg$currPos, 2) === peg$c52) {
						s1 = peg$c52;
						peg$currPos += 2;
					} else {
						s1 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c53);
						}
					}
					if (s1 === peg$FAILED) {
						if (input.charCodeAt(peg$currPos) === 61) {
							s1 = peg$c54;
							peg$currPos++;
						} else {
							s1 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c55);
							}
						}
					}
					if (s1 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c56();
					}
					s0 = s1;
					if (s0 === peg$FAILED) {
						s0 = peg$currPos;
						if (input.substr(peg$currPos, 2) === peg$c57) {
							s1 = peg$c57;
							peg$currPos += 2;
						} else {
							s1 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c58);
							}
						}
						if (s1 !== peg$FAILED) {
							peg$savedPos = s0;
							s1 = peg$c59();
						}
						s0 = s1;
						if (s0 === peg$FAILED) {
							s0 = peg$currPos;
							if (input.charCodeAt(peg$currPos) === 62) {
								s1 = peg$c60;
								peg$currPos++;
							} else {
								s1 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c61);
								}
							}
							if (s1 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c62();
							}
							s0 = s1;
							if (s0 === peg$FAILED) {
								s0 = peg$currPos;
								if (input.substr(peg$currPos, 2) === peg$c63) {
									s1 = peg$c63;
									peg$currPos += 2;
								} else {
									s1 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c64);
									}
								}
								if (s1 !== peg$FAILED) {
									peg$savedPos = s0;
									s1 = peg$c65();
								}
								s0 = s1;
							}
						}
					}
				}
			}
			return s0;
		}

		function peg$parse_() {
			var s0, s1;
			peg$silentFails++;
			s0 = [];
			if (peg$c67.test(input.charAt(peg$currPos))) {
				s1 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c68);
				}
			}
			while (s1 !== peg$FAILED) {
				s0.push(s1);
				if (peg$c67.test(input.charAt(peg$currPos))) {
					s1 = input.charAt(peg$currPos);
					peg$currPos++;
				} else {
					s1 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c68);
					}
				}
			}
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c66);
				}
			}
			return s0;
		}

		function peg$parseCounter() {
			var s0, s1, s2, s3;
			s0 = peg$currPos;
			s1 = peg$parseEnglishInteger();
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c69(s1);
			}
			s0 = s1;
			if (s0 === peg$FAILED) {
				s0 = peg$currPos;
				if (input.substr(peg$currPos, 7) === peg$c70) {
					s1 = peg$c70;
					peg$currPos += 7;
				} else {
					s1 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c71);
					}
				}
				if (s1 !== peg$FAILED) {
					s2 = peg$parse_();
					if (s2 !== peg$FAILED) {
						s3 = peg$parseEnglishInteger();
						if (s3 !== peg$FAILED) {
							peg$savedPos = s0;
							s1 = peg$c72(s3);
							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.substr(peg$currPos, 7) === peg$c73) {
						s1 = peg$c73;
						peg$currPos += 7;
					} else {
						s1 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c74);
						}
					}
					if (s1 !== peg$FAILED) {
						s2 = peg$parse_();
						if (s2 !== peg$FAILED) {
							s3 = peg$parseEnglishInteger();
							if (s3 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c75(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$parseEnglishInteger() {
			var s0, s1;
			s0 = peg$currPos;
			if (input.substr(peg$currPos, 4) === peg$c76) {
				s1 = peg$c76;
				peg$currPos += 4;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c77);
				}
			}
			if (s1 === peg$FAILED) {
				if (input.substr(peg$currPos, 3) === peg$c78) {
					s1 = peg$c78;
					peg$currPos += 3;
				} else {
					s1 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c79);
					}
				}
				if (s1 === peg$FAILED) {
					if (input.substr(peg$currPos, 3) === peg$c80) {
						s1 = peg$c80;
						peg$currPos += 3;
					} else {
						s1 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c81);
						}
					}
					if (s1 === peg$FAILED) {
						if (input.substr(peg$currPos, 5) === peg$c82) {
							s1 = peg$c82;
							peg$currPos += 5;
						} else {
							s1 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c83);
							}
						}
						if (s1 === peg$FAILED) {
							if (input.substr(peg$currPos, 4) === peg$c84) {
								s1 = peg$c84;
								peg$currPos += 4;
							} else {
								s1 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c85);
								}
							}
							if (s1 === peg$FAILED) {
								if (input.substr(peg$currPos, 4) === peg$c86) {
									s1 = peg$c86;
									peg$currPos += 4;
								} else {
									s1 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c87);
									}
								}
								if (s1 === peg$FAILED) {
									if (input.substr(peg$currPos, 3) === peg$c88) {
										s1 = peg$c88;
										peg$currPos += 3;
									} else {
										s1 = peg$FAILED;
										if (peg$silentFails === 0) {
											peg$fail(peg$c89);
										}
									}
									if (s1 === peg$FAILED) {
										if (input.substr(peg$currPos, 5) === peg$c90) {
											s1 = peg$c90;
											peg$currPos += 5;
										} else {
											s1 = peg$FAILED;
											if (peg$silentFails === 0) {
												peg$fail(peg$c91);
											}
										}
										if (s1 === peg$FAILED) {
											if (input.substr(peg$currPos, 5) === peg$c92) {
												s1 = peg$c92;
												peg$currPos += 5;
											} else {
												s1 = peg$FAILED;
												if (peg$silentFails === 0) {
													peg$fail(peg$c93);
												}
											}
											if (s1 === peg$FAILED) {
												if (input.substr(peg$currPos, 4) === peg$c94) {
													s1 = peg$c94;
													peg$currPos += 4;
												} else {
													s1 = peg$FAILED;
													if (peg$silentFails === 0) {
														peg$fail(peg$c95);
													}
												}
												if (s1 === peg$FAILED) {
													if (input.substr(peg$currPos, 3) === peg$c96) {
														s1 = peg$c96;
														peg$currPos += 3;
													} else {
														s1 = peg$FAILED;
														if (peg$silentFails === 0) {
															peg$fail(peg$c97);
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c98(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseNot() {
			var s0, s1, s2, s3;
			s0 = peg$currPos;
			if (input.charCodeAt(peg$currPos) === 33) {
				s1 = peg$c99;
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c100);
				}
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseExpression();
					if (s3 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c101(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$parseParenthetical() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseOpenParen();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseOr();
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseCloseParen();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c38(s3);
								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$parseOr() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseAnd();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 124) {
						s3 = peg$c29;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c30);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseOr();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c31(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseAnd();
			}
			return s0;
		}

		function peg$parseAnd() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseExpression();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 38) {
						s3 = peg$c33;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c34);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseAnd();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c35(s1, 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;
			}
			if (s0 === peg$FAILED) {
				s0 = peg$parseExpression();
			}
			return s0;
		}

		function peg$parseOfList() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11;
			s0 = peg$currPos;
			s1 = peg$parseOpenParen();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = [];
					s4 = peg$currPos;
					s5 = peg$parseOr();
					if (s5 !== peg$FAILED) {
						s6 = [];
						s7 = peg$currPos;
						s8 = peg$parse_();
						if (s8 !== peg$FAILED) {
							if (input.charCodeAt(peg$currPos) === 44) {
								s9 = peg$c102;
								peg$currPos++;
							} else {
								s9 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c103);
								}
							}
							if (s9 !== peg$FAILED) {
								s10 = peg$parse_();
								if (s10 !== peg$FAILED) {
									s11 = peg$parseOr();
									if (s11 !== peg$FAILED) {
										peg$savedPos = s7;
										s8 = peg$c104(s5, s11);
										s7 = s8;
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
							} else {
								peg$currPos = s7;
								s7 = peg$FAILED;
							}
						} else {
							peg$currPos = s7;
							s7 = peg$FAILED;
						}
						while (s7 !== peg$FAILED) {
							s6.push(s7);
							s7 = peg$currPos;
							s8 = peg$parse_();
							if (s8 !== peg$FAILED) {
								if (input.charCodeAt(peg$currPos) === 44) {
									s9 = peg$c102;
									peg$currPos++;
								} else {
									s9 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c103);
									}
								}
								if (s9 !== peg$FAILED) {
									s10 = peg$parse_();
									if (s10 !== peg$FAILED) {
										s11 = peg$parseOr();
										if (s11 !== peg$FAILED) {
											peg$savedPos = s7;
											s8 = peg$c104(s5, s11);
											s7 = s8;
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
							} else {
								peg$currPos = s7;
								s7 = peg$FAILED;
							}
						}
						if (s6 !== peg$FAILED) {
							peg$savedPos = s4;
							s5 = peg$c105(s5, s6);
							s4 = s5;
						} else {
							peg$currPos = s4;
							s4 = peg$FAILED;
						}
					} else {
						peg$currPos = s4;
						s4 = peg$FAILED;
					}
					if (s4 !== peg$FAILED) {
						while (s4 !== peg$FAILED) {
							s3.push(s4);
							s4 = peg$currPos;
							s5 = peg$parseOr();
							if (s5 !== peg$FAILED) {
								s6 = [];
								s7 = peg$currPos;
								s8 = peg$parse_();
								if (s8 !== peg$FAILED) {
									if (input.charCodeAt(peg$currPos) === 44) {
										s9 = peg$c102;
										peg$currPos++;
									} else {
										s9 = peg$FAILED;
										if (peg$silentFails === 0) {
											peg$fail(peg$c103);
										}
									}
									if (s9 !== peg$FAILED) {
										s10 = peg$parse_();
										if (s10 !== peg$FAILED) {
											s11 = peg$parseOr();
											if (s11 !== peg$FAILED) {
												peg$savedPos = s7;
												s8 = peg$c104(s5, s11);
												s7 = s8;
											} else {
												peg$currPos = s7;
												s7 = peg$FAILED;
											}
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
								while (s7 !== peg$FAILED) {
									s6.push(s7);
									s7 = peg$currPos;
									s8 = peg$parse_();
									if (s8 !== peg$FAILED) {
										if (input.charCodeAt(peg$currPos) === 44) {
											s9 = peg$c102;
											peg$currPos++;
										} else {
											s9 = peg$FAILED;
											if (peg$silentFails === 0) {
												peg$fail(peg$c103);
											}
										}
										if (s9 !== peg$FAILED) {
											s10 = peg$parse_();
											if (s10 !== peg$FAILED) {
												s11 = peg$parseOr();
												if (s11 !== peg$FAILED) {
													peg$savedPos = s7;
													s8 = peg$c104(s5, s11);
													s7 = s8;
												} else {
													peg$currPos = s7;
													s7 = peg$FAILED;
												}
											} else {
												peg$currPos = s7;
												s7 = peg$FAILED;
											}
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								}
								if (s6 !== peg$FAILED) {
									peg$savedPos = s4;
									s5 = peg$c105(s5, s6);
									s4 = s5;
								} else {
									peg$currPos = s4;
									s4 = peg$FAILED;
								}
							} else {
								peg$currPos = s4;
								s4 = peg$FAILED;
							}
						}
					} else {
						s3 = peg$FAILED;
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							if (input.charCodeAt(peg$currPos) === 44) {
								s5 = peg$c102;
								peg$currPos++;
							} else {
								s5 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c103);
								}
							}
							if (s5 === peg$FAILED) {
								s5 = null;
							}
							if (s5 !== peg$FAILED) {
								s6 = peg$parse_();
								if (s6 !== peg$FAILED) {
									s7 = peg$parseCloseParen();
									if (s7 !== peg$FAILED) {
										peg$savedPos = s0;
										s1 = peg$c106(s3);
										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$parseOf() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$parseCounter();
			if (s1 === peg$FAILED) {
				s1 = peg$currPos;
				if (input.substr(peg$currPos, 3) === peg$c107) {
					s2 = peg$c107;
					peg$currPos += 3;
				} else {
					s2 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c108);
					}
				}
				if (s2 !== peg$FAILED) {
					peg$savedPos = s1;
					s2 = peg$c109();
				}
				s1 = s2;
				if (s1 === peg$FAILED) {
					s1 = peg$currPos;
					if (input.substr(peg$currPos, 3) === peg$c110) {
						s2 = peg$c110;
						peg$currPos += 3;
					} else {
						s2 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c111);
						}
					}
					if (s2 !== peg$FAILED) {
						peg$savedPos = s1;
						s2 = peg$c112();
					}
					s1 = s2;
					if (s1 === peg$FAILED) {
						s1 = peg$currPos;
						if (input.substr(peg$currPos, 4) === peg$c113) {
							s2 = peg$c113;
							peg$currPos += 4;
						} else {
							s2 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c114);
							}
						}
						if (s2 !== peg$FAILED) {
							peg$savedPos = s1;
							s2 = peg$c115();
						}
						s1 = s2;
					}
				}
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 2) === peg$c20) {
						s3 = peg$c20;
						peg$currPos += 2;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c21);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseOfList();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s0;
								s1 = peg$c116(s1, 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$parseChildList() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11;
			s0 = peg$currPos;
			s1 = peg$parseOpenParen();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = [];
					s4 = peg$currPos;
					s5 = peg$parseReference();
					if (s5 !== peg$FAILED) {
						s6 = [];
						s7 = peg$currPos;
						s8 = peg$parse_();
						if (s8 !== peg$FAILED) {
							if (input.charCodeAt(peg$currPos) === 44) {
								s9 = peg$c102;
								peg$currPos++;
							} else {
								s9 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c103);
								}
							}
							if (s9 !== peg$FAILED) {
								s10 = peg$parse_();
								if (s10 !== peg$FAILED) {
									s11 = peg$parseReference();
									if (s11 !== peg$FAILED) {
										peg$savedPos = s7;
										s8 = peg$c104(s5, s11);
										s7 = s8;
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
							} else {
								peg$currPos = s7;
								s7 = peg$FAILED;
							}
						} else {
							peg$currPos = s7;
							s7 = peg$FAILED;
						}
						while (s7 !== peg$FAILED) {
							s6.push(s7);
							s7 = peg$currPos;
							s8 = peg$parse_();
							if (s8 !== peg$FAILED) {
								if (input.charCodeAt(peg$currPos) === 44) {
									s9 = peg$c102;
									peg$currPos++;
								} else {
									s9 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c103);
									}
								}
								if (s9 !== peg$FAILED) {
									s10 = peg$parse_();
									if (s10 !== peg$FAILED) {
										s11 = peg$parseReference();
										if (s11 !== peg$FAILED) {
											peg$savedPos = s7;
											s8 = peg$c104(s5, s11);
											s7 = s8;
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
							} else {
								peg$currPos = s7;
								s7 = peg$FAILED;
							}
						}
						if (s6 !== peg$FAILED) {
							peg$savedPos = s4;
							s5 = peg$c105(s5, s6);
							s4 = s5;
						} else {
							peg$currPos = s4;
							s4 = peg$FAILED;
						}
					} else {
						peg$currPos = s4;
						s4 = peg$FAILED;
					}
					if (s4 !== peg$FAILED) {
						while (s4 !== peg$FAILED) {
							s3.push(s4);
							s4 = peg$currPos;
							s5 = peg$parseReference();
							if (s5 !== peg$FAILED) {
								s6 = [];
								s7 = peg$currPos;
								s8 = peg$parse_();
								if (s8 !== peg$FAILED) {
									if (input.charCodeAt(peg$currPos) === 44) {
										s9 = peg$c102;
										peg$currPos++;
									} else {
										s9 = peg$FAILED;
										if (peg$silentFails === 0) {
											peg$fail(peg$c103);
										}
									}
									if (s9 !== peg$FAILED) {
										s10 = peg$parse_();
										if (s10 !== peg$FAILED) {
											s11 = peg$parseReference();
											if (s11 !== peg$FAILED) {
												peg$savedPos = s7;
												s8 = peg$c104(s5, s11);
												s7 = s8;
											} else {
												peg$currPos = s7;
												s7 = peg$FAILED;
											}
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
								while (s7 !== peg$FAILED) {
									s6.push(s7);
									s7 = peg$currPos;
									s8 = peg$parse_();
									if (s8 !== peg$FAILED) {
										if (input.charCodeAt(peg$currPos) === 44) {
											s9 = peg$c102;
											peg$currPos++;
										} else {
											s9 = peg$FAILED;
											if (peg$silentFails === 0) {
												peg$fail(peg$c103);
											}
										}
										if (s9 !== peg$FAILED) {
											s10 = peg$parse_();
											if (s10 !== peg$FAILED) {
												s11 = peg$parseReference();
												if (s11 !== peg$FAILED) {
													peg$savedPos = s7;
													s8 = peg$c104(s5, s11);
													s7 = s8;
												} else {
													peg$currPos = s7;
													s7 = peg$FAILED;
												}
											} else {
												peg$currPos = s7;
												s7 = peg$FAILED;
											}
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								}
								if (s6 !== peg$FAILED) {
									peg$savedPos = s4;
									s5 = peg$c105(s5, s6);
									s4 = s5;
								} else {
									peg$currPos = s4;
									s4 = peg$FAILED;
								}
							} else {
								peg$currPos = s4;
								s4 = peg$FAILED;
							}
						}
					} else {
						s3 = peg$FAILED;
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parse_();
						if (s4 !== peg$FAILED) {
							if (input.charCodeAt(peg$currPos) === 44) {
								s5 = peg$c102;
								peg$currPos++;
							} else {
								s5 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c103);
								}
							}
							if (s5 === peg$FAILED) {
								s5 = null;
							}
							if (s5 !== peg$FAILED) {
								s6 = peg$parse_();
								if (s6 !== peg$FAILED) {
									s7 = peg$parseCloseParen();
									if (s7 !== peg$FAILED) {
										peg$savedPos = s0;
										s1 = peg$c117(s3);
										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$parseModifier() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
			s0 = peg$currPos;
			s1 = peg$parseCounter();
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 6) === peg$c4) {
						s3 = peg$c4;
						peg$currPos += 6;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c5);
						}
					}
					if (s3 === peg$FAILED) {
						if (input.substr(peg$currPos, 6) === peg$c118) {
							s3 = peg$c118;
							peg$currPos += 6;
						} else {
							s3 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c119);
							}
						}
						if (s3 === peg$FAILED) {
							if (input.substr(peg$currPos, 10) === peg$c120) {
								s3 = peg$c120;
								peg$currPos += 10;
							} else {
								s3 = peg$FAILED;
								if (peg$silentFails === 0) {
									peg$fail(peg$c121);
								}
							}
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parseOptionalS();
						if (s4 !== peg$FAILED) {
							s5 = peg$parse_();
							if (s5 !== peg$FAILED) {
								if (input.substr(peg$currPos, 4) === peg$c14) {
									s6 = peg$c14;
									peg$currPos += 4;
								} else {
									s6 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c15);
									}
								}
								if (s6 !== peg$FAILED) {
									s7 = peg$parse_();
									if (s7 !== peg$FAILED) {
										s8 = peg$currPos;
										if (input.substr(peg$currPos, 8) === peg$c122) {
											s9 = peg$c122;
											peg$currPos += 8;
										} else {
											s9 = peg$FAILED;
											if (peg$silentFails === 0) {
												peg$fail(peg$c123);
											}
										}
										if (s9 !== peg$FAILED) {
											s10 = peg$parse_();
											if (s10 !== peg$FAILED) {
												if (input.substr(peg$currPos, 5) === peg$c6) {
													s11 = peg$c6;
													peg$currPos += 5;
												} else {
													s11 = peg$FAILED;
													if (peg$silentFails === 0) {
														peg$fail(peg$c7);
													}
												}
												if (s11 !== peg$FAILED) {
													s12 = peg$parse_();
													if (s12 !== peg$FAILED) {
														s13 = peg$parseQualifier();
														if (s13 !== peg$FAILED) {
															peg$savedPos = s8;
															s9 = peg$c124(s1, s3, s13);
															s8 = s9;
														} else {
															peg$currPos = s8;
															s8 = peg$FAILED;
														}
													} else {
														peg$currPos = s8;
														s8 = peg$FAILED;
													}
												} else {
													peg$currPos = s8;
													s8 = peg$FAILED;
												}
											} else {
												peg$currPos = s8;
												s8 = peg$FAILED;
											}
										} else {
											peg$currPos = s8;
											s8 = peg$FAILED;
										}
										if (s8 === peg$FAILED) {
											s8 = peg$currPos;
											if (input.substr(peg$currPos, 8) === peg$c122) {
												s9 = peg$c122;
												peg$currPos += 8;
											} else {
												s9 = peg$FAILED;
												if (peg$silentFails === 0) {
													peg$fail(peg$c123);
												}
											}
											if (s9 !== peg$FAILED) {
												peg$savedPos = s8;
												s9 = peg$c125(s1, s3);
											}
											s8 = s9;
											if (s8 === peg$FAILED) {
												s8 = peg$currPos;
												if (input.substr(peg$currPos, 6) === peg$c126) {
													s9 = peg$c126;
													peg$currPos += 6;
												} else {
													s9 = peg$FAILED;
													if (peg$silentFails === 0) {
														peg$fail(peg$c127);
													}
												}
												if (s9 !== peg$FAILED) {
													s10 = peg$parse_();
													if (s10 !== peg$FAILED) {
														if (input.substr(peg$currPos, 5) === peg$c6) {
															s11 = peg$c6;
															peg$currPos += 5;
														} else {
															s11 = peg$FAILED;
															if (peg$silentFails === 0) {
																peg$fail(peg$c7);
															}
														}
														if (s11 !== peg$FAILED) {
															s12 = peg$parse_();
															if (s12 !== peg$FAILED) {
																s13 = peg$parseQualifier();
																if (s13 !== peg$FAILED) {
																	peg$savedPos = s8;
																	s9 = peg$c128(s1, s3, s13);
																	s8 = s9;
																} else {
																	peg$currPos = s8;
																	s8 = peg$FAILED;
																}
															} else {
																peg$currPos = s8;
																s8 = peg$FAILED;
															}
														} else {
															peg$currPos = s8;
															s8 = peg$FAILED;
														}
													} else {
														peg$currPos = s8;
														s8 = peg$FAILED;
													}
												} else {
													peg$currPos = s8;
													s8 = peg$FAILED;
												}
												if (s8 === peg$FAILED) {
													s8 = peg$currPos;
													if (input.substr(peg$currPos, 6) === peg$c126) {
														s9 = peg$c126;
														peg$currPos += 6;
													} else {
														s9 = peg$FAILED;
														if (peg$silentFails === 0) {
															peg$fail(peg$c127);
														}
													}
													if (s9 !== peg$FAILED) {
														peg$savedPos = s8;
														s9 = peg$c129(s1, s3);
													}
													s8 = s9;
													if (s8 === peg$FAILED) {
														s8 = peg$currPos;
														if (input.substr(peg$currPos, 7) === peg$c11) {
															s9 = peg$c11;
															peg$currPos += 7;
														} else {
															s9 = peg$FAILED;
															if (peg$silentFails === 0) {
																peg$fail(peg$c12);
															}
														}
														if (s9 !== peg$FAILED) {
															s10 = peg$parse_();
															if (s10 !== peg$FAILED) {
																if (input.substr(peg$currPos, 5) === peg$c6) {
																	s11 = peg$c6;
																	peg$currPos += 5;
																} else {
																	s11 = peg$FAILED;
																	if (peg$silentFails === 0) {
																		peg$fail(peg$c7);
																	}
																}
																if (s11 !== peg$FAILED) {
																	s12 = peg$parse_();
																	if (s12 !== peg$FAILED) {
																		s13 = peg$parseQualifier();
																		if (s13 !== peg$FAILED) {
																			peg$savedPos = s8;
																			s9 = peg$c130(s1, s3, s13);
																			s8 = s9;
																		} else {
																			peg$currPos = s8;
																			s8 = peg$FAILED;
																		}
																	} else {
																		peg$currPos = s8;
																		s8 = peg$FAILED;
																	}
																} else {
																	peg$currPos = s8;
																	s8 = peg$FAILED;
																}
															} else {
																peg$currPos = s8;
																s8 = peg$FAILED;
															}
														} else {
															peg$currPos = s8;
															s8 = peg$FAILED;
														}
														if (s8 === peg$FAILED) {
															s8 = peg$currPos;
															s9 = peg$parseChildList();
															if (s9 !== peg$FAILED) {
																s10 = peg$parse_();
																if (s10 !== peg$FAILED) {
																	if (input.substr(peg$currPos, 5) === peg$c6) {
																		s11 = peg$c6;
																		peg$currPos += 5;
																	} else {
																		s11 = peg$FAILED;
																		if (peg$silentFails === 0) {
																			peg$fail(peg$c7);
																		}
																	}
																	if (s11 !== peg$FAILED) {
																		s12 = peg$parse_();
																		if (s12 !== peg$FAILED) {
																			s13 = peg$parseQualifier();
																			if (s13 !== peg$FAILED) {
																				peg$savedPos = s8;
																				s9 = peg$c131(s1, s3, s9, s13);
																				s8 = s9;
																			} else {
																				peg$currPos = s8;
																				s8 = peg$FAILED;
																			}
																		} else {
																			peg$currPos = s8;
																			s8 = peg$FAILED;
																		}
																	} else {
																		peg$currPos = s8;
																		s8 = peg$FAILED;
																	}
																} else {
																	peg$currPos = s8;
																	s8 = peg$FAILED;
																}
															} else {
																peg$currPos = s8;
																s8 = peg$FAILED;
															}
															if (s8 === peg$FAILED) {
																s8 = peg$currPos;
																s9 = peg$parseChildList();
																if (s9 !== peg$FAILED) {
																	peg$savedPos = s8;
																	s9 = peg$c132(s1, s3, s9);
																}
																s8 = s9;
																if (s8 === peg$FAILED) {
																	s8 = peg$currPos;
																	s9 = peg$parseReference();
																	if (s9 !== peg$FAILED) {
																		peg$savedPos = s8;
																		s9 = peg$c133(s1, s3, s9);
																	}
																	s8 = s9;
																}
															}
														}
													}
												}
											}
										}
										if (s8 !== peg$FAILED) {
											peg$savedPos = s0;
											s1 = peg$c134(s1, s3, s8);
											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;
			}
			return s0;
		}

		function peg$parseRequirementTitle() {
			var s0, s1, s2, s3, s4;
			s0 = peg$currPos;
			s1 = peg$currPos;
			if (peg$c135.test(input.charAt(peg$currPos))) {
				s2 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s2 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c136);
				}
			}
			if (s2 !== peg$FAILED) {
				s3 = [];
				if (peg$c137.test(input.charAt(peg$currPos))) {
					s4 = input.charAt(peg$currPos);
					peg$currPos++;
				} else {
					s4 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c138);
					}
				}
				while (s4 !== peg$FAILED) {
					s3.push(s4);
					if (peg$c137.test(input.charAt(peg$currPos))) {
						s4 = input.charAt(peg$currPos);
						peg$currPos++;
					} else {
						s4 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c138);
						}
					}
				}
				if (s3 !== peg$FAILED) {
					peg$savedPos = s1;
					s2 = peg$c139(s2, s3);
					s1 = s2;
				} else {
					peg$currPos = s1;
					s1 = peg$FAILED;
				}
			} else {
				peg$currPos = s1;
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c140(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseReference() {
			var s0, s1, s2, s3, s4, s5, s6, s7;
			peg$silentFails++;
			s0 = peg$currPos;
			s1 = peg$currPos;
			s2 = peg$parseRequirementTitle();
			if (s2 !== peg$FAILED) {
				s3 = peg$currPos;
				s4 = peg$parse_();
				if (s4 !== peg$FAILED) {
					s5 = peg$parseOpenParen();
					if (s5 !== peg$FAILED) {
						s6 = peg$parseRequirementTitle();
						if (s6 !== peg$FAILED) {
							s7 = peg$parseCloseParen();
							if (s7 !== peg$FAILED) {
								peg$savedPos = s3;
								s4 = peg$c142(s2, s6);
								s3 = s4;
							} else {
								peg$currPos = s3;
								s3 = peg$FAILED;
							}
						} else {
							peg$currPos = s3;
							s3 = peg$FAILED;
						}
					} else {
						peg$currPos = s3;
						s3 = peg$FAILED;
					}
				} else {
					peg$currPos = s3;
					s3 = peg$FAILED;
				}
				if (s3 === peg$FAILED) {
					s3 = null;
				}
				if (s3 !== peg$FAILED) {
					peg$savedPos = s1;
					s2 = peg$c143(s2, s3);
					s1 = s2;
				} else {
					peg$currPos = s1;
					s1 = peg$FAILED;
				}
			} else {
				peg$currPos = s1;
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c144(s1);
			}
			s0 = s1;
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c141);
				}
			}
			return s0;
		}

		function peg$parseCourse() {
			var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12;
			s0 = peg$currPos;
			s1 = peg$parseCourseDepartment();
			if (s1 === peg$FAILED) {
				s1 = null;
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$parse_();
				if (s2 !== peg$FAILED) {
					s3 = peg$parseCourseNumber();
					if (s3 !== peg$FAILED) {
						s4 = peg$currPos;
						if (input.charCodeAt(peg$currPos) === 46) {
							s5 = peg$c145;
							peg$currPos++;
						} else {
							s5 = peg$FAILED;
							if (peg$silentFails === 0) {
								peg$fail(peg$c146);
							}
						}
						if (s5 !== peg$FAILED) {
							s6 = peg$parseCourseSection();
							if (s6 !== peg$FAILED) {
								s7 = peg$currPos;
								if (input.charCodeAt(peg$currPos) === 46) {
									s8 = peg$c145;
									peg$currPos++;
								} else {
									s8 = peg$FAILED;
									if (peg$silentFails === 0) {
										peg$fail(peg$c146);
									}
								}
								if (s8 !== peg$FAILED) {
									s9 = peg$parseCourseYear();
									if (s9 !== peg$FAILED) {
										s10 = peg$currPos;
										if (input.charCodeAt(peg$currPos) === 46) {
											s11 = peg$c145;
											peg$currPos++;
										} else {
											s11 = peg$FAILED;
											if (peg$silentFails === 0) {
												peg$fail(peg$c146);
											}
										}
										if (s11 !== peg$FAILED) {
											s12 = peg$parseCourseSemester();
											if (s12 !== peg$FAILED) {
												peg$savedPos = s10;
												s11 = peg$c147(s1, s3, s6, s9, s12);
												s10 = s11;
											} else {
												peg$currPos = s10;
												s10 = peg$FAILED;
											}
										} else {
											peg$currPos = s10;
											s10 = peg$FAILED;
										}
										if (s10 === peg$FAILED) {
											s10 = null;
										}
										if (s10 !== peg$FAILED) {
											peg$savedPos = s7;
											s8 = peg$c148(s1, s3, s6, s9, s10);
											s7 = s8;
										} else {
											peg$currPos = s7;
											s7 = peg$FAILED;
										}
									} else {
										peg$currPos = s7;
										s7 = peg$FAILED;
									}
								} else {
									peg$currPos = s7;
									s7 = peg$FAILED;
								}
								if (s7 === peg$FAILED) {
									s7 = null;
								}
								if (s7 !== peg$FAILED) {
									peg$savedPos = s4;
									s5 = peg$c149(s1, s3, s6, s7);
									s4 = s5;
								} else {
									peg$currPos = s4;
									s4 = peg$FAILED;
								}
							} else {
								peg$currPos = s4;
								s4 = peg$FAILED;
							}
						} else {
							peg$currPos = s4;
							s4 = peg$FAILED;
						}
						if (s4 === peg$FAILED) {
							s4 = null;
						}
						if (s4 !== peg$FAILED) {
							peg$savedPos = s0;
							s1 = peg$c150(s1, 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$parseCourseDepartment() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$currPos;
			s2 = peg$parseUppercaseLetter();
			if (s2 !== peg$FAILED) {
				s3 = peg$parseUppercaseLetter();
				if (s3 !== peg$FAILED) {
					peg$savedPos = s1;
					s2 = peg$c151(s2, s3);
					s1 = s2;
				} else {
					peg$currPos = s1;
					s1 = peg$FAILED;
				}
			} else {
				peg$currPos = s1;
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				s2 = peg$currPos;
				s3 = [];
				s4 = peg$parseUppercaseLetter();
				if (s4 !== peg$FAILED) {
					while (s4 !== peg$FAILED) {
						s3.push(s4);
						s4 = peg$parseUppercaseLetter();
					}
				} else {
					s3 = peg$FAILED;
				}
				if (s3 !== peg$FAILED) {
					peg$savedPos = s2;
					s3 = peg$c152(s1, s3);
				}
				s2 = s3;
				if (s2 === peg$FAILED) {
					s2 = peg$currPos;
					if (input.charCodeAt(peg$currPos) === 47) {
						s3 = peg$c153;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c154);
						}
					}
					if (s3 !== peg$FAILED) {
						s4 = peg$parseUppercaseLetter();
						if (s4 !== peg$FAILED) {
							s5 = peg$parseUppercaseLetter();
							if (s5 !== peg$FAILED) {
								peg$savedPos = s2;
								s3 = peg$c155(s1, s4, s5);
								s2 = s3;
							} else {
								peg$currPos = s2;
								s2 = peg$FAILED;
							}
						} else {
							peg$currPos = s2;
							s2 = peg$FAILED;
						}
					} else {
						peg$currPos = s2;
						s2 = peg$FAILED;
					}
				}
				if (s2 !== peg$FAILED) {
					peg$savedPos = s0;
					s1 = peg$c156(s1, s2);
					s0 = s1;
				} else {
					peg$currPos = s0;
					s0 = peg$FAILED;
				}
			} else {
				peg$currPos = s0;
				s0 = peg$FAILED;
			}
			return s0;
		}

		function peg$parseCourseNumber() {
			var s0, s1, s2, s3, s4, s5;
			peg$silentFails++;
			s0 = peg$currPos;
			s1 = peg$currPos;
			s2 = peg$currPos;
			s3 = peg$parseDigit();
			if (s3 !== peg$FAILED) {
				s4 = peg$parseDigit();
				if (s4 !== peg$FAILED) {
					s5 = peg$parseDigit();
					if (s5 !== peg$FAILED) {
						s3 = [s3, s4, s5];
						s2 = s3;
					} else {
						peg$currPos = s2;
						s2 = peg$FAILED;
					}
				} else {
					peg$currPos = s2;
					s2 = peg$FAILED;
				}
			} else {
				peg$currPos = s2;
				s2 = peg$FAILED;
			}
			if (s2 !== peg$FAILED) {
				peg$savedPos = s1;
				s2 = peg$c158(s2);
			}
			s1 = s2;
			if (s1 === peg$FAILED) {
				s1 = peg$currPos;
				s2 = peg$parseDigit();
				if (s2 !== peg$FAILED) {
					if (input.substr(peg$currPos, 2) === peg$c159) {
						s3 = peg$c159;
						peg$currPos += 2;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c160);
						}
					}
					if (s3 !== peg$FAILED) {
						peg$savedPos = s1;
						s2 = peg$c161(s2);
						s1 = s2;
					} else {
						peg$currPos = s1;
						s1 = peg$FAILED;
					}
				} else {
					peg$currPos = s1;
					s1 = peg$FAILED;
				}
			}
			if (s1 !== peg$FAILED) {
				if (input.charCodeAt(peg$currPos) === 73) {
					s2 = peg$c162;
					peg$currPos++;
				} else {
					s2 = peg$FAILED;
					if (peg$silentFails === 0) {
						peg$fail(peg$c163);
					}
				}
				if (s2 === peg$FAILED) {
					s2 = null;
				}
				if (s2 !== peg$FAILED) {
					if (input.charCodeAt(peg$currPos) === 76) {
						s3 = peg$c164;
						peg$currPos++;
					} else {
						s3 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c165);
						}
					}
					if (s3 === peg$FAILED) {
						s3 = null;
					}
					if (s3 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c166(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;
			}
			peg$silentFails--;
			if (s0 === peg$FAILED) {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c157);
				}
			}
			return s0;
		}

		function peg$parseCourseSection() {
			var s0, s1;
			s0 = peg$parseUppercaseLetter();
			if (s0 === peg$FAILED) {
				s0 = peg$parseAsterisk();
				if (s0 === peg$FAILED) {
					s0 = peg$currPos;
					s1 = peg$parseElse();
					if (s1 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c167();
					}
					s0 = s1;
				}
			}
			return s0;
		}

		function peg$parseCourseYear() {
			var s0, s1, s2, s3, s4, s5;
			s0 = peg$currPos;
			s1 = peg$currPos;
			s2 = peg$parseDigit();
			if (s2 !== peg$FAILED) {
				s3 = peg$parseDigit();
				if (s3 !== peg$FAILED) {
					s4 = peg$parseDigit();
					if (s4 !== peg$FAILED) {
						s5 = peg$parseDigit();
						if (s5 !== peg$FAILED) {
							s2 = [s2, s3, s4, s5];
							s1 = s2;
						} else {
							peg$currPos = s1;
							s1 = peg$FAILED;
						}
					} else {
						peg$currPos = s1;
						s1 = peg$FAILED;
					}
				} else {
					peg$currPos = s1;
					s1 = peg$FAILED;
				}
			} else {
				peg$currPos = s1;
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c168(s1);
			}
			s0 = s1;
			if (s0 === peg$FAILED) {
				s0 = peg$parseAsterisk();
				if (s0 === peg$FAILED) {
					s0 = peg$currPos;
					s1 = peg$parseElse();
					if (s1 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c169();
					}
					s0 = s1;
				}
			}
			return s0;
		}

		function peg$parseCourseSemester() {
			var s0, s1;
			s0 = peg$currPos;
			if (peg$c170.test(input.charAt(peg$currPos))) {
				s1 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c171);
				}
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c172(s1);
			}
			s0 = s1;
			if (s0 === peg$FAILED) {
				s0 = peg$parseAsterisk();
				if (s0 === peg$FAILED) {
					s0 = peg$currPos;
					s1 = peg$parseElse();
					if (s1 !== peg$FAILED) {
						peg$savedPos = s0;
						s1 = peg$c173();
					}
					s0 = s1;
				}
			}
			return s0;
		}

		function peg$parseElse() {
			var s0, s1;
			s0 = [];
			if (input.length > peg$currPos) {
				s1 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c174);
				}
			}
			if (s1 !== peg$FAILED) {
				while (s1 !== peg$FAILED) {
					s0.push(s1);
					if (input.length > peg$currPos) {
						s1 = input.charAt(peg$currPos);
						peg$currPos++;
					} else {
						s1 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c174);
						}
					}
				}
			} else {
				s0 = peg$FAILED;
			}
			return s0;
		}

		function peg$parseUppercaseLetter() {
			var s0, s1;
			s0 = peg$currPos;
			if (peg$c175.test(input.charAt(peg$currPos))) {
				s1 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c176);
				}
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c177(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseAsterisk() {
			var s0;
			if (input.charCodeAt(peg$currPos) === 42) {
				s0 = peg$c178;
				peg$currPos++;
			} else {
				s0 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c179);
				}
			}
			return s0;
		}

		function peg$parseWord() {
			var s0, s1, s2;
			s0 = peg$currPos;
			s1 = [];
			if (peg$c180.test(input.charAt(peg$currPos))) {
				s2 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s2 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c181);
				}
			}
			if (s2 !== peg$FAILED) {
				while (s2 !== peg$FAILED) {
					s1.push(s2);
					if (peg$c180.test(input.charAt(peg$currPos))) {
						s2 = input.charAt(peg$currPos);
						peg$currPos++;
					} else {
						s2 = peg$FAILED;
						if (peg$silentFails === 0) {
							peg$fail(peg$c181);
						}
					}
				}
			} else {
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c182(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseInteger() {
			var s0, s1, s2;
			s0 = peg$currPos;
			s1 = [];
			s2 = peg$parseDigit();
			if (s2 !== peg$FAILED) {
				while (s2 !== peg$FAILED) {
					s1.push(s2);
					s2 = peg$parseDigit();
				}
			} else {
				s1 = peg$FAILED;
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c183(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseDigit() {
			var s0, s1;
			s0 = peg$currPos;
			if (peg$c184.test(input.charAt(peg$currPos))) {
				s1 = input.charAt(peg$currPos);
				peg$currPos++;
			} else {
				s1 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c185);
				}
			}
			if (s1 !== peg$FAILED) {
				peg$savedPos = s0;
				s1 = peg$c172(s1);
			}
			s0 = s1;
			return s0;
		}

		function peg$parseOpenParen() {
			var s0;
			if (input.charCodeAt(peg$currPos) === 40) {
				s0 = peg$c186;
				peg$currPos++;
			} else {
				s0 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c187);
				}
			}
			return s0;
		}

		function peg$parseCloseParen() {
			var s0;
			if (input.charCodeAt(peg$currPos) === 41) {
				s0 = peg$c188;
				peg$currPos++;
			} else {
				s0 = peg$FAILED;
				if (peg$silentFails === 0) {
					peg$fail(peg$c189);
				}
			}
			return s0;
		}
		var globalLastDept = undefined;

		function storeDept(dept) {
			globalLastDept = dept;
		}

		function fetchDept(dept) {
			return globalLastDept;
		}
		var flatten = require('lodash/array/flatten');
		var expandDepartment = require('./expand-department');
		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
	};
})();