NCBI C++ ToolKit
macro_parse.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: macro_parse.cpp 45964 2021-01-20 16:32:20Z grichenk $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Anatoly Osipov
27  *
28  * File Description: Macro parser
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
37 #include <functional>
38 #include <math.h>
39 
40 /** @addtogroup GUI_MACRO_SCRIPTS_UTIL
41  *
42  * @{
43  */
44 
46 BEGIN_SCOPE(macro)
47 
48 /////////////////////////////////////////////////////////////////////////////
49 //
50 // CScanner
51 //
52 
53 void CScanner::x_InitScanner()
54 {
55  m_CurrentLexem.m_Token = eTokenILLEGAL;
56  m_CurrentLexem.m_Position = SLocation(0, 1, 1);
57  m_CurrentLexem.m_Data.Init();
58 }
59 
61 {
62  return m_CurrentLexem.m_Token;
63 }
64 
66 {
68 
69  char ch = m_StrMacro[pos];
71 
72  int i;
73  for (i=0; (m_StrMacro[pos] != '\0') &&
74  (m_StrMacro[pos] != ch) &&
75  (i < MAX_STRING_LEXEM_LENGTH); i++) {
76 
77  switch (m_StrMacro[pos]) {
78  case '\n':
80  break;
81  case '\\':
82  if (m_StrMacro[pos+1] == ch)
84  break;
85  default:
86  ; // intentionally no operators here
87  }
88 
91  }
92 
93  m_CurrentLexem.m_Data.m_Str[i] = '\0';
94 
95  if (i >= MAX_STRING_LEXEM_LENGTH) {
96  m_CurrentLexem.m_ErrorMsg.assign("String is too long");
98  }
99 
100  if (m_StrMacro[pos] == '\0') {
101  m_CurrentLexem.m_ErrorMsg.assign("String is not closed");
103  }
104 
105  m_CurrentLexem.m_Position.IncColumn(); // this eats " symbol
106  return m_CurrentLexem.m_Token = (ch == '"') ? eTokenSTRING : eTokenASK;
107 }
108 
110 {
111  m_CurrentLexem.m_ErrorMsg.clear();
113 
115  if (m_StrMacro) {
116  // Skip Delimeters
117  while ((m_StrMacro[pos] == ' ') ||
118  (m_StrMacro[pos] == '\t') ||
119  (m_StrMacro[pos] == '\n')) {
120 
121  if (m_StrMacro[pos] != '\n')
123  else
125  }
128  }
129 }
130 
132 {
134 
135  // It's to decide should we report a problem if:
136  // 1) ** or .. is encountered
137  // 2) dot is the first or last symbol in selector
138 
139  if (!m_StrMacro)
141 
143  if (isalpha(m_StrMacro[pos]) || (m_StrMacro[pos]=='*')) {
144  int i;
145  for ( i = 0; ( isdigit(m_StrMacro[pos]) ||
146  isalpha(m_StrMacro[pos]) ||
147  (m_StrMacro[pos] == '_') ||
148  (m_StrMacro[pos] == '-') ||
149  (m_StrMacro[pos] =='*') ||
150  (m_StrMacro[pos] =='.')
151  ) && (i < MAX_STRING_LEXEM_LENGTH); i++) {
152 
155  }
156  m_CurrentLexem.m_Data.m_Str[i] = '\0';
157 
158  if (i >= MAX_STRING_LEXEM_LENGTH) {
159  m_CurrentLexem.m_ErrorMsg.assign("String is too long");
161  }
162  else {
166  }
167  }
169  }
170  else {
171  m_CurrentLexem.m_ErrorMsg.assign("ASN.1 selector expected");
173  }
174 }
175 
177 {
179 
180  if (!m_StrMacro)
182 
184  if (m_StrMacro[pos] == 'N' && m_StrMacro[pos + 1] == 'A') {
185  size_t i = 0;
186  for (i; ( isdigit(m_StrMacro[pos]) ||
187  isalpha(m_StrMacro[pos]) ||
188  (m_StrMacro[pos] == '.') ||
189  (m_StrMacro[pos] == '#')
190  ) && (i < MAX_STRING_LEXEM_LENGTH); i++) {
193  }
194  m_CurrentLexem.m_Data.m_Str[i] = '\0';
195 
196  if (i >= MAX_STRING_LEXEM_LENGTH) {
197  m_CurrentLexem.m_ErrorMsg.assign("String is too long");
199  }
200  else {
204  }
205  }
207  }
208 
209  m_CurrentLexem.m_ErrorMsg.assign("Named annotation (NA number) expected");
211 }
212 
214 {
215  char ch = tolower(m_StrMacro[pos]);
216  strncat(m_CurrentLexem.m_Data.m_Str, &ch, 1);
218  m_CurrentLexem.m_Token = token;
219  return m_CurrentLexem.m_Token;
220 }
221 
222 int CScanner::Next(bool parseComment)
223 {
225 
226  if (!m_StrMacro)
228 
230  switch (tolower(m_StrMacro[pos])) {
231  case '\0':
232  // We reached the end of string.
233  // Do not increment position.
235  case '=':
236  return x_SetCurrentLexem(pos, eTokenASSIGNMENT);
237  case '(':
238  return x_SetCurrentLexem(pos, eTokenLEFTPAREN);
239  case ')':
240  return x_SetCurrentLexem(pos, eTokenRIGHTPAREN);
241  case '{':
242  return x_SetCurrentLexem(pos, eTokenLEFTBRACE);
243  case '}':
244  return x_SetCurrentLexem(pos, eTokenRIGHTBRACE);
245  case '[':
247  case ']':
249  case ',':
250  return x_SetCurrentLexem(pos, eTokenCOMMA);
251  case ';':
252  return x_SetCurrentLexem(pos, eTokenSEMICOLON);
253 
254  case '-': // unary - in front of a number or start of a comment
256  if (m_StrMacro[pos] != '-')
258 
260 
261  if (parseComment) {
262  int i = 0;
263  for (; i < MAX_STRING_LEXEM_LENGTH; i++) {
264  if (m_StrMacro[pos] == '\0' || m_StrMacro[pos] == '\n')
265  break;
266 
269  }
270  m_CurrentLexem.m_Data.m_Str[i] = '\0';
271 
272  while ((m_StrMacro[pos] != '\0') && (m_StrMacro[pos] != '\n'))
274 
276  }
277 
278  // it is a comment, skip it till the end of line.
279  while ((m_StrMacro[pos] != '\0') && (m_StrMacro[pos] != '\n'))
281  return Next();
282 
283  case '+': // unary + in front of a number
284  return x_SetCurrentLexem(pos, eTokenPLUS);
285  case '.': // FOR WHERE CLAUSE
286  return x_SetCurrentLexem(pos, eTokenDOT);
287  case '*': // FOR WHERE CLAUSE
288  return x_SetCurrentLexem(pos, eTokenMULT);
289  case '/': // FOR WHERE CLAUSE
290  return x_SetCurrentLexem(pos, eTokenDIV);
291 
292  case '>': // FOR WHERE CLAUSE
294  if (m_StrMacro[pos] != '=')
296 
299 
300  case '<': // FOR WHERE CLAUSE
302  if ((m_StrMacro[pos] != '>') && (m_StrMacro[pos] != '='))
304 
306  if (m_StrMacro[pos] == '=')
309 
310  case '0': // can numbers start with 0?
311  case '1':case '2':case '3':
312  case '4':case '5':case '6':
313  case '7':case '8':case '9':
314  {
315  Int4 num = m_StrMacro[pos] - '0';
317 
318  while (isdigit(m_StrMacro[pos])) {
319  num = num * 10 + (m_StrMacro[pos] - '0');
321  }
322 
323  if (m_StrMacro[pos] == '.') {
325  double fl_num = (double)num;
326  short index = -1;
327  while (isdigit(m_StrMacro[pos])) {
328  fl_num += (m_StrMacro[pos] - '0')*pow(10.0, index);
329  index--;
331  }
334  }
335  else {
338  }
339  }
340  case '"':
341  case '%':
342  return x_GetQuotedString();
343  default:
344  if (isalpha(m_StrMacro[pos])) {
345  int i;
346  // * and . are included for asn selectors
347  for ( i = 0; ( isdigit(m_StrMacro[pos]) ||
348  isalpha(m_StrMacro[pos]) ||
349  // .
350  // -
351  (m_StrMacro[pos] == '_')
352  ) && (i < MAX_STRING_LEXEM_LENGTH); i++) {
353 
356  }
357  m_CurrentLexem.m_Data.m_Str[i] = '\0';
358 
359  if (i >= MAX_STRING_LEXEM_LENGTH) {
360  m_CurrentLexem.m_ErrorMsg.assign("Identifier is too long");
362  }
363 
365  // Look up keyword names
366  if (NStr::EqualNocase(keyword, "macro")) {
368  } else if (NStr::EqualNocase(keyword, "var")) {
370  } else if (NStr::EqualNocase(keyword, "vars")) {
372  } else if (NStr::EqualNocase(keyword, "for")) {
374  } else if (NStr::EqualNocase(keyword, "each")) {
376  } else if (NStr::EqualNocase(keyword, "from")) {
378  } else if (NStr::EqualNocase(keyword, "choice")) {
380  } else if (NStr::EqualNocase(keyword, "range")) {
382  } else if (NStr::EqualNocase(keyword, "where")) {
384  } else if (NStr::EqualNocase(keyword, "do")) {
386  } else if (NStr::EqualNocase(keyword, "done")) {
388  } else if (NStr::EqualNocase(keyword, "do_p")) {
390  } else if (NStr::EqualNocase(keyword, "auto")) {
392  } else if (NStr::EqualNocase(keyword, "true")) {
395  } else if (NStr::EqualNocase(keyword, "false")) {
398  } else {
399  /* TEMPORARY DISABLE THIS
400  // Search for built-in function names
401  for (i = 0; m_FuncNames[i] != NULL; i++) {
402  if (!NStr::CompareNocase(m_CurrentLexem.m_Data.m_Str, m_FuncNames[i]))
403  break;
404  }
405  if (m_FuncNames[i] != NULL)
406  return m_CurrentLexem.m_Token = eTokenFUNCTION;
407  */
409  }
410  }
411  else {
412  m_CurrentLexem.m_ErrorMsg.assign("Symbol is not allowed");
415  }
416  }
417 }
418 
419 
420 
421 
422 /////////////////////////////////////////////////////////////////////////////
423 //
424 // CMacroParser
425 //
426 
427 const char* CMacroParser::sm_Automatic = "automatic";
428 
429 bool CMacroParser::Parse(bool bSingleMacroMode, CQueryExec* exec)
430 {
431  m_RTVars.clear();
432 
433  if (m_MacroRep) {
434  delete m_MacroRep;
435  }
436  m_MacroRep = new CMacroRep(exec);
437 
439  delete m_MacroRep;
440  m_MacroRep = 0;
441  return false;
442  }
443 
444  Int4 pos_start = m_Scanner.GetLexemInfo().m_Start.m_Pos;
445 
446  x_ParseScript();
447 
449  m_MacroRep->SetSource( string (m_StrMacro + pos_start, pos_end - pos_start) );
450 
451  if (bSingleMacroMode) {
453  string msg = x_GetError();
454  msg += "Unexpected token: '" + m_Scanner.GetLexemInfo().GetStringRepr() + "'";
455  NCBI_THROW(CMacroParseException, eParseNothingExpected, msg);
456  }
457  }
458  return true;
459 }
460 
462 {
464 
465  string msg = "[Parsing error] ";
467  msg += "Line ";
469  msg += ", Pos ";
471  msg += ": ";
472  }
473  else {
474  msg += "Pos ";
476  msg += ": ";
477  }
478 
479  return msg;
480 }
481 
482 
484 {
485  if (m_ErrorLocation.m_Pos == -1) {
487  }
488 }
489 
491 {
493  return x_GetErrorLocation();
494 }
495 
496 // Inits parser to its initial state
498 {
501 }
502 
504 {
505  // Macro heading section
507  string msg = x_GetError();
508  msg += "Keyword 'MACRO' expected instead of '";
509  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
510  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
511  }
512 
513  m_Scanner.Next();
515  string msg = x_GetError();
516  msg += "Macro name expected";
517  NCBI_THROW(CMacroParseException, eParseMacroNameExpected, msg);
518  }
519  else {
521  }
522 
523  m_Scanner.Next(true);
524  // description of the macro is optional
527  m_Scanner.Next(true);
528  }
529 
531  x_ParseMetaData();
532  m_Scanner.Next(true);
533  }
534 
535  //LOG_POST(Error << m_MacroRep->GetMetaKeywords());
536 
537  // Vars section(s) is optional
539  m_Scanner.Next();
541  }
542 
543 /*
544  // to identify which macro had a parsing error
545  LOG_POST("Parsing: " << m_MacroRep->GetName());
546 */
547  // Macro body section
548  x_ParseBody();
549 };
550 
552 {
554 
556  string msg = x_GetError();
557  msg += "Identifier name expected";
558  NCBI_THROW(CMacroParseException, eParseIdentifierNameExpected, msg);
559  }
560 
561  do {
562  // Store Variable Name
563  string var_name = m_Scanner.GetLexemInfo().m_Data.m_Str;
564  if (m_MacroRep->FindVar(var_name)) {
565  string msg = x_GetError();
566  msg += "Variable '" + m_Scanner.GetLexemInfo().GetStringRepr();
567  msg += "' is already defined";
568  NCBI_THROW(CMacroParseException, eParseVariableDefined, msg);
569  }
570 
571  m_Scanner.Next();
573  string msg = x_GetError();
574  msg += "Assignment expected";
575  NCBI_THROW(CMacroParseException, eParseAssignmentExpected, msg);
576  }
577 
578  m_Scanner.Next();
579  switch (m_Scanner.GetToken()) {
581  // Store variable's value as a string
583  m_Scanner.Next();
584  break;
585  case CScanner::eTokenASK:
586  // Store ASK's value as a string
588  m_Scanner.Next();
589  break;
591  // Store variables's name
592  m_MacroRep->SetVarChoiceName(var_name);
593  m_Scanner.Next();
594  x_ParseChoice();
595  break;
597  // Store bool const value
599  m_Scanner.Next();
600  break;
601  default:
602  {
603  x_ParseNumericVarValue(var_name, x_ParseSign());
604  }
605  }
606  }
608 }
609 
611 {
612  int sign = 1;
614  sign = -1;
615  }
618 
619  m_Scanner.Next();
620  }
621  return sign;
622 }
623 
624 void CMacroParser::x_ParseNumericVarValue(const string& var_name, int sign)
625 {
626  switch (m_Scanner.GetToken()) {
628  {
630  m_MacroRep->SetVarInt(var_name, value);
631  break;
632  }
634  {
635  double value = sign * m_Scanner.GetLexemInfo().m_Data.m_FloatNumber;
636  m_MacroRep->SetVarFloat(var_name, value);
637  break;
638  }
639  default: {
640  string msg = x_GetError();
641  msg += "Definition of '" + var_name + "' variable is incomplete";
642  NCBI_THROW(CMacroParseException, eParseVarDefinitionExpected, msg);
643  }
644  }
645 
646  m_Scanner.Next();
647 }
648 
650 {
652  string msg = x_GetError();
653  msg += "Symbol '{' expected instead of '";
654  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
655  NCBI_THROW(CMacroParseException, eParseLeftBraceExpected, msg);
656  }
657 
658  do {
659  // Parse var value
660  m_Scanner.Next();
661 
662  switch (m_Scanner.GetToken()) {
664  // Store choice variable's value as a string
666  m_Scanner.Next();
667  break;
670  m_Scanner.Next();
671  break;
672  default:
673  {
675  }
676  }
677  }
679 
681  string msg = x_GetError();
682  msg += "Comma or '}' expected instead of '";
683  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
684  NCBI_THROW(CMacroParseException, eParseCommaOrRightBraceExpected, msg);
685  }
686 
687  m_Scanner.Next();
688 }
689 
691 {
692  switch (m_Scanner.GetToken()) {
694  {
697  break;
698  }
700  {
701  double value = sign * m_Scanner.GetLexemInfo().m_Data.m_FloatNumber;
703  break;
704  }
705  default: {
706  string msg = x_GetError();
707  msg += "Variable definition expected";
708  NCBI_THROW(CMacroParseException, eParseVarDefinitionExpected, msg);
709  }
710  }
711 
712  m_Scanner.Next();
713 }
714 
716 {
718  m_Scanner.Next();
720  string msg = x_GetError();
721  msg += "Keyword 'FOR EACH' expected instead of '";
722  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
723  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
724  }
725 
728  string msg = x_GetError();
729  msg += "ASN.1 selector expected instead of '";
730  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
731  NCBI_THROW(CMacroParseException, eParseAsnSelectorExpected, msg);
732  }
733 
734  // Store ASN selector
736  m_Scanner.Next();
737  }
738 
739  // Code below commented out, because only one ASN selector is allowed
740  //
741  // while ( m_Scanner.GetToken() == CScanner::eTokenCOMMA ) {
742  // m_Scanner.NextASNSelector();
743  // if ( m_Scanner.GetToken() != CScanner::eTokenASNSELECTOR )
744  // NCBI_THROW(CMacroParseException, EErCode_ASN_SELECTOR_EXPECTED, "Macro Exception");
745  //
746  // m_Scanner.Next();
747  // }
748 
752  string msg = x_GetError();
753  msg += "Named annotation expected instead of '";
754  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
755  NCBI_THROW(CMacroParseException, eParseNamedAnnotExpected, msg);
756  }
757 
759  m_Scanner.Next();
760  }
761 
763  x_ParseRange();
764  }
765 
767  x_ParseWhere();
768 
769  x_ParseDo();
770 }
771 
773 {
775  string msg = x_GetError();
776  msg += "Keyword 'RANGE' expected instead of '";
777  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
778  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
779  }
780 
781  m_Scanner.Next();
782  auto token = m_Scanner.GetToken();
783  if ((token == CScanner::eTokenKWWHERE) ||
784  (token == CScanner::eTokenKWDO) ||
785  (token == CScanner::eTokenKWDOPARL) ||
786  (token == CScanner::eTokenILLEGAL) ||
787  (token == CScanner::eTokenEOS)) {
788  string msg = x_GetError();
789  msg += "Sequence range expected instead of '";
790  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
791  NCBI_THROW(CMacroParseException, eParseWhereClauseExpected, msg);
792  }
793 
795  string msg = x_GetError();
796  msg += "Symbol '[' expected instead of '";
797  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
798  NCBI_THROW(CMacroParseException, eParseLeftBracketExpected, msg);
799  }
800 
801  Int8 start = 0, stop = 0;
802  bool found_start = false, found_stop = false, found_comma = false;
803  int sign = 1;
804 
805  m_Scanner.Next();
806  token = m_Scanner.GetToken();
807  while ((token != CScanner::eTokenRIGHTBRACKET) &&
808  (token != CScanner::eTokenKWDO) &&
809  (token != CScanner::eTokenKWWHERE) &&
810  (token != CScanner::eTokenILLEGAL) &&
811  (token != CScanner::eTokenEOS)) {
812 
813  switch (token) {
815  if (!found_start && !found_comma) {
816  found_start = true;
817  start = sign * m_Scanner.GetLexemInfo().m_Data.m_IntNumber;
818  }
819  else if (found_comma && !found_stop) {
820  found_stop = true;
821  stop = sign * m_Scanner.GetLexemInfo().m_Data.m_IntNumber;
822  }
823  break;
825  found_comma = true;
826  break;
830  {
831  string msg = x_GetError();
832  msg += "Positive integer number expected instead of '";
833  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
834  NCBI_THROW(CMacroParseException, eParseIntegerExpected, msg);
835  break;
836  }
838  case CScanner::eTokenDOT:
839  {
840  string msg = x_GetError();
841  msg += "Comma expected to separate two positive integers instead of '";
842  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
843  NCBI_THROW(CMacroParseException, eParseCommaExpected, msg);
844  break;
845  }
848  {
849  string msg = x_GetError();
850  msg += "Symbol ']' expected instead of '";
851  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
852  NCBI_THROW(CMacroParseException, eParseRightBracketExpected, msg);
853  break;
854  }
855  default:
856  break;
857  }
858  m_Scanner.Next();
859  sign = x_ParseSign();
860  token = m_Scanner.GetToken();
861  }
862 
863  if (token != CScanner::eTokenRIGHTBRACKET || !found_start || !found_stop) {
864  string msg = "Range was not specified as expected: '[start, stop]'";
865  NCBI_THROW(CMacroParseException, eParseRangeInvalid, msg);
866  }
867 
868  if (start < 0 || stop < 0) {
869  string msg = "Start and Stop positions are expected to be positive integers";
870  NCBI_THROW(CMacroParseException, eParseRangeInvalid, msg);
871  }
872 
873  if (start > stop) {
874  string msg = "Start position should be less than or equal to the Stop position";
875  NCBI_THROW(CMacroParseException, eParseRangeInvalid, msg);
876  }
877 
878  m_MacroRep->SetSeqRange(TSeqRange((unsigned)start, (unsigned)stop));
879  m_Scanner.Next();
880 }
881 
882 void CMacroParser::x_GetWhereClause(Int4 istart, Int4 iend, string& result) const
883 {
884  int len = static_cast<int>(iend - istart);
885  if ( len > 0 ) {
886  int i = 0;
887  result.resize(len + 1);
888  while (i<len)
889  result[i++] = m_StrMacro[istart++];
890  result[len] = '\0';
891  } else {
892  result.clear();
893  }
894 }
895 
896 namespace {
897  size_t s_NodeCost(const CQueryParseTree::TNode node)
898  {
899  switch (node->GetType()){
901  {
903  if ((*iter)->GetValue().GetType() == CQueryParseNode::eFunction) {
904  const string& name = (*iter)->GetValue().GetOrig();
905  if (NStr::StartsWith(name, "Sequence_for", NStr::eNocase)) {
906  return 100;
907  }
908  }
909  return 1;
910  }
912  {
914  if ((*iter)->GetValue().GetType() == CQueryParseNode::eFunction) {
915  const string& name = (*iter)->GetValue().GetOrig();
916  if (NStr::StartsWith(name, "Sequence_for", NStr::eNocase)) {
917  return 100;
918  }
919  }
920  return 5;
921  }
922  default:
923  return 10;
924  }
925  }
926 
927  struct SNode_Less
928  {
929  bool operator() (const CQueryParseTree::TNode* item1, const CQueryParseTree::TNode* item2) const
930  {
931  return s_NodeCost(*item1) < s_NodeCost(*item2);
932  }
933  };
934 } // end of namespace
935 
937 {
938  switch (node->GetType()) {
941  {{
942  vector<CQueryParseTree::TNode*> nodes;
943  if (node.CountNodes() > 1) {
945  for (; iter != node.SubNodeEnd();) {
946  CQueryParseTree::TNode* ptr = node.DetachNode(iter++);
947  nodes.push_back(ptr);
948  }
949 
950  std::function<bool(const CQueryParseTree::TNode*, const CQueryParseTree::TNode*)> sorter = SNode_Less();
951  sort(nodes.begin(), nodes.end(), sorter);
952  ITERATE(vector<CQueryParseTree::TNode*>, iter, nodes) {
953  node.AddNode(*iter);
954  }
955  }
956  }}
957  default:
958  break;
959  }
960 
962  for (; iter != node.SubNodeEnd(); ++iter) {
963  x_SortParseTree(**iter);
964  }
965 }
966 
967 CQueryParseTree* CMacroParser::x_QParseWhere(const string& str, unsigned line, unsigned linePos) const
968 {
969  unique_ptr<CQueryParseTree> ap_qparse_tree(new CQueryParseTree());
970  ap_qparse_tree->Parse(str.c_str(),
973  false,
975  line,
976  linePos
977  );
978 
979  Flatten_ParseTree(*ap_qparse_tree->GetQueryTree());
980 
981  x_SortParseTree(*ap_qparse_tree->GetQueryTree());
982 
983  CQueryParseTree* p_where_tree = ap_qparse_tree.release();
984  ap_qparse_tree.reset(NULL);
985  return p_where_tree;
986 }
987 
989 {
990  tree = 0;
991  str.empty();
992 
993  vector<CScanner::EToken> end_tokens{ CScanner::eTokenILLEGAL, CScanner::eTokenEOS, terminator };
995  end_tokens.push_back(CScanner::eTokenKWDOPARL);
996  }
997 
999  string msg = x_GetError();
1000  msg += "Keyword 'WHERE' expected instead of '";
1001  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1002  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
1003  }
1004 
1005  m_Scanner.Next();
1006  if (find(end_tokens.begin(), end_tokens.end(), m_Scanner.GetToken()) != end_tokens.end()) {
1007  string msg = x_GetError();
1008  msg += "'WHERE' clause expected instead of '";
1009  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1010  NCBI_THROW(CMacroParseException, eParseWhereClauseExpected, msg);
1011  }
1012 
1013  // store the potential error location
1015  const CScanner::SLocation whereStart = m_Scanner.GetLexemInfo().m_Start;
1016 
1018  while (find(end_tokens.begin(), end_tokens.end(), m_Scanner.GetToken()) == end_tokens.end()) {
1019  m_Scanner.Next();
1020  }
1022 
1023  x_GetWhereClause(istart , iend, str);
1024 
1025  if(!str.empty()) {
1026  try {
1027  tree = x_QParseWhere(str, whereStart.m_Line - 1, whereStart.m_Column - 1);
1028  }
1029  catch(CQueryParseException&)
1030  {
1031  m_ErrorLocation = er_loc;
1032  string msg = x_GetErrorLocation();
1033  msg += "Invalid 'WHERE' clause";
1034  NCBI_THROW(CMacroParseException, eParseWhereClauseInvalid, msg);
1035  }
1036  } else {
1037  string msg = x_GetError();
1038  msg += "Invalid 'WHERE' clause: ";
1040  NCBI_THROW(CMacroParseException, eParseWhereClauseInvalid, msg);
1041  }
1042 }
1043 
1045 {
1046  string where_clause;
1047  CQueryParseTree* where_tree;
1048 
1050  where_clause,
1051  where_tree);
1052 
1053  //where_tree->Print(NcbiCout);
1054  m_MacroRep->AttachWhereTree(where_tree);
1055 }
1056 
1058 {
1059  string where_clause;
1060  CQueryParseTree* where_tree;
1061 
1063  where_clause,
1064  where_tree);
1065 
1066  //where_tree->Print(NcbiCout);
1067  m_MacroRep->SetAssignmentWhereClause(where_clause, where_tree, m_Scanner.GetLexemInfo().m_Start);
1068 }
1069 
1071 {
1072  auto token = m_Scanner.GetToken();
1073  if (token != CScanner::eTokenKWDO &&
1074  token != CScanner::eTokenKWDOPARL) {
1075  string msg = x_GetError();
1076  msg += "Keyword 'DO' or keyword 'DO_P' expected instead of '";
1077  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1078  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
1079  }
1080 
1081  if (token == CScanner::eTokenKWDOPARL) {
1083  }
1084 
1085  CQueryParseTree *doTree = m_MacroRep->GetDoTree();
1086  _ASSERT(doTree);
1087  CQueryParseTree::TNode *doNode = doTree->GetQueryTree();
1088  _ASSERT(doNode);
1089  doNode->GetValue().SetLoc(m_Scanner.GetLexemInfo().m_Start);
1090 
1091  m_Scanner.Next();
1092  do {
1093  CQueryParseTree::TNode* assignmentNode = nullptr;
1095  string msg = x_GetError();
1096  msg += "Function or object name is expected instead of '";
1097  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1098  NCBI_THROW(CMacroParseException, eParseFunctionOrObjectNameExpected, msg);
1099  }
1100 
1101  string ident = m_Scanner.GetLexemInfo().m_Data.m_Str;
1102  if ( !x_IsFunction(ident) ) {
1103 
1105 
1106  if (m_MacroRep->FindVar(ident)) {
1107  string msg = x_GetError();
1108  msg += "Assignment to non-modifiable variable '";
1109  msg += ident + "' in this context";
1110  NCBI_THROW(CMacroParseException, eParseAssignmentToConst, msg);
1111  }
1112 
1113  // Create the variable node
1114  unique_ptr<CQueryParseTree::TNode> aptrVar (doTree->CreateNode(CQueryParseNode::eSelect, 0, 0, ident));
1115  aptrVar->GetValue().SetLoc(m_Scanner.GetLexemInfo().m_Start);
1116 
1117  m_RTVars.insert(ident);
1118 
1119  m_Scanner.Next();
1120 
1122  // the function name ('ident') was probably misspelled
1123  string msg = x_GetErrorLocation();
1124  msg += "Unknown function name: '" + ident + "'";
1125  NCBI_THROW(CMacroParseException, eParseFunctionExpected, msg);
1126  } else if (m_Scanner.GetToken() != CScanner::eTokenASSIGNMENT) {
1127  string msg = x_GetError();
1128  msg += "Assignment operator expected instead of '";
1129  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1130  NCBI_THROW(CMacroParseException, eParseAssignmentExpected, msg);
1131  }
1132 
1133  // Create the assignment node
1134  assignmentNode = doTree->CreateNode(CQueryParseNode::eFrom, aptrVar.release(), 0, "ASSIGNMENT OPERATOR");
1135  assignmentNode->GetValue().SetLoc(m_Scanner.GetLexemInfo().m_Start);
1136 
1137  // Attach the assignment to the tree
1138  doTree->GetQueryTree()->AddNode(assignmentNode);
1139 
1140  m_Scanner.Next();
1141  }
1143 
1144  x_ParseFunctionCall(assignmentNode);
1145  }
1146  while ( (m_Scanner.GetToken() != CScanner::eTokenKWDONE) &&
1149 
1151  string msg = x_GetError();
1152  msg += "Function name or 'DONE' expected instead of '";
1153  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1154  NCBI_THROW(CMacroParseException, eParseFunctionOrDoneExpected, msg);
1155  }
1156 
1157  m_Scanner.Next();
1158 }
1159 
1161 {
1163  string msg = x_GetError();
1164  msg += "Keyword 'DO_P' expected instead of '";
1165  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1166  NCBI_THROW(CMacroParseException, eParseKeywordExpected, msg);
1167  }
1168 
1169  m_Scanner.Next();
1171  string msg = x_GetError();
1172  msg += "Symbol '(' expected instead of '";
1173  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1174  NCBI_THROW(CMacroParseException, eParseLeftParenthesisExpected, msg);
1175  }
1176 
1177  Int8 threads = 0; // number of threads should always be specified in the macro
1178  int sign = 1;
1179 
1180  m_Scanner.Next();
1181  auto token = m_Scanner.GetToken();
1182 
1183  bool set_automatically = false;
1184  // it's true when DO_P(AUTO) is present in the macro
1185  // in that case, the engine decides the number of threads to be used based on the
1186  // number of features in the requested range and the type of features
1187 
1188  while ((token != CScanner::eTokenRIGHTPAREN) &&
1189  (token != CScanner::eTokenKWDO) &&
1190  (token != CScanner::eTokenKWWHERE) &&
1191  (token != CScanner::eTokenIDENT) &&
1192  (token != CScanner::eTokenILLEGAL) &&
1193  (token != CScanner::eTokenEOS)) {
1194 
1195  switch (token) {
1197  threads = sign * m_Scanner.GetLexemInfo().m_Data.m_IntNumber;
1198  break;
1202  {
1203  string msg = x_GetError();
1204  msg += "Positive integer number expected instead of '";
1205  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1206  NCBI_THROW(CMacroParseException, eParseIntegerExpected, msg);
1207  break;
1208  }
1211  {
1212  string msg = x_GetError();
1213  msg += "Symbol ')' expected instead of '";
1214  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1215  NCBI_THROW(CMacroParseException, eParseCommaOrRightBraceExpected, msg);
1216  break;
1217  }
1218  case CScanner::eTokenMINUS:
1219  sign = -1;
1220  break;
1222  set_automatically = true;
1223  break;
1224  default:
1225  break;
1226  }
1227 
1228  m_Scanner.Next();
1229  token = m_Scanner.GetToken();
1230  }
1231 
1233  string msg = x_GetError();
1234  msg += "Symbol ')' expected instead of '";
1235  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1236  NCBI_THROW(CMacroParseException, eParseRightParenthesisExpected, msg);
1237  }
1238 
1239  if (threads <= 0 && !set_automatically) {
1240  string msg = "Number of threads is expected to be a positive, non-zero integer";
1241  NCBI_THROW(CMacroParseException, eParseThreadCountInvalid, msg);
1242  }
1243  if (set_automatically) {
1245  }
1246  else {
1248  }
1249 }
1250 
1251 bool CMacroParser::x_IsFunction(const string& name) const
1252 {
1253  auto it = find_if(m_DoFunctionsList.begin(), m_DoFunctionsList.end(),
1254  [&name](const string& func) { return NStr::EqualNocase(func, name); } );
1255  return (it != m_DoFunctionsList.end());
1256 }
1257 
1259 {
1261  string msg = x_GetError();
1262  msg += "Function name expected instead of '";
1263  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1264  NCBI_THROW(CMacroParseException, eParseFunctionExpected, msg);
1265  }
1266 
1267  string fname = m_Scanner.GetLexemInfo().m_Data.m_Str;
1268  if (!x_IsFunction(fname)) {
1269  string msg = x_GetError();
1270  msg += "Unknown function name: '" + fname + "'";
1271  NCBI_THROW(CMacroParseException, eParseFunctionExpected, msg);
1272  }
1273 
1274  m_MacroRep->SetFunction(fname, m_Scanner.GetLexemInfo().m_Start, assignmentNode);
1275 
1276  m_Scanner.Next();
1278  string msg = x_GetError();
1279  msg += "Symbol '(' expected instead of '";
1280  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1281  NCBI_THROW(CMacroParseException, eParseLeftParenthesisExpected, msg);
1282  }
1283 
1284  m_Scanner.Next();
1286  bool bNextPar=true;
1287  while (bNextPar) {
1288  switch (m_Scanner.GetToken())
1289  {
1290  case CScanner::eTokenIDENT:
1291  // Identifier
1292  {
1293  string ident = m_Scanner.GetLexemInfo().m_Data.m_Str;
1294  if (!m_MacroRep->FindVar(ident) && (m_RTVars.find(ident) == m_RTVars.end()) &&
1295  !m_MacroRep->HasIdentifier(ident)) {
1296  string msg = x_GetError();
1297  msg += "Undefined variable: '" + ident + "'";
1298  NCBI_THROW(CMacroParseException, eParseUndefinedVariable, msg);
1299  }
1300 
1302  m_Scanner.Next();
1303  break;
1304  }
1306  // String
1308  m_Scanner.Next();
1309  break;
1311  // String
1313  m_Scanner.Next();
1314  break;
1315  default:
1316  {
1318  }
1319  }
1320 
1322  m_Scanner.Next();
1323  else
1324  bNextPar = false;
1325  }
1326  }
1327 
1329  string msg = x_GetError();
1330  msg += "Symbol '\"' expected around the argument of '" + fname + "'";
1331  NCBI_THROW(CMacroParseException, eParseWrongVariableUsage, msg);
1332  } else if (m_Scanner.GetToken() != CScanner::eTokenRIGHTPAREN) {
1333  string msg = x_GetError();
1334  msg += "Symbol ')' expected instead of '";
1335  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1336  NCBI_THROW(CMacroParseException, eParseRightParenthesisExpected, msg);
1337  }
1338  m_Scanner.Next();
1339 
1340  if (!assignmentNode && m_Scanner.GetToken() != CScanner::eTokenSEMICOLON) {
1341  string msg = x_GetError();
1342  msg += "Symbol ';' expected";
1343  NCBI_THROW(CMacroParseException, eParseSemicolonExpected, msg);
1344  }
1345 
1346  switch ( m_Scanner.GetToken() ) {
1349  m_Scanner.Next();
1350  break;
1352  m_Scanner.Next();
1353  break;
1354  default:{
1355  string msg = x_GetError();
1356  msg += "Keyword 'WHERE' or semicolon expected instead of '";
1357  msg += m_Scanner.GetLexemInfo().GetStringRepr() + "'";
1358  NCBI_THROW(CMacroParseException, eParseEndOfFunction, msg);
1359  }
1360  }
1361 }
1362 
1364 {
1365  switch (m_Scanner.GetToken()) {
1367  {
1370  break;
1371  }
1373  {
1374  double value = sign * m_Scanner.GetLexemInfo().m_Data.m_FloatNumber;
1376  break;
1377  }
1378  default: {
1379  string msg = x_GetError();
1380  msg += "Variable definition expected";
1381  NCBI_THROW(CMacroParseException, eParseVarDefinitionExpected, msg);
1382  }
1383  }
1384 
1385  m_Scanner.Next();
1386 }
1387 
1389  m_WhereFunctionsList = wh_funcs;
1390  m_DoFunctionsList = do_funcs;
1391 }
1392 
1394 {
1396  string msg = "COMMENT token expected";
1397  NCBI_THROW(CMacroParseException, eParseFunctionExpected, msg);
1398  }
1399 
1400  const char kKeywords[] = "#Keywords:";
1401 
1402  string comment = m_Scanner.GetLexemInfo().GetStringRepr();
1403  size_t pos = comment.find(kKeywords);
1404  if (pos == string::npos)
1405  return;
1406 
1407  string keywords = comment.substr(pos + sizeof(kKeywords) - 1);
1408 
1409  string delim, result;
1410  pos = 0;
1411  for(;;) {
1412  size_t pos2 = keywords.find(',', pos);
1413  size_t len = (pos2 == string::npos) ? pos2 : pos2 - pos;
1414  if (len > 0) {
1415  string w = NStr::TruncateSpaces(keywords.substr(pos, len));
1416  if (!w.empty()) {
1417  result += delim;
1418  delim = ",";
1419  result += w;
1420  }
1421  }
1422 
1423  if (pos2 == string::npos)
1424  break;
1425 
1426  pos = pos2 + 1;
1427  }
1428 
1429  if (!result.empty())
1431 }
1432 
1433 END_SCOPE(macro)
1435 
1436 /* @} */
#define bool
Definition: bool.h:34
Macro exception.
Definition: macro_ex.hpp:55
Class for parsed macro representation.
Definition: macro_rep.hpp:254
Query execution environment holds the function registry and the execution context.
Definition: query_exec.hpp:144
Query parser exceptions.
Query tree and associated utility methods.
Class for lexical tokens extraction from macro string.
Definition: macro_parse.hpp:60
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
definition of a Culling tree
Definition: ncbi_tree.hpp:100
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
void clear()
Definition: set.hpp:153
const_iterator find(const key_type &key) const
Definition: set.hpp:137
const_iterator end() const
Definition: set.hpp:136
char value[7]
Definition: config.c:431
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NULL
Definition: ncbistd.hpp:225
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
void x_ParseNumericVarValue(const string &var_name, int sign)
Entry point to parse numeric var value.
void x_ParseFunctionCall(CQueryParseTree::TNode *assignmentNode)
Entry point to parse function call.
static const char * sm_Automatic
void SetName(const string &name)
Set the name of the macro.
Definition: macro_rep.hpp:275
const SLexem & GetLexemInfo() const
static const int MAX_STRING_LEXEM_LENGTH
Max buffer size for lexem string info.
Definition: macro_parse.hpp:63
bool Parse(bool bSingleMacroMode=true, CQueryExec *exec=NULL)
Parse the macro and build its representation Function throws CMacroException if parsing is unsuccessf...
void x_ParseNumericChoiceValue(int sign)
Parses numeric value of a choice variable.
string x_GetErrorLocation() const
int x_GetQuotedString()
Definition: macro_parse.cpp:65
void x_InitForNextLexem()
void SetForEachItem(const string &name)
Set "for each" asn selector.
Definition: macro_rep.hpp:309
SLocation GetErrorLocation() const
void x_ParseDo()
Entry point to parse DO-DONE section.
CMacroRep * m_MacroRep
binary representation of macro while parsing
void x_ParseRange()
Entry point to parse range.
SLexem m_CurrentLexem
void x_UpdateErrorLocation()
void SetVarChoiceString(const string &value)
Definition: macro_rep.cpp:467
void SetNamedAnnot(const string &name)
Set named annotation.
Definition: macro_rep.hpp:311
bool x_IsFunction(const string &name) const
Checks whether its parameter is a name of the registered functions.
void x_ParseChoice()
Entry point to parse choice section.
void SetAssignmentWhereClause(const string &where_str, CQueryParseTree *where_tree, const CQueryParseNode::SSrcLoc &pos)
Set the function Where clause as a part of an assignment operator.
Definition: macro_rep.cpp:344
TFunctionNamesList m_DoFunctionsList
list of functions available for Do clause
void SetFunctionParameterAsIdent(const string &name, const CQueryParseNode::SSrcLoc &pos)
Set the function parameters.
Definition: macro_rep.cpp:294
void SetFunctionParameterAsBool(bool value, const CQueryParseNode::SSrcLoc &pos)
Definition: macro_rep.cpp:324
void SetVarFloat(const string &name, double value)
Definition: macro_rep.cpp:385
void SetVarString(const string &name, const string &value)
Definition: macro_rep.cpp:407
CScanner::EToken GetToken()
Definition: macro_parse.cpp:60
void x_ParseVariables()
Entry point to parse vars section.
void x_ParseThreadCount()
Entry point to parse number of threads to be used.
void SetFunctionParameterAsString(const string &value, const CQueryParseNode::SSrcLoc &pos)
Definition: macro_rep.cpp:334
CQueryParseTree::TFunctionNames TFunctionNamesList
Type for the list of functions in Where/Do clauses.
void x_ParseFunctionWhere()
Entry point to parse where clause in function call.
void SetFunctionNames(const TFunctionNamesList &wh_funcs, const TFunctionNamesList &do_funcs)
initializes lists of known functions that should be recognized by the parser when going through WHERE...
void SetFunctionParameterAsFloat(double value, const CQueryParseNode::SSrcLoc &pos)
Definition: macro_rep.cpp:314
int NextNamedAnnot()
void SetVarChoiceBool(bool value)
Definition: macro_rep.cpp:458
CScanner::SLocation m_ErrorLocation
error location
string GetStringRepr() const
void SetNewVarBlock()
Set the new variable block.
Definition: macro_rep.hpp:292
set< string > m_RTVars
list of run-time variables met in the left side of assignment in DO clause
void x_ParseScript()
Entry point to parse whole script.
bool FindVar(const string &name) const
Look up the variable among the stored ones.
Definition: macro_rep.cpp:476
void x_ParseMetaData()
void SetFunction(const string &name, const CQueryParseNode::SSrcLoc &pos, CQueryParseTree::TNode *parentNode=0)
Set function name.
Definition: macro_rep.cpp:285
void x_InitParser()
Resets parser to initial state.
void AddMetaKeywords(const string &keyWords)
Definition: macro_rep.hpp:279
void SetVarChoiceName(const string &name)
Definition: macro_rep.cpp:429
void SetTitle(const string &title)
Set the title of the macro.
Definition: macro_rep.hpp:277
CScanner m_Scanner
scanner for extracting tokens and meta info
void SetVarInt(const string &name, Int8 value)
Definition: macro_rep.cpp:374
SLocation m_Position
void SetVarChoiceInt(Int8 value)
Definition: macro_rep.cpp:440
EParsingErrReportType m_ErrorReportType
Specifies the type of error reporting.
void SetSeqRange(const TSeqRange &range)
Set the sequence range.
Definition: macro_rep.hpp:313
void x_GetWhereClause(Int4 istart, Int4 iend, string &result) const
Extracts where clause as a string.
string x_GetError()
int Next(bool parseComment=false)
void SetVarAsk(const string &name, const string &value)
Definition: macro_rep.cpp:418
CQueryParseTree * GetDoTree() const
Return "do" clause.
Definition: macro_rep.hpp:367
void SetVarChoiceFloat(double value)
Definition: macro_rep.cpp:449
void AttachWhereTree(CQueryParseTree *pWhereTree)
Attach where tree after its constrution in qParser.
Definition: macro_rep.cpp:360
void x_SortParseTree(CQueryParseTree::TNode &node) const
Sorts the nodes according to a weight function for faster tree evaluation.
TFunctionNamesList m_WhereFunctionsList
list of functions available for Where clause
void x_ParseNumericParameterValue(int sign, CScanner::SLocation start)
Parses numeric value of a function parameter.
void Reset(const char *sMacroText)
const char * m_StrMacro
bool HasIdentifier(const string &ident) const
Return true if identifier is in datasource (only works if m_Exec not NULL)
Definition: macro_rep.cpp:543
int x_SetCurrentLexem(Int4 &pos, CScanner::EToken token)
void SetFunctionParameterAsInt(Int8 value, const CQueryParseNode::SSrcLoc &pos)
Definition: macro_rep.cpp:304
const char * m_StrMacro
string to be parsed
int NextASNSelector()
void x_ParseWhere()
Entry point to parse where clause.
void SetVarBool(const string &name, bool value)
Definition: macro_rep.cpp:396
CQueryParseTree * x_QParseWhere(const string &str, unsigned line, unsigned linePos) const
Translates Where clause into a tree.
void SetThreadCount(const string &threads)
Set number of threads.
Definition: macro_rep.hpp:315
void SetSource(const string &source_text)
Work with macro source text.
Definition: macro_rep.hpp:333
char m_Str[MAX_STRING_LEXEM_LENGTH+1]
SLocation m_ErrorLoc
void x_InternalParseWhere(const CScanner::EToken terminator, string &str, CQueryParseTree *&tree)
Extracts Where clause string and builds Where clause tree; it uses terminator token to determine the ...
void x_ParseBody()
Entry point to parse body section.
@ eErrorLineAndColumn
Report the line and column for the error (default)
@ eTokenKWDONE
Keyword done.
Definition: macro_parse.hpp:78
@ eTokenKWVARS
Keyword var or vars.
Definition: macro_parse.hpp:70
@ eTokenKWDOPARL
Keyword do_p(arallel)
Definition: macro_parse.hpp:79
@ eTokenKWPARLAUTO
Keyword auto used with do_p keyword.
Definition: macro_parse.hpp:80
@ eTokenNOTEQUAL
'<>' token
@ eTokenRIGHTPAREN
')' token
Definition: macro_parse.hpp:94
@ eTokenCOMMENT
Comment read on request.
@ eTokenKWDO
Keyword do.
Definition: macro_parse.hpp:77
@ eTokenCOMMA
',' token
Definition: macro_parse.hpp:99
@ eTokenEOS
If next token is eos.
Definition: macro_parse.hpp:67
@ eTokenKWEACH
Keyword each as a part of for each.
Definition: macro_parse.hpp:72
@ eTokenKWCHOICE
Keyword choice.
Definition: macro_parse.hpp:74
@ eTokenNOTLESS
'>=' token
@ eTokenASNSELECTOR
ASN selector.
Definition: macro_parse.hpp:84
@ eTokenLEFTPAREN
'(' token
Definition: macro_parse.hpp:93
@ eTokenMULT
'*' token
@ eTokenKWMACRO
Keyword macro.
Definition: macro_parse.hpp:69
@ eTokenBOOLCONST
Boolean const value.
Definition: macro_parse.hpp:90
@ eTokenMINUS
'-' token
@ eTokenDIV
'/' token
@ eTokenLEFTBRACE
'{' token
Definition: macro_parse.hpp:97
@ eTokenLEFTBRACKET
'[' token
Definition: macro_parse.hpp:95
@ eTokenFLOATNUMBER
Floating point number.
Definition: macro_parse.hpp:87
@ eTokenKWWHERE
Keyword where.
Definition: macro_parse.hpp:76
@ eTokenASSIGNMENT
'=' token
Definition: macro_parse.hpp:92
@ eTokenNOTGREATER
'<=' token
@ eTokenINTNUMBER
Integer number.
Definition: macro_parse.hpp:86
@ eTokenKWFROM
Keyword from for specifying named annotation.
Definition: macro_parse.hpp:73
@ eTokenSTRING
String in double quotes.
Definition: macro_parse.hpp:88
@ eTokenLESS
'<' token
@ eTokenKWRANGE
Keyword range.
Definition: macro_parse.hpp:75
@ eTokenASK
String enclosed in % symbols.
Definition: macro_parse.hpp:89
@ eTokenGREATER
'>' token
@ eTokenRIGHTBRACE
'}' token
Definition: macro_parse.hpp:98
@ eTokenRIGHTBRACKET
']' token
Definition: macro_parse.hpp:96
@ eTokenILLEGAL
Error.
Definition: macro_parse.hpp:66
@ eTokenSEMICOLON
';' token
@ eTokenIDENT
Identifier.
Definition: macro_parse.hpp:83
@ eTokenKWFOR
Keyword for as a part of for each.
Definition: macro_parse.hpp:71
@ eTokenDOT
'.' token
@ eTokenNAMEDANNOT
Named annotation.
Definition: macro_parse.hpp:85
@ eTokenPLUS
'+' token
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
virtual TNode * CreateNode(const string &value, const string &orig_text, bool isIdent)
Create Identifier node or string node.
const TNode * GetQueryTree() const
void Flatten_ParseTree(CQueryParseTree::TNode &node)
Flatten the AND and the OR subtrees transforming them from binary subtrees to n-ary subtrees.
Definition: parse_utils.cpp:38
@ eCaseInsensitive
Case insensitive parsing (AnD)
@ eFunction
Function.
Definition: query_parse.hpp:91
@ eSyntaxCheck
Best possible check for errors.
CRange< TSeqPos > TSeqRange
typedefs for sequence ranges
Definition: range.hpp:419
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5158
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5083
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5411
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5352
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string.
Definition: ncbistr.cpp:3182
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
TNodeList::iterator TNodeList_I
Definition: ncbi_tree.hpp:109
TTreeType * DetachNode(TTreeType *subnode)
Remove the subtree from the tree without destroying it.
Definition: ncbi_tree.hpp:720
unsigned int CountNodes(unsigned int depth=1, TCountNodes how=0) const
Count nodes of the tree of which this node is a root.
Definition: ncbi_tree.hpp:999
TNodeList_CI SubNodeBegin(void) const
Return first const iterator on subnode list.
Definition: ncbi_tree.hpp:160
TNodeList::const_iterator TNodeList_CI
Definition: ncbi_tree.hpp:110
void AddNode(TTreeType *subnode)
Add new subnode.
Definition: ncbi_tree.hpp:743
TNodeList_CI SubNodeEnd(void) const
Return last const iterator on subnode list.
Definition: ncbi_tree.hpp:166
const TValue & GetValue(void) const
Return node's value.
Definition: ncbi_tree.hpp:184
int i
int len
Macro exceptions.
Macro parser components.
constexpr auto sort(_Init &&init)
int isalpha(Uchar c)
Definition: ncbictype.hpp:61
int tolower(Uchar c)
Definition: ncbictype.hpp:72
int isdigit(Uchar c)
Definition: ncbictype.hpp:64
static char terminator
Definition: njn_ioutil.cpp:56
static const char * str(char *buf, int n)
Definition: stats.c:84
#define _ASSERT
else result
Definition: token2.c:20
Modified on Mon Dec 11 02:39:23 2023 by modify_doxy.py rev. 669887