MatchExpressionParser.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. "use strict";
  2. // Autogenerated by cport.py on 2013-09-17 14:37
  3. var MatchExpressionParser = module.exports = function (){
  4. }, klass = MatchExpressionParser, base = Object , proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  5. // DEPENDENCIES
  6. var errors = require("../../Errors.js"),
  7. ErrorCodes = errors.ErrorCodes,
  8. AndMatchExpression = require("./AndMatchExpression.js"),
  9. MatchExpression = require("./MatchExpression.js"),
  10. OrMatchExpression = require("./OrMatchExpression.js"),
  11. ModMatchExpression = require("./ModMatchExpression.js"),
  12. NorMatchExpression = require("./NorMatchExpression.js"),
  13. NotMatchExpression = require("./NotMatchExpression.js"),
  14. LTMatchExpression = require("./LTMatchExpression.js"),
  15. LTEMatchExpression = require("./LTEMatchExpression.js"),
  16. GTMatchExpression = require("./GTMatchExpression.js"),
  17. GTEMatchExpression = require("./GTEMatchExpression.js"),
  18. InMatchExpression = require("./InMatchExpression.js"),
  19. SizeMatchExpression = require("./SizeMatchExpression.js"),
  20. TypeMatchExpression = require("./TypeMatchExpression.js"),
  21. ExistsMatchExpression = require("./ExistsMatchExpression.js"),
  22. EqualityMatchExpression = require("./EqualityMatchExpression.js"),
  23. ArrayMatchingMatchExpression = require("./ArrayMatchingMatchExpression.js"),
  24. RegexMatchExpression = require("./RegexMatchExpression.js"),
  25. FalseMatchExpression = require("./FalseMatchExpression.js"),
  26. ComparisonMatchExpression = require("./ComparisonMatchExpression.js"),
  27. ElemMatchValueMatchExpression = require("./ElemMatchValueMatchExpression.js"),
  28. ElemMatchObjectMatchExpression = require("./ElemMatchObjectMatchExpression.js"),
  29. AllElemMatchOp = require("./AllElemMatchOp.js"),
  30. AtomicMatchExpression = require("./AtomicMatchExpression.js");
  31. /**
  32. *
  33. * This documentation was automatically generated. Please update when you touch this function.
  34. * @method _isExpressionDocument
  35. * @param
  36. *
  37. */
  38. proto._isExpressionDocument = function _isExpressionDocument(element){
  39. // File: expression_parser.cpp lines: 340-355
  40. if (!(element instanceof Object))
  41. return false;
  42. if (Object.keys(element).length === 0)
  43. return false;
  44. var name = Object.keys(element)[0];
  45. if (name[0] != '$')
  46. return false;
  47. if ("$ref" == name)
  48. return false;
  49. return true;
  50. };
  51. /**
  52. *
  53. * This documentation was automatically generated. Please update when you touch this function.
  54. * @method _parse
  55. * @param
  56. *
  57. */
  58. proto._parse = function _parse(obj, topLevel){
  59. // File: expression_parser.cpp lines: 217-319
  60. var rest, temp, status, element, eq, real;
  61. var root = new AndMatchExpression();
  62. var objkeys = Object.keys(obj);
  63. var currname, currval;
  64. for (var i = 0; i < objkeys.length; i++) {
  65. currname = objkeys[i];
  66. currval = obj[currname];
  67. if (currname[0] == '$' ) {
  68. rest = currname.substr(1);
  69. // TODO: optimize if block?
  70. if ("or" == rest) {
  71. if (!(currval instanceof Array))
  72. return {code:ErrorCodes.BAD_VALUE, description:"$or needs an array"};
  73. temp = new OrMatchExpression();
  74. status = this._parseTreeList(currval, temp);
  75. if (status.code != ErrorCodes.OK)
  76. return status;
  77. root.add(temp);
  78. }
  79. else if ("and" == rest) {
  80. if (!(currval instanceof Array))
  81. return {code:ErrorCodes.BAD_VALUE, description:"and needs an array"};
  82. temp = new AndMatchExpression();
  83. status = this._parseTreeList(currval, temp);
  84. if (status.code != ErrorCodes.OK)
  85. return status;
  86. root.add(temp);
  87. }
  88. else if ("nor" == rest) {
  89. if (!(currval instanceof Array))
  90. return {code:ErrorCodes.BAD_VALUE, description:"and needs an array"};
  91. temp = new NorMatchExpression();
  92. status = this._parseTreeList(currval, temp);
  93. if (status.code != ErrorCodes.OK)
  94. return status;
  95. root.add(temp);
  96. }
  97. else if (("atomic" == rest) || ("isolated" == rest)) {
  98. if (!topLevel)
  99. return {code:ErrorCodes.BAD_VALUE, description:"$atomic/$isolated has to be at the top level"};
  100. if (element)
  101. root.add(new AtomicMatchExpression());
  102. }
  103. else if ("where" == rest) {
  104. /*
  105. if ( !topLevel )
  106. return StatusWithMatchExpression( ErrorCodes::BAD_VALUE, "$where has to be at the top level" );
  107. */
  108. return {'code':'FAILED_TO_PARSE', 'desc':'Where unimplimented.'};
  109. status = this.expressionParserWhereCallback(element);
  110. if (status.code != ErrorCodes.OK)
  111. return status;
  112. root.add(status.result);
  113. }
  114. else if ("comment" == rest) {
  115. }
  116. else {
  117. return {code:ErrorCodes.BAD_VALUE, description:"unknown top level operator: " + currname};
  118. }
  119. continue;
  120. }
  121. if (this._isExpressionDocument(currval)) {
  122. status = this._parseSub(currname, currval, root);
  123. if (status.code != ErrorCodes.OK)
  124. return status;
  125. continue;
  126. }
  127. if (currval instanceof RegExp) {
  128. status = this._parseRegexElement(currname, currval);
  129. if (status.code != ErrorCodes.OK)
  130. return status;
  131. root.add(status.result);
  132. continue;
  133. }
  134. eq = new EqualityMatchExpression();
  135. status = eq.init(currname, currval);
  136. if (status.code != ErrorCodes.OK)
  137. return status;
  138. root.add(eq);
  139. }
  140. if (root.numChildren() == 1) {
  141. return {code:ErrorCodes.OK, result:root.getChild(0)};
  142. }
  143. return {code:ErrorCodes.OK, result:root};
  144. };
  145. /**
  146. *
  147. * This documentation was automatically generated. Please update when you touch this function.
  148. * @method _parseAll
  149. * @param
  150. *
  151. */
  152. proto._parseAll = function _parseAll(name, element){
  153. // File: expression_parser.cpp lines: 512-583
  154. var status, i;
  155. if (!(element instanceof Array))
  156. return {code:ErrorCodes.BAD_VALUE, description:"$all needs an array"};
  157. var arr = element;
  158. if ((arr[0] instanceof Object) && ("$elemMatch" == Object.keys(arr[0])[0])) {
  159. // $all : [ { $elemMatch : {} } ... ]
  160. var temp = new AllElemMatchOp();
  161. status = temp.init(name);
  162. if (status.code != ErrorCodes.OK)
  163. return status;
  164. for (i = 0; i < arr.length; i++) {
  165. var hopefullyElemMatchElement = arr[i];
  166. if (!(hopefullyElemMatchElement instanceof Object)) {
  167. // $all : [ { $elemMatch : ... }, 5 ]
  168. return {code:ErrorCodes.BAD_VALUE, description:"$all/$elemMatch has to be consistent"};
  169. }
  170. if ("$elemMatch" != hopefullyElemMatchElement.keys()[0]) {
  171. // $all : [ { $elemMatch : ... }, { x : 5 } ]
  172. return {code:ErrorCodes.BAD_VALUE, description:"$all/$elemMatch has to be consistent"};
  173. }
  174. status = this._parseElemMatch("", hopefullyElemMatchElement[hopefullyElemMatchElement.keys()[0]]); // TODO: wrong way to do this?
  175. if (status.code != ErrorCodes.OK)
  176. return status;
  177. temp.add(new ArrayMatchingMatchExpression(status.result));
  178. }
  179. return {code:ErrorCodes.OK, result:temp};
  180. }
  181. var myAnd = new AndMatchExpression();
  182. for (i = 0; i < arr.length; i++) {
  183. var e = arr[i];
  184. if (e instanceof RegExp) {
  185. var r = new RegexMatchExpression();
  186. status = r.init(name, e);
  187. if (status.code != ErrorCodes.OK)
  188. return status;
  189. myAnd.add(r);
  190. }
  191. else if ((e instanceof Object) && (typeof(Object.keys(e)[0] == 'string' && Object.keys(e)[0][0] == '$' ))) {
  192. return {code:ErrorCodes.BAD_VALUE, description:"no $ expressions in $all"};
  193. }
  194. else {
  195. var x = new EqualityMatchExpression();
  196. status = x.init(name, e);
  197. if (status.code != ErrorCodes.OK)
  198. return status;
  199. myAnd.add(x);
  200. }
  201. }
  202. if (myAnd.numChildren() === 0) {
  203. return {code:ErrorCodes.OK, result:new FalseMatchExpression()};
  204. }
  205. return {code:ErrorCodes.OK, result:myAnd};
  206. };
  207. /**
  208. *
  209. * This documentation was automatically generated. Please update when you touch this function.
  210. * @method _parseArrayFilterEntries
  211. * @param
  212. *
  213. */
  214. proto._parseArrayFilterEntries = function _parseArrayFilterEntries(entries, theArray){
  215. // File: expression_parser.cpp lines: 445-468
  216. var status, e, r;
  217. for (var i = 0; i < theArray.length; i++) {
  218. e = theArray[i];
  219. if (e instanceof RegExp ) {
  220. r = new RegexMatchExpression();
  221. status = r.init("", e);
  222. if (status.code != ErrorCodes.OK)
  223. return status;
  224. status = entries.addRegex(r);
  225. if (status.code != ErrorCodes.OK)
  226. return status;
  227. }
  228. else {
  229. status = entries.addEquality(e);
  230. if (status.code != ErrorCodes.OK)
  231. return status;
  232. }
  233. }
  234. return {code:ErrorCodes.OK};
  235. };
  236. /**
  237. *
  238. * This documentation was automatically generated. Please update when you touch this function.
  239. * @method _parseComparison
  240. * @param
  241. *
  242. */
  243. proto._parseComparison = function _parseComparison(name, cmp, element){
  244. // File: expression_parser.cpp lines: 34-43
  245. var temp = new ComparisonMatchExpression(cmp);
  246. var status = temp.init(name, element);
  247. if (status.code != ErrorCodes.OK)
  248. return status;
  249. return {code:ErrorCodes.OK, result:temp};
  250. };
  251. /**
  252. *
  253. * This documentation was automatically generated. Please update when you touch this function.
  254. * @method _parseElemMatch
  255. * @param
  256. *
  257. */
  258. proto._parseElemMatch = function _parseElemMatch(name, element){
  259. // File: expression_parser.cpp lines: 471-509
  260. var temp, status;
  261. if (!(element instanceof Object))
  262. return {code:ErrorCodes.BAD_VALUE, description:"$elemMatch needs an Object"};
  263. if (this._isExpressionDocument(element)) {
  264. // value case
  265. var theAnd = new AndMatchExpression();
  266. status = this._parseSub("", element, theAnd);
  267. if (status.code != ErrorCodes.OK)
  268. return status;
  269. temp = new ElemMatchValueMatchExpression();
  270. status = temp.init(name);
  271. if (status.code != ErrorCodes.OK)
  272. return status;
  273. for (var i = 0; i < theAnd.numChildren(); i++ ) {
  274. temp.add(theAnd.getChild(i));
  275. }
  276. theAnd.clearAndRelease();
  277. return {code:ErrorCodes.OK, result:temp};
  278. }
  279. // object case
  280. status = this._parse(element, false);
  281. if (status.code != ErrorCodes.OK)
  282. return status;
  283. temp = new ElemMatchObjectMatchExpression();
  284. status = temp.init(name, status.result);
  285. if (status.code != ErrorCodes.OK)
  286. return status;
  287. return {code:ErrorCodes.OK, result:temp};
  288. };
  289. /**
  290. *
  291. * This documentation was automatically generated. Please update when you touch this function.
  292. * @method _parseMOD
  293. * @param
  294. *
  295. */
  296. proto._parseMOD = function _parseMOD(name, element){
  297. // File: expression_parser.cpp lines: 360-387
  298. if (!(element instanceof Array))
  299. return {code:ErrorCodes.BAD_VALUE, result:"malformed mod, needs to be an array"};
  300. if (element.length < 2)
  301. return {code:ErrorCodes.BAD_VALUE, result:"malformed mod, not enough elements"};
  302. if (element.length > 2)
  303. return {code:ErrorCodes.BAD_VALUE, result:"malformed mod, too many elements"};
  304. if (!(element[0] instanceof Number))
  305. return {code:ErrorCodes.BAD_VALUE, result:"malformed mod, divisor not a number"};
  306. if (!(element[1] instanceof Number))
  307. return {code:ErrorCodes.BAD_VALUE, result:"malformed mod, remainder not a number"};
  308. var temp = new ModMatchExpression();
  309. var status = temp.init( name, element[0], element[1]);
  310. if (status.code != ErrorCodes.OK)
  311. return status;
  312. return {code:ErrorCodes.OK, result:temp};
  313. };
  314. /**
  315. *
  316. * This documentation was automatically generated. Please update when you touch this function.
  317. * @method _parseNot
  318. * @param
  319. *
  320. */
  321. proto._parseNot = function _parseNot(name, element){
  322. // File: expression_parser_tree.cpp lines: 55-91
  323. var status;
  324. if (element instanceof RegExp) {
  325. status = this._parseRegexElement(name, element);
  326. if (status.code != ErrorCodes.OK)
  327. return status;
  328. var n = new NotMatchExpression();
  329. status = n.init(status.result);
  330. if (status.code != ErrorCodes.OK)
  331. return status;
  332. return {code:ErrorCodes.OK, result:n};
  333. }
  334. if (!(element instanceof Object))
  335. return {code:ErrorCodes.BAD_VALUE, result:"$not needs a regex or a document"};
  336. if (element == {})
  337. return {code:ErrorCodes.BAD_VALUE, result:"$not cannot be empty"};
  338. var theAnd = new AndMatchExpression();
  339. status = this._parseSub(name, element, theAnd);
  340. if (status.code != ErrorCodes.OK)
  341. return status;
  342. // TODO: this seems arbitrary?
  343. // tested in jstests/not2.js
  344. for (var i = 0; i < theAnd.numChildren(); i++) {
  345. if (theAnd.getChild(i).matchType == MatchExpression.REGEX) {
  346. return {code:ErrorCodes.BAD_VALUE, result:"$not cannot have a regex"};
  347. }
  348. }
  349. var theNot = new NotMatchExpression();
  350. status = theNot.init(theAnd);
  351. if (status.code != ErrorCodes.OK)
  352. return status;
  353. return {code:ErrorCodes.OK, result:theNot};
  354. };
  355. /**
  356. *
  357. * This documentation was automatically generated. Please update when you touch this function.
  358. * @method _parseRegexDocument
  359. * @param
  360. *
  361. */
  362. proto._parseRegexDocument = function _parseRegexDocument(name, doc){
  363. // File: expression_parser.cpp lines: 402-442
  364. var regex, regexOptions, e;
  365. for (var i = 0; i < doc.length; i++) {
  366. e = doc[i];
  367. switch (e.getGtLtOp()) {
  368. case 'opREGEX':
  369. if (e instanceof String) {
  370. regex = e;
  371. }
  372. else if (e instanceof RegExp) {
  373. var str = e.toString(),
  374. flagIndex = 0;
  375. for (var c = str.length; c > 0; c--){
  376. if (str[c] == '/') {
  377. flagIndex = c;
  378. break;
  379. }
  380. }
  381. regex = str.substr(1, flagIndex-1);
  382. regexOptions = str.substr(flagIndex, str.length);
  383. }
  384. else {
  385. return {code:ErrorCodes.BAD_VALUE, description:"$regex has to be a string"};
  386. }
  387. break;
  388. case 'opOPTIONS':
  389. if (!(e instanceof String))
  390. return {code:ErrorCodes.BAD_VALUE, description:"$options has to be a string"};
  391. regexOptions = e;
  392. break;
  393. default:
  394. break;
  395. }
  396. }
  397. var temp = new RegexMatchExpression();
  398. var status = temp.init(name, regex, regexOptions);
  399. if (status.code != ErrorCodes.OK)
  400. return status;
  401. return {code:ErrorCodes.OK, result:temp};
  402. };
  403. /**
  404. *
  405. * This documentation was automatically generated. Please update when you touch this function.
  406. * @method _parseRegexElement
  407. * @param
  408. *
  409. */
  410. proto._parseRegexElement = function _parseRegexElement(name, element){
  411. // File: expression_parser.cpp lines: 390-399
  412. if (!(element instanceof RegExp))
  413. return {code:ErrorCodes.BAD_VALUE, description:"not a regex"};
  414. var str = element.toString(),
  415. flagIndex = 0;
  416. for (var c = str.length; c > 0; c--){
  417. if (str[c] == '/') {
  418. flagIndex = c;
  419. break;
  420. }
  421. }
  422. var regex = str.substr(1, flagIndex-1),
  423. regexOptions = str.substr(flagIndex+1, str.length),
  424. temp = new RegexMatchExpression(),
  425. status = temp.init(name, regex, regexOptions);
  426. if (status.code != ErrorCodes.OK)
  427. return status;
  428. return {code:ErrorCodes.OK, result:temp};
  429. };
  430. /**
  431. *
  432. * This documentation was automatically generated. Please update when you touch this function.
  433. * @method _parseSub
  434. * @param
  435. *
  436. */
  437. proto._parseSub = function _parseSub(name, sub, root){
  438. // File: expression_parser.cpp lines: 322-337
  439. var subkeys = Object.keys(sub),
  440. currname, currval;
  441. for (var i = 0; i < subkeys.length; i++) {
  442. currname = subkeys[i];
  443. currval = sub[currname];
  444. var deep = {};
  445. deep[currname] = currval;
  446. var status = this._parseSubField(sub, root, name, deep);
  447. if (status.code != ErrorCodes.OK)
  448. return status;
  449. if (status.result)
  450. root.add(status.result);
  451. }
  452. return {code:ErrorCodes.OK, result:root};
  453. };
  454. /**
  455. *
  456. * This documentation was automatically generated. Please update when you touch this function.
  457. * @method _parseSubField
  458. * @param
  459. *
  460. */
  461. proto._parseSubField = function _parseSubField(context, andSoFar, name, element){
  462. // File: expression_parser.cpp lines: 46-214
  463. // TODO: these should move to getGtLtOp, or its replacement
  464. var currname = Object.keys(element)[0];
  465. var currval = element[currname];
  466. if ("$eq" == currname)
  467. return this._parseComparison(name, 'EQ', currval);
  468. if ("$not" == currname) {
  469. return this._parseNot(name, currval);
  470. }
  471. var status, temp, temp2;
  472. switch (currname) {
  473. case '$lt':
  474. return this._parseComparison(name, 'LT', currval);
  475. case '$lte':
  476. return this._parseComparison(name, 'LTE', currval);
  477. case '$gt':
  478. return this._parseComparison(name, 'GT', currval);
  479. case '$gte':
  480. return this._parseComparison(name, 'GTE', currval);
  481. case '$ne':
  482. status = this._parseComparison(name, 'EQ', currval);
  483. if (status.code != ErrorCodes.OK)
  484. return status;
  485. var n = new NotMatchExpression();
  486. status = n.init(status.result);
  487. if (status.code != ErrorCodes.OK)
  488. return status;
  489. return {code:ErrorCodes.OK, result:n};
  490. case '$eq':
  491. return this._parseComparison(name, 'EQ', currval);
  492. case '$in':
  493. if (!(currval instanceof Array))
  494. return {code:ErrorCodes.BAD_VALUE, description:"$in needs an array"};
  495. temp = new InMatchExpression();
  496. status = temp.init(name);
  497. if (status.code != ErrorCodes.OK)
  498. return status;
  499. status = this._parseArrayFilterEntries(temp.getArrayFilterEntries(), currval);
  500. if (status.code != ErrorCodes.OK)
  501. return status;
  502. return {code:ErrorCodes.OK, result:temp};
  503. case '$nin':
  504. if (!(currval instanceof Array))
  505. return {code:ErrorCodes.BAD_VALUE, description:"$nin needs an array"};
  506. temp = new InMatchExpression();
  507. status = temp.init(name);
  508. if (status.code != ErrorCodes.OK)
  509. return status;
  510. status = this._parseArrayFilterEntries(temp.getArrayFilterEntries(), currval);
  511. if (status.code != ErrorCodes.OK)
  512. return status;
  513. temp2 = new NotMatchExpression();
  514. status = temp2.init(temp);
  515. if (status.code != ErrorCodes.OK)
  516. return status;
  517. return {code:ErrorCodes.OK, result:temp2};
  518. case '$size':
  519. var size = 0;
  520. if (currval instanceof String || typeof(currval) === 'string')
  521. // matching old odd semantics
  522. size = 0;
  523. else if (typeof(currval) === 'number' || currval instanceof Number)
  524. size = currval;
  525. else {
  526. return {code:ErrorCodes.BAD_VALUE, description:"$size needs a number"};
  527. }
  528. temp = new SizeMatchExpression();
  529. status = temp.init(name, size);
  530. if (status.code != ErrorCodes.OK)
  531. return status;
  532. return {code:ErrorCodes.OK, result:temp};
  533. case '$exists':
  534. if (currval == {})
  535. return {code:ErrorCodes.BAD_VALUE, description:"$exists can't be eoo"};
  536. temp = new ExistsMatchExpression();
  537. status = temp.init(name);
  538. if (status.code != ErrorCodes.OK)
  539. return status;
  540. if (currval)
  541. return {code:ErrorCodes.OK, result:temp};
  542. temp2 = new NotMatchExpression();
  543. status = temp2.init(temp);
  544. if (status.code != ErrorCodes.OK)
  545. return status;
  546. return {code:ErrorCodes.OK, result:temp2};
  547. case '$type':
  548. if (!(currval instanceof Number || typeof(currval) === 'number'))
  549. return {code:ErrorCodes.BAD_VALUE, description:"$type has to be a number"};
  550. var type = currval;
  551. temp = new TypeMatchExpression();
  552. status = temp.init(name, type);
  553. if (status.code != ErrorCodes.OK)
  554. return status;
  555. return {code:ErrorCodes.OK, result:temp};
  556. case '$mod':
  557. return this._parseMOD(name, currval);
  558. case '$options':
  559. // TODO: try to optimize this
  560. // we have to do this since $options can be before or after a $regex
  561. // but we validate here
  562. for(var i = 0; i < Object.keys(context).length; i++) {
  563. temp = Object.keys(context)[i];
  564. if (temp == '$regex')
  565. return {code:ErrorCodes.OK, result:null};
  566. }
  567. return {code:ErrorCodes.BAD_VALUE, description:"$options needs a $regex"};
  568. case '$regex':
  569. return this._parseRegexDocument(name, context);
  570. case '$elemMatch':
  571. return this._parseElemMatch(name, currval);
  572. case '$all':
  573. return this._parseAll(name, currval);
  574. case '$geoWithin':
  575. case '$geoIntersects':
  576. case '$near':
  577. case '$nearSphere':
  578. return this.expressionParserGeoCallback(name, x, context);
  579. } // end switch
  580. return {code:ErrorCodes.BAD_VALUE, description:"not handled: " + element};
  581. };
  582. /**
  583. *
  584. * This documentation was automatically generated. Please update when you touch this function.
  585. * @method _parseTreeList
  586. * @param
  587. *
  588. */
  589. proto._parseTreeList = function _parseTreeList(arr, out){
  590. // File: expression_parser_tree.cpp lines: 33-52
  591. if (arr.length === 0)
  592. return {code:ErrorCodes.BAD_VALUE, description:"$and/$or/$nor must be a nonempty array"};
  593. var status, element;
  594. for (var i = 0; i < arr.length; i++) {
  595. element = arr[i];
  596. if (!(element instanceof Object))
  597. return {code:ErrorCodes.BAD_VALUE, description:"$or/$and/$nor entries need to be full objects"};
  598. status = this._parse(element, false);
  599. if (status.code != ErrorCodes.OK)
  600. return status;
  601. out.add(status.result);
  602. }
  603. return {code:ErrorCodes.OK};
  604. };
  605. /**
  606. *
  607. * This documentation was automatically generated. Please update when you touch this function.
  608. * @method parse
  609. * @param
  610. *
  611. */
  612. proto.parse = function parse(obj){
  613. // File: expression_parser.h lines: 40-41
  614. return this._parse(obj, true);
  615. };