MatchExpressionParser.js 20 KB

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