PageRenderTime 60ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/IRC/vendor/kouprey/kouprey.js

https://github.com/BigBlueHat/sIRCouch
JavaScript | 815 lines | 522 code | 111 blank | 182 comment | 79 complexity | dd6a22661ffdc8c3f84649cc56ed4e2f MD5 | raw file
  1. /* kouprey.js - A Parsing Expression Grammar (PEG) library for JavaScript.
  2. * Copyright (C) 2009 Rob King <jking@deadpixi.com>
  3. *
  4. * This file is part of Kouprey.
  5. *
  6. * Kouprey is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Kouprey is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Kouprey. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /* Set up the Kouprey namespace. */
  20. if (this.com === undefined) {
  21. com = {};
  22. }
  23. if (com.deadpixi === undefined) {
  24. com.deadpixi = {};
  25. }
  26. if (com.deadpixi.kouprey === undefined) {
  27. com.deadpixi.kouprey = {};
  28. }
  29. /* Parser objects have a unique ID, to help identify rules' cachelines. */
  30. com.deadpixi.kouprey.ParserID = 0;
  31. /* Match objects represent something interesting in the input. */
  32. com.deadpixi.kouprey.Match = function (label, length, offset) {
  33. this.type = label;
  34. this.matchlength = length;
  35. this.offset = offset;
  36. this.children = [];
  37. this.value = undefined;
  38. };
  39. /* Parser objects can be created using the Parser function. Every parser
  40. * has a set of parsing rules, and a root rule. The root rule is the goal of
  41. * the parser - any invocations of the parser will try to ensure that its
  42. * input matches that root rule. The root rule is identified by name. */
  43. com.deadpixi.kouprey.Parser = function (rules, root, debug) {
  44. // Store the rules.
  45. this.rules = rules;
  46. this.root = rules[root];
  47. // Was the root rule valid?
  48. if (this.root === null || this.root === undefined) {
  49. throw "Root rule '" + root + "' is not present in rule set.";
  50. }
  51. // Give this parser a unique ID.
  52. this.parserID = com.deadpixi.kouprey.ParserID++;
  53. // Parsers keep count of how often they've been initialized.
  54. this.initCount = 0;
  55. // Set the debug flag.
  56. this.debug = (debug === undefined) ? false : debug;
  57. // Print out a debug trace.
  58. this.getDebugTrace = function () {
  59. // Function scope variables.
  60. var i, // Loop index.
  61. j, // Loop index.
  62. o, // The output.
  63. s; // Prefix string.
  64. if (this.debug) {
  65. o = "Debug trace: \n" + this.cacheHits + " cache hits.\n";
  66. for (i = 0; i < this.debugStack.length; i++) {
  67. s = "";
  68. for (j = 0; j < this.debugStack[i][1]; j++) {
  69. s = s + " ";
  70. }
  71. o = o + (s + this.debugStack[i][2] + ": " +
  72. this.debugStack[i][0] + "\n");
  73. }
  74. return o;
  75. }
  76. return "No debug trace available.";
  77. };
  78. // The initialization function resets input and cache properties.
  79. this.init = function () {
  80. // Increment the initialization count of this parser. This helps
  81. // identify rule cache lines.
  82. this.initCount++;
  83. // Create an empty input string.
  84. this.input = "";
  85. // Initialize the cache. Note that we don't set up cache lines for
  86. // rules yet; we do that during the call to parse(). This makes sense
  87. // because we want to cache sub-rules of rules too, which aren't
  88. // visible to us until the rule is called.
  89. this.cache = {};
  90. // Start the UID counter. Every rule and subrule is identified by a
  91. // unique ID number.
  92. this.highUID = 0;
  93. // Keep track of the highest offset we've made it to in parser, to
  94. // help in error messages.
  95. this.highestOffset = 0;
  96. // Keep track of the number of cache hits.
  97. this.cacheHits = 0;
  98. // Update the initialization count.
  99. this.initCount++;
  100. // Update the debugging stack.
  101. this.debugStack = [];
  102. this.debugLength = 0;
  103. };
  104. // The parse function actually runs the parser. It expects up to three
  105. // arguments: the input to parse (as a string), the rule to use to parse
  106. // it (as a name), and the offset into the input string at which to
  107. // begin parsing. If the rule is not specified, the root rule is used.
  108. // If the offset is not specified, the offset is 0. If the input value is
  109. // null, it uses the previously-cached input. If input is provided, the
  110. // parser is reinitialized and that input is used.
  111. this.parse = function (input, offset, rule) {
  112. // Function scope variables.
  113. var count, // Match count.
  114. i, // Loop index.
  115. match, // Match to return.
  116. prefix, // Rule UID prefix.
  117. rc; // Temporary match.
  118. // If we don't have an input, use the cached one.
  119. if (input === null || input === undefined) {
  120. input = this.input;
  121. } else {
  122. // If new input is provided, reinitialize.
  123. this.init();
  124. this.input = input;
  125. }
  126. // If we don't have an offset, use zero.
  127. offset = (offset === undefined) ? 0 : offset;
  128. // If we don't have a rule, use the parser-specific root rule.
  129. rule = (rule === undefined) ? this.root : rule;
  130. // Figure out what rule we're in.
  131. if (this.debug) {
  132. this.debugLength++;
  133. if (typeof rule === "string" || rule instanceof String) {
  134. this.debugStack.push([rule, this.debugLength, offset]);
  135. } else {
  136. for (i in this.rules) {
  137. if (this.rules[i] === rule) {
  138. this.debugStack.push([i, this.debugLength, offset]);
  139. break;
  140. }
  141. }
  142. }
  143. }
  144. // The parse function handles terminals, which are presented as
  145. // strings or regular expressions. It also handles sequences,
  146. // represented as arrays. Everything else is represented as a function,
  147. // which the parse function will invoke using their call() methods.
  148. // If our offset is higher than the previous highest, update it.
  149. if (offset >= this.highestOffset) {
  150. this.highestOffset = offset;
  151. }
  152. // Give the rule a UID if it doesn't already have one and set up a
  153. // cache line for this rule.
  154. prefix = this.parserID + "-" + this.initCount + "-";
  155. if (rule.uid === undefined || rule.uid.indexOf(prefix) !== 0) {
  156. rule.uid = prefix + this.highUID++;
  157. this.cache[rule.uid] = {};
  158. }
  159. // Make sure the rule has a cacheline.
  160. if (this.cache[rule.uid] === undefined) {
  161. this.cache[rule.uid] = {};
  162. }
  163. // If this rule already has a cached rule at this offset, return the
  164. // cached result rather than run it again.
  165. if (this.cache[rule.uid][offset] !== undefined) {
  166. this.cacheHits++;
  167. this.debugLength--;
  168. return this.cache[rule.uid][offset];
  169. }
  170. // Parse using the given rule. First, check to see if it's a terminal.
  171. // The simplest type of terminal is a string.
  172. if (typeof rule === "string" || rule instanceof String) {
  173. // Check to see if the string matches the input at the offset.
  174. if (input.substring(offset, offset + rule.length) === rule) {
  175. // We matched.
  176. match = new String(rule);
  177. // Note tha length of the match.
  178. match.matchlength = rule.length;
  179. // Cache the result.
  180. this.cache[rule.uid][offset] = match;
  181. // And return the match.
  182. this.debugLength--;
  183. return match;
  184. }
  185. // Nope, we didn't match. Consume no input and return null.
  186. this.cache[rule.uid][offset] = null;
  187. this.debugLength--;
  188. return null;
  189. }
  190. // The other type of terminal is the regular expression.
  191. if (rule instanceof RegExp) {
  192. // Check for a match.
  193. rc = rule.exec(input.substring(offset));
  194. // Did we get a match?
  195. if (rc !== null && rc !== undefined) {
  196. // We did. Create the match.
  197. match = new String(rc[0]);
  198. // Note the length of the match.
  199. match.matchlength = rc[0].length;
  200. // Cache the result.
  201. this.cache[rule.uid][offset] = match;
  202. // Return the match.
  203. this.debugLength--;
  204. return match;
  205. }
  206. // Didn't match. Consume no input and return null.
  207. this.cache[rule.uid][offset] = null;
  208. this.debugLength--;
  209. return null;
  210. }
  211. // It's an array, indicating a sequence. Check each predicate in turn.
  212. if (rule instanceof Array) {
  213. // We have to build the response piecewise.
  214. rc = [];
  215. count = 0;
  216. // Check each predicate.
  217. for (i = 0; i < rule.length; i++) {
  218. // Check the predicate from the index of the last match.
  219. match = this.parse(null, offset + count, rule[i]);
  220. // If we didn't get a match, fail.
  221. if (match === null || match === undefined) {
  222. // Sequences have to match completely or not at all, so
  223. // we can kill the whole thing here.
  224. this.cache[rule.uid][offset] = null;
  225. this.debugLength--;
  226. return null;
  227. }
  228. // Otherwise, continue on.
  229. if (match.matchlength > 0) {
  230. rc.push(match);
  231. count = count + match.matchlength;
  232. }
  233. }
  234. // The whole thing matched. Horray. Update the length.
  235. rc.matchlength = count;
  236. // Update the cache.
  237. if (this.cache[rule.uid] === undefined) {
  238. this.cache[rule.uid] = [];
  239. }
  240. this.cache[rule.uid][offset] = rc;
  241. // And we're done.
  242. this.debugLength--;
  243. return rc;
  244. }
  245. // If it's a function, call it.
  246. if (typeof rule === "function" || rule instanceof Function) {
  247. // Invoke the rule.
  248. rc = rule.call(this, offset);
  249. if (this.cache[rule.uid] === undefined) {
  250. this.cache[rule.uid] = [];
  251. }
  252. this.cache[rule.uid][offset] = rc;
  253. this.debugLength--;
  254. return rc;
  255. }
  256. // We matched nothing.
  257. this.cache[rule.uid][offset] = null;
  258. this.debugLength--;
  259. return null;
  260. };
  261. };
  262. /* The End predicate matches the end of input. */
  263. com.deadpixi.kouprey.End = function () {
  264. return function (offset) {
  265. return (offset >= this.input.length) ? {matchlength: 0} : null;
  266. };
  267. };
  268. /* The Start predicate matches the start of input. */
  269. com.deadpixi.kouprey.Start = function (offset) {
  270. return function (offset) {
  271. return (offset === 0) ? {matchlength: 0} : null;
  272. };
  273. };
  274. /* Declare a Balanced rule. */
  275. com.deadpixi.kouprey.Balanced = function (start, end, esc) {
  276. return function (offset) {
  277. // Function scope variables.
  278. var counter, // The current count of values.
  279. eend, // The escaped end string.
  280. estart, // The escaped start string.
  281. leend, // Length of escaped end string.
  282. lestart, // Length of escaped start string.
  283. lend, // Length of the end string.
  284. lstart, // Length of the start string.
  285. s; // String contents.
  286. // We start the counter at zero.
  287. counter = 0;
  288. // If there's an escape sequence, initialize the eend and estart stuff.
  289. if (esc !== undefined) {
  290. eend = esc + end;
  291. estart = esc + start;
  292. leend = eend.length;
  293. lestart = estart.length;
  294. } else {
  295. eend = null;
  296. estart = null;
  297. }
  298. // Grab the length of the start and end strings.
  299. lstart = start.length;
  300. lend = end.length;
  301. // Initialize the string match.
  302. s = "";
  303. // If we don't start at the start position, we fail.
  304. if (this.input.substring(offset, offset + lstart) != start) {
  305. return null;
  306. }
  307. // Walk through the input. Every time we encounter the start string,
  308. // increase the counter. Every time we encounter the end string,
  309. // decrease the counter. If the counter hits zero, we're done.
  310. do {
  311. if (this.input.substring(offset, offset + lestart) == estart) {
  312. s = s + estart;
  313. offset = offset + lestart;
  314. } else if (this.input.substring(offset, offset + leend) == eend) {
  315. s = s + eend;
  316. offset = offset + leend;
  317. } else if (this.input.substring(offset, offset + lstart) == start) {
  318. counter++;
  319. s = s + start;
  320. offset = offset + lstart;
  321. } else if (this.input.substring(offset, offset + lend) == end) {
  322. counter--;
  323. s = s + end;
  324. offset = offset + lend;
  325. } else {
  326. s = s + this.input.charAt(offset);
  327. offset++;
  328. }
  329. if (offset >= this.input.length) {
  330. return null;
  331. }
  332. } while (counter !== 0);
  333. // Return the match.
  334. s = new String(s);
  335. s.matchlength = s.length;
  336. return s;
  337. };
  338. };
  339. /* Declare an Or rule. */
  340. com.deadpixi.kouprey.Or = function () {
  341. // Function scope variables.
  342. var options; // Parsing options.
  343. // Copy the options over.
  344. options = arguments;
  345. // Return the closure.
  346. return function (offset) {
  347. // Function scope variables.
  348. var i, // Loop index.
  349. match; // Potential match.
  350. // Check out each alternative.
  351. for (i = 0; i < options.length; i++) {
  352. match = this.parse(null, offset, options[i]);
  353. if (match !== null) {
  354. return match;
  355. }
  356. }
  357. // We matched nothing.
  358. return null;
  359. };
  360. };
  361. /* Declare an Optional predicate. */
  362. com.deadpixi.kouprey.Optional = function (rule) {
  363. return function (offset) {
  364. // Function scope variables.
  365. var match; // Parsing match.
  366. // Check to see if we match.
  367. match = this.parse(null, offset, rule);
  368. // If we did, great.
  369. if (match !== null) {
  370. return match;
  371. }
  372. // If we didn't, that's okay too. We're optional.
  373. return {matchlength: 0};
  374. };
  375. };
  376. /* Declare an Any predicate. */
  377. com.deadpixi.kouprey.Any = function (rule) {
  378. return function (offset) {
  379. // Function scope variables.
  380. var count, // Number of symbols matched.
  381. match, // The match.
  382. rc; // The returned match.
  383. // We haven't matched anything yet.
  384. count = 0;
  385. // We always return something.
  386. rc = [];
  387. rc.matchlength = 0;
  388. // As long as we match, append the value.
  389. match = this.parse(null, offset, rule);
  390. while (match !== null && match.matchlength !== 0) {
  391. // Otherwise, append the match.
  392. rc.push(match);
  393. // Update the count.
  394. count = count + match.matchlength;
  395. // And reparse.
  396. match = this.parse(null, offset + count, rule);
  397. }
  398. // Return the match.
  399. rc.matchlength = count;
  400. return rc;
  401. };
  402. };
  403. /* Declare a Some predicate. */
  404. com.deadpixi.kouprey.Some = function (rule) {
  405. return function (offset) {
  406. if (this.parse(null, offset, rule) !== null) {
  407. return this.parse(null, offset, com.deadpixi.kouprey.Any(rule));
  408. }
  409. return null;
  410. };
  411. };
  412. /* Declare an And rule. */
  413. com.deadpixi.kouprey.And = function (rule) {
  414. return function (offset) {
  415. if (this.parse(null, offset, rule) !== null) {
  416. return {matchlength: 0};
  417. }
  418. return null;
  419. };
  420. };
  421. /* Declare a Not predicate. */
  422. com.deadpixi.kouprey.Not = function (rule) {
  423. return function (offset) {
  424. if (this.parse(null, offset, rule) === null) {
  425. return {matchlength: 0};
  426. }
  427. return null;
  428. };
  429. };
  430. /* Allow for forward declarations. */
  431. com.deadpixi.kouprey.Forward = function (name) {
  432. return function (offset) {
  433. return this.parse(null, offset, this.rules[name]);
  434. };
  435. };
  436. /* Mark a value as interesting. What this does is wrap a match in a
  437. * Match object. It walks through all of the children of a match (if it's an
  438. * object that can have children, like an array), and adds all of the
  439. * interesting children to an array called children. */
  440. com.deadpixi.kouprey.$ = function (rule, label) {
  441. return function (offset) {
  442. // Function scope variables.
  443. var func, // Function to grab interesting child nodes.
  444. match, // The match.
  445. rc; // The returned match.
  446. // Execute the match.
  447. match = this.parse(null, offset, rule);
  448. // If we didn't match, just return null.
  449. if (match === null) {
  450. return null;
  451. }
  452. // The function used to recursively search child nodes.
  453. func = function (node) {
  454. // Function scope variables.
  455. var i, // Loop index.
  456. children, // Matches on child nodes.
  457. rc; // Returned match.
  458. // Initialize the list of children.
  459. rc = [];
  460. // Walk through and find all the interesting children.
  461. if (node instanceof Array) {
  462. for (i = 0; i < node.length; i++) {
  463. if (node[i] instanceof com.deadpixi.kouprey.Match) {
  464. rc = rc.concat(node[i]);
  465. } else {
  466. children = arguments.callee(node[i]);
  467. if (children.length > 0) {
  468. rc = rc.concat(children);
  469. }
  470. }
  471. }
  472. }
  473. // Return list of children.
  474. return rc;
  475. };
  476. // If the label wasn't provided, use the matched value.
  477. label = (label === undefined) ? match.toString() : label;
  478. // The returned match.
  479. rc = new com.deadpixi.kouprey.Match(label, match.matchlength, offset);
  480. // If it's an array, walk through and handle all its children.
  481. if (match instanceof Array) {
  482. rc.children = func(match);
  483. } else {
  484. // Just append the value itself.
  485. rc.value = match;
  486. }
  487. // And return the match.
  488. return rc;
  489. };
  490. };
  491. /* Add the Unicode block table.
  492. * This code was substantially copied from the XRegExp Unicode plugin,
  493. * released under the MIT license. The MIT license is compatible with the
  494. * Lesser GNU General Public License, under which Kouprey is released.
  495. * Below is the copyright declaration and disclaimer as required by the MIT
  496. * license.
  497. *
  498. * Copyright (c) 2009 Steven Levithan
  499. *
  500. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  501. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  502. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  503. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  504. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  505. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  506. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  507. * OTHER DEALINGS IN THE SOFTWARE.
  508. */
  509. com.deadpixi.kouprey.unicodeExps = {};
  510. com.deadpixi.kouprey.unicodeExpsRep = {};
  511. com.deadpixi.kouprey.unicodeInvExps = {};
  512. com.deadpixi.kouprey.unicodeInvExpsRep = {};
  513. com.deadpixi.kouprey.unicode = {
  514. c: "0000-001F007F-009F00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FD800DB7FDB80DBFFDC00DFFFE000F8FFFEFFFFF9-FFFB",
  515. l: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05230531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0904-0939093D09500958-096109710972097B-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1159115F-11A211A8-11F91200-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-16761681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA1900-191C1950-196D1970-19741980-19A919C1-19C71A00-1A161B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2C6F2C71-2C7D2C80-2CE42D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF34004DB54E009FC3A000-A48CA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A90A-A925A930-A946AA00-AA28AA40-AA42AA44-AA4BAC00D7A3F900-FA2DFA30-FA6AFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",
  516. m: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30901-0903093C093E-094D0951-0954096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371DC0-1DE61DFE1DFF20D0-20F02DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA802A806A80BA823-A827A880A881A8B4-A8C4A926-A92DA947-A953AA29-AA36AA43AA4CAA4DFB1EFE00-FE0FFE20-FE26",
  517. n: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19D91B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892153-21822185-21882460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A8D0-A8D9A900-A909AA50-AA59FF10-FF19",
  518. p: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-1368166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1B5A-1B601C3B-1C3F1C7E1C7F2010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E303001-30033008-30113014-301F3030303D30A030FBA60D-A60FA673A67EA874-A877A8CEA8CFA92EA92FA95FAA5C-AA5FFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",
  519. s: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B5210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E72400-24262440-244A249C-24E92500-269D26A0-26BC26C0-26C32701-27042706-2709270C-27272729-274B274D274F-275227562758-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B542CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-324332503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BFB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",
  520. z: "002000A01680180E2000-200A20282029202F205F3000",
  521. inbasiclatin: "0000-007F",
  522. inlatin1supplement: "0080-00FF",
  523. inlatinextendeda: "0100-017F",
  524. inlatinextendedb: "0180-024F",
  525. inipaextensions: "0250-02AF",
  526. inspacingmodifierletters: "02B0-02FF",
  527. incombiningdiacriticalmarks: "0300-036F",
  528. ingreekandcoptic: "0370-03FF",
  529. incyrillic: "0400-04FF",
  530. incyrillicsupplement: "0500-052F",
  531. inarmenian: "0530-058F",
  532. inhebrew: "0590-05FF",
  533. inarabic: "0600-06FF",
  534. insyriac: "0700-074F",
  535. inarabicsupplement: "0750-077F",
  536. inthaana: "0780-07BF",
  537. innko: "07C0-07FF",
  538. indevanagari: "0900-097F",
  539. inbengali: "0980-09FF",
  540. ingurmukhi: "0A00-0A7F",
  541. ingujarati: "0A80-0AFF",
  542. inoriya: "0B00-0B7F",
  543. intamil: "0B80-0BFF",
  544. intelugu: "0C00-0C7F",
  545. inkannada: "0C80-0CFF",
  546. inmalayalam: "0D00-0D7F",
  547. insinhala: "0D80-0DFF",
  548. inthai: "0E00-0E7F",
  549. inlao: "0E80-0EFF",
  550. intibetan: "0F00-0FFF",
  551. inmyanmar: "1000-109F",
  552. ingeorgian: "10A0-10FF",
  553. inhanguljamo: "1100-11FF",
  554. inethiopic: "1200-137F",
  555. inethiopicsupplement: "1380-139F",
  556. incherokee: "13A0-13FF",
  557. inunifiedcanadianaboriginalsyllabics: "1400-167F",
  558. inogham: "1680-169F",
  559. inrunic: "16A0-16FF",
  560. intagalog: "1700-171F",
  561. inhanunoo: "1720-173F",
  562. inbuhid: "1740-175F",
  563. intagbanwa: "1760-177F",
  564. inkhmer: "1780-17FF",
  565. inmongolian: "1800-18AF",
  566. inlimbu: "1900-194F",
  567. intaile: "1950-197F",
  568. innewtailue: "1980-19DF",
  569. inkhmersymbols: "19E0-19FF",
  570. inbuginese: "1A00-1A1F",
  571. inbalinese: "1B00-1B7F",
  572. insundanese: "1B80-1BBF",
  573. inlepcha: "1C00-1C4F",
  574. inolchiki: "1C50-1C7F",
  575. inphoneticextensions: "1D00-1D7F",
  576. inphoneticextensionssupplement: "1D80-1DBF",
  577. incombiningdiacriticalmarkssupplement: "1DC0-1DFF",
  578. inlatinextendedadditional: "1E00-1EFF",
  579. ingreekextended: "1F00-1FFF",
  580. ingeneralpunctuation: "2000-206F",
  581. insuperscriptsandsubscripts: "2070-209F",
  582. incurrencysymbols: "20A0-20CF",
  583. incombiningdiacriticalmarksforsymbols: "20D0-20FF",
  584. inletterlikesymbols: "2100-214F",
  585. innumberforms: "2150-218F",
  586. inarrows: "2190-21FF",
  587. inmathematicaloperators: "2200-22FF",
  588. inmiscellaneoustechnical: "2300-23FF",
  589. incontrolpictures: "2400-243F",
  590. inopticalcharacterrecognition: "2440-245F",
  591. inenclosedalphanumerics: "2460-24FF",
  592. inboxdrawing: "2500-257F",
  593. inblockelements: "2580-259F",
  594. ingeometricshapes: "25A0-25FF",
  595. inmiscellaneoussymbols: "2600-26FF",
  596. indingbats: "2700-27BF",
  597. inmiscellaneousmathematicalsymbolsa: "27C0-27EF",
  598. insupplementalarrowsa: "27F0-27FF",
  599. inbraillepatterns: "2800-28FF",
  600. insupplementalarrowsb: "2900-297F",
  601. inmiscellaneousmathematicalsymbolsb: "2980-29FF",
  602. insupplementalmathematicaloperators: "2A00-2AFF",
  603. inmiscellaneoussymbolsandarrows: "2B00-2BFF",
  604. inglagolitic: "2C00-2C5F",
  605. inlatinextendedc: "2C60-2C7F",
  606. incoptic: "2C80-2CFF",
  607. ingeorgiansupplement: "2D00-2D2F",
  608. intifinagh: "2D30-2D7F",
  609. inethiopicextended: "2D80-2DDF",
  610. incyrillicextendeda: "2DE0-2DFF",
  611. insupplementalpunctuation: "2E00-2E7F",
  612. incjkradicalssupplement: "2E80-2EFF",
  613. inkangxiradicals: "2F00-2FDF",
  614. inideographicdescriptioncharacters: "2FF0-2FFF",
  615. incjksymbolsandpunctuation: "3000-303F",
  616. inhiragana: "3040-309F",
  617. inkatakana: "30A0-30FF",
  618. inbopomofo: "3100-312F",
  619. inhangulcompatibilityjamo: "3130-318F",
  620. inkanbun: "3190-319F",
  621. inbopomofoextended: "31A0-31BF",
  622. incjkstrokes: "31C0-31EF",
  623. inkatakanaphoneticextensions: "31F0-31FF",
  624. inenclosedcjklettersandmonths: "3200-32FF",
  625. incjkcompatibility: "3300-33FF",
  626. incjkunifiedideographsextensiona: "3400-4DBF",
  627. inyijinghexagramsymbols: "4DC0-4DFF",
  628. incjkunifiedideographs: "4E00-9FFF",
  629. inyisyllables: "A000-A48F",
  630. inyiradicals: "A490-A4CF",
  631. invai: "A500-A63F",
  632. incyrillicextendedb: "A640-A69F",
  633. inmodifiertoneletters: "A700-A71F",
  634. inlatinextendedd: "A720-A7FF",
  635. insylotinagri: "A800-A82F",
  636. inphagspa: "A840-A87F",
  637. insaurashtra: "A880-A8DF",
  638. inkayahli: "A900-A92F",
  639. inrejang: "A930-A95F",
  640. incham: "AA00-AA5F",
  641. inhangulsyllables: "AC00-D7AF",
  642. inhighsurrogates: "D800-DB7F",
  643. inhighprivateusesurrogates: "DB80-DBFF",
  644. inlowsurrogates: "DC00-DFFF",
  645. inprivateusearea: "E000-F8FF",
  646. incjkcompatibilityideographs: "F900-FAFF",
  647. inalphabeticpresentationforms: "FB00-FB4F",
  648. inarabicpresentationformsa: "FB50-FDFF",
  649. invariationselectors: "FE00-FE0F",
  650. inverticalforms: "FE10-FE1F",
  651. incombininghalfmarks: "FE20-FE2F",
  652. incjkcompatibilityforms: "FE30-FE4F",
  653. insmallformvariants: "FE50-FE6F",
  654. inarabicpresentationformsb: "FE70-FEFF",
  655. inhalfwidthandfullwidthforms: "FF00-FFEF",
  656. inspecials: "FFF0-FFFF"
  657. };
  658. /* Initialize the Unicode table. */
  659. (function () {
  660. // Function scope variables.
  661. var p, // Loop index.
  662. s; // Transformed string.
  663. for (p in com.deadpixi.kouprey.unicode) {
  664. if (com.deadpixi.kouprey.unicode.hasOwnProperty(p)) {
  665. s = com.deadpixi.kouprey.unicode[p].replace(/\w{4}/g, "\\u$&");
  666. com.deadpixi.kouprey.unicodeExps[p] =
  667. new RegExp("^[" + s + "]");
  668. com.deadpixi.kouprey.unicodeExpsRep[p] =
  669. new RegExp("^[" + s + "]+");
  670. com.deadpixi.kouprey.unicodeInvExps[p] =
  671. new RegExp("^[^" + s + "]");
  672. com.deadpixi.kouprey.unicodeInvExpsRep[p] =
  673. new RegExp("^[^" + s + "]+");
  674. }
  675. }
  676. })();
  677. /* Create the Unicode matching combinator. */
  678. com.deadpixi.kouprey.u = function (block) {
  679. // Function scope variables.
  680. var exp; // The expression we're going to return.
  681. // Fix the block to account for spaces and such in the block name.
  682. block = block.replace(/[- _^]+/g, "").toLowerCase();
  683. if (block.charAt(block.length - 1) === "+") {
  684. return com.deadpixi.kouprey.unicodeExpsRep[
  685. block.substring(0, block.length - 1)];
  686. } else {
  687. return com.deadpixi.kouprey.unicodeExps[block];
  688. }
  689. };
  690. /* Create the Unicode inverse matching combinator. */
  691. com.deadpixi.kouprey.U = function (block) {
  692. // Function scope variables.
  693. var exp; // The expression we're going to return.
  694. // Fix the block to account for spaces and such in the block name.
  695. block = block.replace(/[- _^]+/g, "").toLowerCase();
  696. if (block.charAt(block.length - 1) === "+") {
  697. return com.deadpixi.kouprey.unicodeInvExpsRep[
  698. block.substring(0, block.length - 1)];
  699. } else {
  700. return com.deadpixi.kouprey.unicodeInvExps[block];
  701. }
  702. };
  703. /* ------------------------------ EXPORTS ------------------------------ */
  704. if (typeof module !== "undefined" && module.exports) module.exports = com;