Pteros  2.0
Molecular modeling library for human beings!
selection_grammar.h
1 /*
2  *
3  * This source code is part of
4  * ******************
5  * *** Pteros ***
6  * ******************
7  * molecular modeling library
8  *
9  * Copyright (c) 2009-2013, Semen Yesylevskyy
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of Artistic License:
13  *
14  * Please note, that Artistic License is slightly more restrictive
15  * then GPL license in terms of distributing the modified versions
16  * of this software (they should be approved first).
17  * Read http://www.opensource.org/licenses/artistic-license-2.0.php
18  * for details. Such license fits scientific software better then
19  * GPL because it prevents the distribution of bugged derivatives.
20  *
21 */
22 
23 #ifndef SELECTION_GRAMMAR_H
24 #define SELECTION_GRAMMAR_H
25 
26 #include "selection_parser.h"
27 #include <functional>
28 #include <map>
29 #include "pteros/core/pteros_error.h"
30 
31 //===========================================================
32 using namespace std;
33 using namespace std::placeholders;
34 using namespace pteros;
35 
36 #ifdef _DEBUG_PARSER
37 #define DEBUG(code) code
38 #else
39 #define DEBUG(code)
40 #endif
41 
42 
43 #ifdef _DEBUG_PARSER
44 /*===================================================*/
45 /* Rule macros for debug mode - with rule names */
46 /*===================================================*/
47 
48 // Rule
49 #define RULE(_name) \
50 bool _name(bool add_to_tree = true, bool do_memo = true){ \
51  return rule_proxy(__LINE__, /*rule_id*/ \
52  add_to_tree, do_memo, \
53  false, /* do_reduce */ \
54  "", /* literal */ \
55  std::bind(&Grammar::_name##_body,this,_1,_2,_3), \
56  #_name); /* rule_name */ \
57 }\
58 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
59 
60 // Reduction rule
61 #define RULE_REDUCE(_name) \
62 bool _name(bool add_to_tree = true, bool do_memo = true){ \
63  return rule_proxy(__LINE__, /*rule_id*/ \
64  add_to_tree, do_memo, \
65  true, /* do_reduce */ \
66  "", /* literal */ \
67  std::bind(&Grammar::_name##_body,this,_1,_2,_3), \
68  #_name); /* rule_name */ \
69 }\
70 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
71 
72 // Literal rule
73 #define LITERAL_RULE(_name, _lit) \
74 bool _name(bool add_to_tree = true, bool do_memo = false){ \
75  return rule_proxy(__LINE__, /*rule_id*/ \
76  add_to_tree, do_memo, \
77  false, /* do_reduce */ \
78  _lit, /* literal */ \
79  std::bind(&Grammar::_name##_body,this,_1,_2,_3), \
80  #_name); /* rule_name */ \
81 }\
82 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
83 
84 #else
85 
86 /*========================================================*/
87 /* Rule macros for release mode - without rule names */
88 /*========================================================*/
89 
90 // Rule
91 #define RULE(_name) \
92 bool _name(bool add_to_tree = true, bool do_memo = true){ \
93  return rule_proxy(__LINE__, /*rule_id*/ \
94  add_to_tree, do_memo, \
95  false, /* do_reduce */ \
96  "", /* literal */ \
97  std::bind(&Grammar::_name##_body,this,_1,_2,_3) ); \
98 }\
99 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
100 
101 // Reduction rule
102 #define RULE_REDUCE(_name) \
103 bool _name(bool add_to_tree = true, bool do_memo = true){ \
104  return rule_proxy(__LINE__, /*rule_id*/ \
105  add_to_tree, do_memo, \
106  true, /* do_reduce */ \
107  "", /* literal */ \
108  std::bind(&Grammar::_name##_body,this,_1,_2,_3) ); \
109 }\
110 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
111 
112 // Literal rule
113 #define LITERAL_RULE(_name, _lit) \
114 bool _name(bool add_to_tree = true, bool do_memo = false){ \
115  return rule_proxy(__LINE__, /*rule_id*/ \
116  add_to_tree, do_memo, \
117  false, /* do_reduce */ \
118  _lit, /* literal */ \
119  std::bind(&Grammar::_name##_body,this,_1,_2,_3) ); \
120 }\
121 void _name##_body(AstNode_ptr& _this_rule_, bool& _ok_, const std::string::iterator& _old_) \
122 
123 #endif
124 
125 
126 
127 #define SUBRULE(n) (_this_rule_->child_node(n))
128 
129 #define NUM_SUBRULES() (_this_rule_->children.size())
130 
131 /*===================================*/
132 /* PREDICATES */
133 /*===================================*/
134 
135 // Predicate, which combines sequence of rules. If sequence fails it rewinds _pos_ to beginning
136 #define Comb(rule) \
137  ( \
138  [this,&_this_rule_]()->bool{ \
139  std::string::iterator old=_pos_; \
140  int old_sz = NUM_SUBRULES(); \
141  bool ok = (rule);\
142  if(!ok) { \
143  _pos_ = old; \
144  _this_rule_->children.resize(old_sz); \
145  } \
146  return ok; \
147  }() \
148  )
149 
150 // Make rule optional
151 #define Opt(rule) (Comb(rule)||true)
152 
153 // Predicate, which checks if rule matches, but doesn't advance iterator
154 #define Check(rule) \
155  ( \
156  [this,&_this_rule_]()->bool{ \
157  std::string::iterator old=_pos_; \
158  int old_sz = NUM_SUBRULES(); \
159  bool ok = (rule);\
160  _pos_ = old; \
161  _this_rule_->children.resize(old_sz); \
162  return ok; \
163  }() \
164  )
165 
166 #define ZeroOrMore(rule) \
167  ( \
168  [this,&_this_rule_]()->bool{ \
169  bool ok = true; \
170  while(ok){ ok = Comb(rule); } \
171  return true; \
172  }() \
173  )
174 
175 #define OneOrMore(rule) \
176  ( \
177  [this,&_this_rule_]()->bool{ \
178  bool ok = Comb(rule); \
179  if(!ok) return false; \
180  while(ok){ ok = Comb(rule); } \
181  return true; \
182  }() \
183  )
184 
185 /*===================================*/
186 /* Memo table */
187 /*===================================*/
188 
189 struct Memo_data {
190  Memo_data(){}
191  Memo_data(bool _ok, const AstNode_ptr& _tree, const string::iterator& _pos):
192  ok(_ok), tree(_tree), pos(_pos) {}
193 
194  bool ok; // Rule evaluation result
195  AstNode_ptr tree; // Subtree
196  string::iterator pos; // iterator after rule completion
197 };
198 
199 
200 
201 /*===================================*/
202 /* THE GRAMMAR */
203 /*===================================*/
204 
205 class Grammar {
206 private:
207  std::string::iterator _pos_,beg,end,last_success;
208  AstNode_ptr current_parent;
209  // Memo table
210  map<int, map<int,Memo_data> > memo;
211 
212 #ifdef _DEBUG_PARSER
213  int level; // For pretty printing
214  int num_stored, num_restored;
215  int max_level;
216  int num_tried;
217  int num_failed;
218 #endif
219 
220 public:
221  Grammar(std::string& s){
222  _pos_ = beg = last_success = s.begin();
223  end = s.end();
224 
225 #ifdef _DEBUG_PARSER
226  level = 0;
227  num_stored = 0;
228  num_restored = 0;
229  max_level = 0;
230  num_tried = 0;
231  num_failed = 0;
232 #endif
233  }
234 
235 #ifdef _DEBUG_PARSER
236  bool rule_proxy(const int rule_id, bool add_to_tree, bool do_memo, bool do_reduce, const string& literal,
237  std::function<void(AstNode_ptr&,bool&,const std::string::iterator&)> user_defined_body,
238  std::string rule_name=""){
239 #else
240  bool rule_proxy(const int rule_id, bool add_to_tree, bool do_memo, bool do_reduce, const string& literal,
241  std::function<void(AstNode_ptr&,bool&,const std::string::iterator&)> user_defined_body){
242 #endif
243  if(_pos_==end) return false;
244 
245  bool _ok_ = false;
246 
247  AstNode_ptr _this_rule_(new AstNode);
248 
249  AstNode_ptr saved_parent = current_parent;
250  current_parent = _this_rule_;
251 
252  DEBUG(_this_rule_->name = rule_name;)
253 
254  int n = std::distance(beg,_pos_);
255 
256  DEBUG(for(int i=0;i<level;++i) cout <<" ";)
257  DEBUG(cout << "Trying " << _this_rule_->name << " id: " << rule_id << " at: " << n << endl;)
258  DEBUG(num_tried++;)
259 
260  /* check memotable */
261  bool restored = false;
262  if(literal!="") do_memo = (literal.size()>3) ? true : false; /*cache only 'large' literals*/
263  if(do_memo && memo[rule_id].count(n)==1){
264  DEBUG(for(int i=0;i<level;++i) cout <<" ";)
265  DEBUG(cout << "-- from memo: " << _this_rule_->name << " at: " << n << endl;)
266  Memo_data& m = memo[rule_id][n];
267  _this_rule_ = m.tree;
268  _pos_ = m.pos;
269  _ok_ = m.ok;
270  restored = true;
271  DEBUG(num_restored++;)
272  }
273  DEBUG(level++;)
274  DEBUG(if(max_level<level) max_level = level;)
275 
276  /* variables for rule body */
277  std::string::iterator _old_ = _pos_;
278 
279  if(!restored){
280 
281  // For literals
282  if(literal!=""){
283  for(auto ch: literal){
284  if(*_pos_==ch){
285  _pos_++;
286  } else {
287  break;
288  }
289  }
290  if(_pos_-_old_== literal.size()) _ok_ = true;
291  if(!_ok_) _pos_ = _old_;
292  }
293 
294  // Call user-defined rule body
295  user_defined_body(_this_rule_,_ok_,_old_);
296  }
297 
298  if(_ok_){
299  if(_pos_>last_success) last_success = _pos_;
300  DEBUG(for(int i=0;i<level-1;++i) cout <<" ";)
301  DEBUG(cout<<"Matched "<< _this_rule_->name << " at: " << n << endl;)
302  if(add_to_tree) {
303  if(do_reduce && _this_rule_->children.size()==1){
304  saved_parent->children.push_back(_this_rule_->children[0]);
305  DEBUG(for(int i=0;i<level-1;++i) cout <<" ";)
306  DEBUG(cout << "-- simplifying node "<<_this_rule_->name << " to parent " << saved_parent->name << endl;)
307  } else {
308  saved_parent->children.push_back(_this_rule_);
309  DEBUG(for(int i=0;i<level-1;++i) cout <<" ";)
310  DEBUG(cout << "-- adding node "<<_this_rule_->name << " to parent " << saved_parent->name << endl;)
311  }
312  }
313  } else {
314  DEBUG(for(int i=0;i<level-1;++i) cout <<" ";)
315  DEBUG(cout<<"Failed "<< _this_rule_->name << " at: " << n << endl;)
316  _pos_ = _old_;
317  _this_rule_->children.clear();
318  DEBUG(num_failed++;)
319  }
320  current_parent = saved_parent;
321  /* Add to memotable */
322  if(do_memo && !restored) {
323  DEBUG(for(int i=0;i<level-1;++i) cout <<" ";)
324  DEBUG(cout << "-- to memo: " << _this_rule_->name << " at: " << n << endl;)
325  memo[rule_id][n] = Memo_data(_ok_,_this_rule_,_pos_);
326  DEBUG(num_stored++;)
327  }
328  DEBUG(level--;)
329  DEBUG(cout << endl;)
330  return _ok_;
331  }
332 
333  /*===================================*/
334  /* TERMINALS */
335  /*===================================*/
336 
337 
338  RULE(SPACE){
339  while(isspace(*_pos_)) _pos_++;
340  if(_old_!=_pos_) _ok_ = true;
341  }
342 
343 // Optional space
344 #define SP_() (SPACE(false,false)||true)
345 // Mandatory space
346 #define SP() (SPACE(false,false))
347 
348  RULE(UINT){
349  char* e;
350  int val = strtoul(&*_old_, &e, 0);
351  _pos_ += e-&*_old_;
352  if(_old_!=_pos_) _ok_ = true;
353  SP_(); // Consume any trailing space if present
354 
355  if(_ok_){
356  _this_rule_->code = TOK_UINT;
357  _this_rule_->children.push_back(val);
358  } // _ok_
359  }
360 
361  RULE(INT){
362  char* e;
363  int val = strtol(&*_old_, &e, 0);
364  _pos_ += e-&*_old_;
365  if(_old_!=_pos_) _ok_ = true;
366  SP_(); // Consume any trailing space if present
367 
368  if(_ok_){
369  _this_rule_->code = TOK_INT;
370  _this_rule_->children.push_back(val);
371  } // _ok_
372  }
373 
374  RULE(FLOAT){
375  char* e;
376  float val = strtod(&*_old_, &e);
377  _pos_ += e-&*_old_;
378  if(_old_!=_pos_) _ok_ = true;
379  SP_(); // Consume any training space if present
380 
381  if(_ok_){
382  _this_rule_->code = TOK_FLOAT;
383  _this_rule_->children.push_back(val);
384  } // _ok_
385  }
386 
387 
388  /*===================================*/
389  /* LITERALS */
390  /*===================================*/
391 
392  LITERAL_RULE(PLUS,"+"){
393  _this_rule_->code = TOK_PLUS;
394  }
395 
396  LITERAL_RULE(MINUS,"-"){
397  _this_rule_->code = TOK_MINUS;
398  }
399 
400  LITERAL_RULE(STAR,"*"){
401  _this_rule_->code = TOK_MULT;
402  }
403 
404  LITERAL_RULE(SLASH,"/"){
405  _this_rule_->code = TOK_DIV;
406  }
407 
408  LITERAL_RULE(CAP,"^"){
409  _this_rule_->code = TOK_POWER;
410  }
411 
412  LITERAL_RULE(DOUBLE_STAR,"**"){
413  _this_rule_->code = TOK_POWER;
414  }
415 
416  LITERAL_RULE(LPAREN,"("){}
417 
418  LITERAL_RULE(RPAREN,")"){}
419 
420  LITERAL_RULE(X,"x"){
421  _this_rule_->code = TOK_X;
422  }
423 
424  LITERAL_RULE(Y,"y"){
425  _this_rule_->code = TOK_Y;
426  }
427 
428  LITERAL_RULE(Z,"z"){
429  _this_rule_->code = TOK_Z;
430  }
431 
432  LITERAL_RULE(BETA,"beta"){
433  _this_rule_->code = TOK_BETA;
434  }
435 
436  LITERAL_RULE(OCCUPANCY,"occupancy"){
437  _this_rule_->code = TOK_OCC;
438  }
439 
440  LITERAL_RULE(DIST1,"distance"){}
441 
442  LITERAL_RULE(DIST2,"dist"){}
443 
444  LITERAL_RULE(POINT,"point"){}
445 
446  LITERAL_RULE(VECTOR,"vector"){}
447 
448  LITERAL_RULE(PLANE,"plane"){}
449 
450  LITERAL_RULE(OR,"or"){
451  _this_rule_->code = TOK_OR;
452  }
453 
454  LITERAL_RULE(AND,"and"){
455  _this_rule_->code = TOK_AND;
456  }
457 
458  LITERAL_RULE(ALL,"all"){
459  _this_rule_->code = TOK_ALL;
460  }
461 
462  LITERAL_RULE(EQ,"=="){
463  _this_rule_->code = TOK_EQ;
464  }
465 
466  LITERAL_RULE(NEQ,"!="){
467  _this_rule_->code = TOK_NEQ;
468  }
469 
470  LITERAL_RULE(GEQ,">="){
471  _this_rule_->code = TOK_GEQ;
472  }
473 
474  LITERAL_RULE(LEQ,"<="){
475  _this_rule_->code = TOK_LEQ;
476  }
477 
478  LITERAL_RULE(GT,">"){
479  _this_rule_->code = TOK_GT;
480  }
481 
482  LITERAL_RULE(LT,"<"){
483  _this_rule_->code = TOK_LT;
484  }
485 
486  LITERAL_RULE(NOT,"not"){}
487 
488  LITERAL_RULE(WITHIN_,"within"){}
489 
490  LITERAL_RULE(OF,"of"){}
491 
492  LITERAL_RULE(SELF_ON,"self"){
493  _this_rule_->code = TOK_SELF;
494  _this_rule_->children.push_back(1);
495  }
496 
497  LITERAL_RULE(SELF_OFF,"noself"){
498  _this_rule_->code = TOK_SELF;
499  _this_rule_->children.push_back(0);
500  }
501 
502  LITERAL_RULE(PBC_ON1,"pbc"){
503  _this_rule_->code = TOK_UINT;
504  _this_rule_->children.push_back(1);
505  }
506 
507  LITERAL_RULE(PBC_ON2,"periodic"){
508  _this_rule_->code = TOK_UINT;
509  _this_rule_->children.push_back(1);
510  }
511 
512  LITERAL_RULE(PBC_OFF1,"nopbc"){
513  _this_rule_->code = TOK_UINT;
514  _this_rule_->children.push_back(0);
515  }
516 
517  LITERAL_RULE(PBC_OFF2,"noperiodic"){
518  _this_rule_->code = TOK_UINT;
519  _this_rule_->children.push_back(0);
520  }
521 
522  LITERAL_RULE(BY,"by"){}
523 
524  LITERAL_RULE(TO,"to"){}
525 
526  LITERAL_RULE(RESIDUE,"residue"){}
527 
528  LITERAL_RULE(NAME,"name"){
529  _this_rule_->code = TOK_NAME;
530  }
531 
532  LITERAL_RULE(RESNAME,"resname"){
533  _this_rule_->code = TOK_RESNAME;
534  }
535 
536  LITERAL_RULE(TAG,"tag"){
537  _this_rule_->code = TOK_TAG;
538  }
539 
540  LITERAL_RULE(CHAIN,"chain"){
541  _this_rule_->code = TOK_CHAIN;
542  }
543 
544  LITERAL_RULE(RESID,"resid"){
545  _this_rule_->code = TOK_RESID;
546  }
547 
548  LITERAL_RULE(RESINDEX,"resindex"){
549  _this_rule_->code = TOK_RESINDEX;
550  }
551 
552  LITERAL_RULE(INDEX,"index"){
553  _this_rule_->code = TOK_INDEX;
554  }
555 
556  /*===================================*/
557  /* NON-TERMINALS */
558  /*===================================*/
559 
560 
561  RULE_REDUCE(NUM_EXPR){
562 
563  _ok_ = NUM_TERM() && ZeroOrMore( (PLUS() || MINUS()) && SP_() && NUM_TERM() );
564 
565  if(_ok_){
566  if(NUM_SUBRULES()>1){ // Some operations present
567  AstNode_ptr tmp = SUBRULE(0);
568  for(int i=1; i<NUM_SUBRULES()-1; i+=2){
569  tmp.swap( SUBRULE(i) ); // i is now left operand, tmp is operation
570  tmp->children.push_back(SUBRULE(i)); // lelf operand
571  tmp->children.push_back(SUBRULE(i+1)); // right operand
572  }
573  _this_rule_ = tmp;
574  }
575  } // _ok_
576  }
577 
578  RULE_REDUCE(NUM_TERM){
579 
580  _ok_ = NUM_POWER() && ZeroOrMore( (STAR() || SLASH()) && SP_() && NUM_POWER() );
581 
582  if(_ok_){
583  if(NUM_SUBRULES()>1){ // Some operations present
584  AstNode_ptr tmp = SUBRULE(0);
585  for(int i=1; i<NUM_SUBRULES()-1; i+=2){
586  tmp.swap( SUBRULE(i) ); // i is now left operand, tmp is operation
587  tmp->children.push_back(SUBRULE(i)); // lelf operand
588  tmp->children.push_back(SUBRULE(i+1)); // right operand
589  }
590  _this_rule_ = tmp;
591  }
592  } // _ok_
593  }
594 
595 
596  RULE_REDUCE(NUM_POWER){
597 
598  _ok_ = NUM_FACTOR() && Opt( (CAP(false) || DOUBLE_STAR(false)) && SP_()&& NUM_FACTOR() );
599 
600  if(_ok_){
601  if(NUM_SUBRULES()>1){
602  _this_rule_->code = TOK_POWER; // Set operation, no other actions needed
603  }
604  } // _ok_
605  }
606 
607  RULE_REDUCE(NUM_FACTOR){
608  _ok_ = Comb( LPAREN(false) && SP_() && NUM_EXPR() && RPAREN(false) && SP_() )
609  || FLOAT()
610  || Comb( X() && SP_() )
611  || Comb( Y() && SP_() )
612  || Comb( Z() && SP_() )
613  || Comb( BETA() && SP_() )
614  || Comb( OCCUPANCY() && SP_() )
615  || Comb( RESINDEX() && SP_() )
616  || Comb( INDEX() && SP_() )
617  || Comb( RESID() && SP_() )
618  || UNARY_MINUS()
619  || DIST_POINT()
620  || DIST_VECTOR()
621  || DIST_PLANE()
622  ;
623  }
624 
625  RULE(UNARY_MINUS){
626  _ok_ = MINUS(false) && NUM_FACTOR();
627 
628  if(_ok_){
629  _this_rule_->code = TOK_UNARY_MINUS;
630  } // _ok_
631  }
632 
633  RULE(DIST_POINT){
634  _ok_ = (DIST1(false) || DIST2(false)) && SP()
635  && POINT(false) && SP()
636  && Opt(PBC())
637  && FLOAT() && FLOAT() && FLOAT();
638 
639  if(_ok_){
640  _this_rule_->code = TOK_POINT;
641  if(NUM_SUBRULES()==3){ // No pbc given
642  _this_rule_->children.push_back(0); // add default pbc at the end
643  } else {
644  // Put pbc to the end
645  std::rotate(_this_rule_->children.begin(),
646  _this_rule_->children.begin()+1,
647  _this_rule_->children.end());
648  // Reduce pbc node to number 0 or 1
649  _this_rule_->children[3] = _this_rule_->child_as_int(3);
650  }
651  // Reduce 3 first nodes to floats
652  for(int i=0;i<3;++i) _this_rule_->children[i] = _this_rule_->child_as_float(i);
653  } // _ok_
654  }
655 
656  RULE(DIST_VECTOR){
657  _ok_ = (DIST1(false) || DIST2(false)) && SP()
658  && VECTOR(false) && SP()
659  && Opt(PBC())
660  && FLOAT() && FLOAT() && FLOAT() && FLOAT() && FLOAT() && FLOAT();
661 
662  if(_ok_){
663  _this_rule_->code = TOK_VECTOR;
664  if(NUM_SUBRULES()==6){ // No pbc given
665  _this_rule_->children.push_back(0); // add default pbc at the end
666  } else {
667  // Put pbc to the end
668  std::rotate(_this_rule_->children.begin(),
669  _this_rule_->children.begin()+1,
670  _this_rule_->children.end());
671  // Reduce pbc node to number 0 or 1
672  _this_rule_->children[6] = _this_rule_->child_as_int(6);
673  }
674  // Reduce 6 first nodes to floats
675  for(int i=0;i<6;++i) _this_rule_->children[i] = _this_rule_->child_as_float(i);
676  } // _ok_
677  }
678 
679  RULE(DIST_PLANE){
680  _ok_ = (DIST1(false) || DIST2(false)) && SP()
681  && PLANE(false) && SP()
682  && Opt(PBC())
683  && FLOAT() && FLOAT() && FLOAT() && FLOAT() && FLOAT() && FLOAT();
684 
685  if(_ok_){
686  _this_rule_->code = TOK_PLANE;
687  if(NUM_SUBRULES()==6){ // No pbc given
688  _this_rule_->children.push_back(0); // add default pbc at the end
689  } else {
690  // Put pbc to the end
691  std::rotate(_this_rule_->children.begin(),
692  _this_rule_->children.begin()+1,
693  _this_rule_->children.end());
694  // Reduce pbc node to number 0 or 1
695  _this_rule_->children[6] = _this_rule_->child_as_int(6);
696  }
697  // Reduce 6 first nodes to floats
698  for(int i=0;i<6;++i) _this_rule_->children[i] = _this_rule_->child_as_float(i);
699  } // _ok_
700  }
701 
702  RULE_REDUCE(LOGICAL_EXPR){
703 
704  _ok_ = LOGICAL_OPERAND() && ZeroOrMore( (OR() || AND()) && SP_() && LOGICAL_OPERAND() );
705 
706  if(_ok_){
707  if(NUM_SUBRULES()>1){ // Some operations present
708  AstNode_ptr tmp = SUBRULE(0);
709  for(int i=1; i<NUM_SUBRULES()-1; i+=2){
710  tmp.swap( SUBRULE(i) ); // i is now left operand, tmp is operation
711  tmp->children.push_back(SUBRULE(i)); // lelf operand
712  tmp->children.push_back(SUBRULE(i+1)); // right operand
713  }
714  _this_rule_ = tmp;
715  }
716  } // _ok_
717  }
718 
719  RULE_REDUCE(LOGICAL_OPERAND){
720  _ok_ = Comb( LPAREN(false) && SP_() && LOGICAL_EXPR() && RPAREN(false) && SP_() )
721  ||
722  Comb( !Check(NUM_EXPR(false) && !COMPARISON_OPERATOR(false)) && NUM_COMPARISON() )
723  ||
724  Comb( ALL() && SP_() )
725  ||
726  LOGICAL_NOT()
727  ||
728  WITHIN()
729  ||
730  BY_RESIDUE()
731  ||
732  KEYWORD_LIST_STR()
733  ||
734  KEYWORD_INT_STR()
735  ||
736  RESID_RULE()
737  ;
738  }
739 
740  RULE_REDUCE(COMPARISON_OPERATOR){
741  _ok_ = (EQ() || NEQ() || LEQ() || GEQ() || LT() || GT()) && SP_();
742  }
743 
744 
745  RULE_REDUCE(NUM_COMPARISON){
746 
747  _ok_ = NUM_EXPR();
748 
749  Comb( COMPARISON_OPERATOR() && NUM_EXPR() && COMPARISON_OPERATOR() && NUM_EXPR()) //chained
750  ||
751  Comb( COMPARISON_OPERATOR() && NUM_EXPR() ); // normal
752 
753 
754  if(_ok_){
755  // single NUM_EXPR will pass through and will be reduced. No action needed.
756  if(NUM_SUBRULES()==3){ // normal comparison
757  SUBRULE(1)->children.push_back(SUBRULE(0));
758  SUBRULE(1)->children.push_back(SUBRULE(2));
759  _this_rule_ = SUBRULE(1);
760  } else { // chained comparison
761  AstNode_ptr op1 = SUBRULE(1);
762  op1->children.push_back(SUBRULE(0));
763  op1->children.push_back(SUBRULE(2));
764  AstNode_ptr op2 = SUBRULE(3);
765  op2->children.push_back(SUBRULE(2));
766  op2->children.push_back(SUBRULE(4));
767  _this_rule_->code = TOK_AND;
768  _this_rule_->children.clear();
769  _this_rule_->children.push_back(op1);
770  _this_rule_->children.push_back(op2);
771  }
772  } // _ok_;
773  }
774 
775  RULE(LOGICAL_NOT){
776  _ok_ = NOT(false) && SP_() && LOGICAL_OPERAND();
777 
778  if(_ok_){
779  _this_rule_->code = TOK_NOT;
780  } // _ok_
781  }
782 
783  RULE(WITHIN){
784  _ok_ = WITHIN_(false) && SP_() && FLOAT() && SP_()
785  && Opt(Comb(PBC() && SELF()) || Comb(SELF() && PBC()) || PBC() || SELF())
786  && OF(false)
787  && (SP()||Check(LPAREN(false))) && LOGICAL_OPERAND();
788 
789  if(_ok_){
790  _this_rule_->code = TOK_WITHIN;
791  if(NUM_SUBRULES()==2){ // no pbc, no self given only (d,operand)
792  _this_rule_->children.push_back(0); // add nopbc at the end
793  _this_rule_->children.push_back(1); // add self at the end
794  } else if(NUM_SUBRULES()==3) { // (d,pbc,operand) or (d,self,operand)
795  if(SUBRULE(1)->code == TOK_SELF){
796  // We have (d,self,op)
797  SUBRULE(1).swap( SUBRULE(2) ); // now: (d,op,self)
798  // insert nopbc before self
799  _this_rule_->children.insert(_this_rule_->children.begin()+2, 0);
800  // And reduce self to int
801  _this_rule_->children[3] = _this_rule_->child_as_int(3);
802  } else {
803  // We have (d,pbc,op)
804  SUBRULE(1).swap( SUBRULE(2) ); // now: (d,op,pbc)
805  // Reduce pbc node to number 0 or 1
806  _this_rule_->children[2] = _this_rule_->child_as_int(2);
807  // Add default self
808  _this_rule_->children.push_back(1);
809  }
810 
811  } else {
812  // We have (d,self,pbc,op) OR (d,pbc,self,op)
813  if(SUBRULE(1)->code == TOK_SELF){
814  // We have (d,self,pbc,op)
815  SUBRULE(1).swap( SUBRULE(3) ); // now: (d,op,pbc,self)
816  } else {
817  // We have (d,pbc,self,op)
818  SUBRULE(1).swap( SUBRULE(3) ); // now: (d,op,self,pbc)
819  SUBRULE(2).swap( SUBRULE(3) ); // now: (d,op,pbc,pbc)
820  }
821  // Reduce both pbc and self
822  _this_rule_->children[2] = _this_rule_->child_as_int(2);
823  _this_rule_->children[3] = _this_rule_->child_as_int(3);
824  }
825 
826  // Reduce dist node to float
827  _this_rule_->children[0] = _this_rule_->child_as_float(0);
828  } // _ok_
829  }
830 
831  RULE_REDUCE(PBC){
832  _ok_ = (PBC_ON1() || PBC_ON2() || PBC_OFF1() || PBC_OFF2()) && SP_();
833  }
834 
835  RULE_REDUCE(SELF){
836  _ok_ = (SELF_ON() || SELF_OFF()) && SP_();
837  }
838 
839  RULE(BY_RESIDUE){
840  _ok_ = BY(false) && SP() && RESIDUE(false) && SP_() && LOGICAL_OPERAND();
841 
842  if(_ok_){
843  _this_rule_->code = TOK_BY;
844  } // _ok_
845  }
846 
847  RULE(KEYWORD_LIST_STR){
848  _ok_ = STR_KEYWORD() && SP() && OneOrMore( STR()||REGEX() );
849 
850  if(_ok_){
851  for(int i=1; i<NUM_SUBRULES(); ++i){
852  SUBRULE(0)->children.push_back(SUBRULE(i));
853  }
854  _this_rule_ = SUBRULE(0);
855  } // _ok_
856  }
857 
858  RULE(KEYWORD_INT_STR){
859  _ok_ = INT_KEYWORD() && SP() && OneOrMore( RANGE()||UINT() && SP_() );
860 
861  if(_ok_){
862  for(int i=1; i<NUM_SUBRULES(); ++i){
863  SUBRULE(0)->children.push_back(SUBRULE(i));
864  }
865  _this_rule_ = SUBRULE(0);
866  } // _ok_
867  }
868 
869  // resid could be negative in some funny structures, so INT, not UINT
870  RULE(RESID_RULE){
871  _ok_ = RESID() && SP() && OneOrMore( RANGE_SIGNED()||INT() && SP_() );
872 
873  if(_ok_){
874  for(int i=1; i<NUM_SUBRULES(); ++i){
875  SUBRULE(0)->children.push_back(SUBRULE(i));
876  }
877  _this_rule_ = SUBRULE(0);
878  } // _ok_
879  }
880 
881  RULE_REDUCE(STR_KEYWORD){
882  _ok_ = NAME() || RESNAME() || TAG() || CHAIN();
883  }
884 
885  RULE_REDUCE(INT_KEYWORD){
886  _ok_ = RESINDEX() || INDEX();
887  }
888 
889  RULE(STR){
890  _ok_ = !Check( OR(false) || AND(false) );
891  if(_ok_){
892  while(isalnum(*_pos_) && _pos_!=end){
893  _pos_++;
894  }
895  }
896 
897  string s;
898 
899  if(_pos_!=_old_){
900  if(_ok_) s = string(_old_,_pos_);
901  _ok_ = SP() || Check(RPAREN(false)) || Check(MINUS(false)) || (_pos_==end);
902  } else {
903  _ok_ = false;
904  }
905 
906  if(_ok_){
907  _this_rule_->code = TOK_STR;
908  _this_rule_->children.push_back(s);
909  } // _ok_
910  }
911 
912  RULE(REGEX){
913  _ok_ = (*_pos_=='\'');
914  if(_ok_){
915  _pos_++;
916  while(*_pos_!='\'' && _pos_!=end) _pos_++;
917  if(_pos_!=_old_){
918  _ok_ = (*_pos_=='\'');
919  if(_ok_) _pos_++;
920  }
921  } else {
922  _ok_ = (*_pos_=='"');
923  if(_ok_){
924  _pos_++;
925  while(*_pos_!='"' && _pos_!=end) _pos_++;
926  if(_pos_!=_old_){
927  _ok_ = (*_pos_=='"');
928  if(_ok_) _pos_++;
929  }
930  }
931  }
932 
933  string::iterator b = _old_+1;
934  string::iterator e = _pos_-1;
935 
936  SP_(); // Consume any trailing space if present
937 
938  if(_ok_){
939  _this_rule_->code = TOK_REGEX;
940  _this_rule_->children.push_back(string(b,e));
941  } // _ok_
942  }
943 
944  RULE(RANGE){
945  _ok_ = UINT() && SP_() && (TO(false)||MINUS(false)) && SP_() && UINT();
946  if(_ok_){
947  _this_rule_->code = TOK_TO;
948  } // _ok_
949  }
950 
951  RULE(RANGE_SIGNED){
952  _ok_ = INT() && SP_() && (TO(false)||MINUS(false)) && SP_() && INT();
953  if(_ok_){
954  _this_rule_->code = TOK_TO;
955  } // _ok_
956  }
957 
958 
959  RULE_REDUCE(START){
960  _ok_ = SP_() && LOGICAL_EXPR();
961  }
962 
963  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
964  AstNode_ptr run(){
965  current_parent.reset(new AstNode); // Hierarchy root
966 
967  START(true,false);
968 
969 #ifdef _DEBUG_PARSER
970  cout << "Statistics:" << endl;
971  cout << "Number of used rules: " << memo.size() << endl;
972  cout << "Recursion depth: " << max_level << endl;
973  cout << "Size of memotable: " << memo.size() << endl;
974  cout << "Rules stored to memotable: " << num_stored << endl;
975  cout << "Rules restored from memotable: " << num_restored << endl;
976  cout << "Rules tried: " << num_tried << endl;
977  cout << "Rules succeded: " << num_tried-num_failed << endl;
978  cout << "Rules failed: " << num_failed << endl;
979 #endif
980 
981  if(current_parent->children.size()>0 && _pos_== end)
982  return current_parent->child_node(0);
983  else {
984  int n = std::distance(beg,last_success);
985  stringstream ss;
986  ss << "Syntax error in selection! Somewhere after position " << n << ":" << endl;
987  ss << string(beg,end) << endl;
988  for(int i=0;i<n-1;i++) ss<< "-";
989  ss << "^" << endl;
990 
991  throw Pteros_error(ss.str());
992  }
993  }
994 
995 };
996 
997 
998 //===========================================================
999 
1000 #endif /* SELECTION_GRAMMAR_H */
1001 
Pteros namespace.
Definition: options.cpp:32
STL namespace.
Represents an error in the Pteros code. Used for all Pteros-related exceptions.
Definition: pteros_error.h:33