ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/selection/SelectionCompiler.cpp
(Generate patch)

Comparing trunk/src/selection/SelectionCompiler.cpp (file contents):
Revision 303 by tim, Mon Feb 7 22:36:32 2005 UTC vs.
Revision 1523 by kstocke1, Fri Nov 19 20:27:02 2010 UTC

# Line 6 | Line 6
6   * redistribute this software in source and binary code form, provided
7   * that the following conditions are met:
8   *
9 < * 1. Acknowledgement of the program authors must be made in any
10 < *    publication of scientific results based in part on use of the
11 < *    program.  An acceptable form of acknowledgement is citation of
12 < *    the article in which the program was described (Matthew
13 < *    A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 < *    J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 < *    Parallel Simulation Engine for Molecular Dynamics,"
16 < *    J. Comput. Chem. 26, pp. 252-271 (2005))
17 < *
18 < * 2. Redistributions of source code must retain the above copyright
9 > * 1. Redistributions of source code must retain the above copyright
10   *    notice, this list of conditions and the following disclaimer.
11   *
12 < * 3. Redistributions in binary form must reproduce the above copyright
12 > * 2. Redistributions in binary form must reproduce the above copyright
13   *    notice, this list of conditions and the following disclaimer in the
14   *    documentation and/or other materials provided with the
15   *    distribution.
# Line 37 | Line 28
28   * arising out of the use of or inability to use software, even if the
29   * University of Notre Dame has been advised of the possibility of
30   * such damages.
31 + *
32 + * SUPPORT OPEN SCIENCE!  If you use OpenMD or its source code in your
33 + * research, please cite the appropriate papers when you publish your
34 + * work.  Good starting points are:
35 + *                                                                      
36 + * [1]  Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).            
37 + * [2]  Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).          
38 + * [3]  Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).          
39 + * [4]  Vardeman & Gezelter, in progress (2009).                        
40   */
41  
42   #include "selection/SelectionCompiler.hpp"
43   #include "utils/StringUtils.hpp"
44 < namespace oopse {
44 > namespace OpenMD {
45  
46 < bool SelectionCompiler::compile(const std::string& filename, const std::string& script) {
46 >  bool SelectionCompiler::compile(const std::string& filename,
47 >                                  const std::string& script) {
48  
49      this->filename = filename;
50      this->script = script;
# Line 52 | Line 53 | bool SelectionCompiler::compile(const std::string& fil
53      aatokenCompiled.clear();
54          
55      if (internalCompile()) {
56 <        return true;
56 >      return true;
57      }
58      
59      int icharEnd;
60      if ((icharEnd = script.find('\r', ichCurrentCommand)) == std::string::npos &&
61          (icharEnd = script.find('\n', ichCurrentCommand)) == std::string::npos) {
62 <        icharEnd = script.size();
62 >      icharEnd = script.size();
63      }
64      errorLine = script.substr(ichCurrentCommand, icharEnd);
65      return false;
66 < }
66 >  }
67  
68 < bool SelectionCompiler::internalCompile(){
68 >  bool SelectionCompiler::internalCompile(){
69  
70      cchScript = script.size();
71      ichToken = 0;
# Line 80 | Line 81 | bool SelectionCompiler::internalCompile(){
81      int tokCommand = Token::nada;
82  
83      for ( ; true; ichToken += cchToken) {
84 <        if (lookingAtLeadingWhitespace())
85 <            continue;
86 <        //if (lookingAtComment())
87 <        //    continue;
88 <        bool endOfLine = lookingAtEndOfLine();
89 <        if (endOfLine || lookingAtEndOfStatement()) {
90 <            if (tokCommand != Token::nada) {
91 <                if (! compileCommand(ltoken)) {
92 <                    return false;
93 <                }
94 <                aatokenCompiled.push_back(atokenCommand);
95 <                lineNumbers.push_back(lineCurrent);
96 <                lineIndices.push_back(ichCurrentCommand);
97 <                ltoken.clear();
98 <                tokCommand = Token::nada;
99 <            }
84 >      if (lookingAtLeadingWhitespace())
85 >        continue;
86 >      //if (lookingAtComment())
87 >      //    continue;
88 >      bool endOfLine = lookingAtEndOfLine();
89 >      if (endOfLine || lookingAtEndOfStatement()) {
90 >        if (tokCommand != Token::nada) {
91 >          if (! compileCommand(ltoken)) {
92 >            return false;
93 >          }
94 >          aatokenCompiled.push_back(atokenCommand);
95 >          lineNumbers.push_back(lineCurrent);
96 >          lineIndices.push_back(ichCurrentCommand);
97 >          ltoken.clear();
98 >          tokCommand = Token::nada;
99 >        }
100              
101 <            if (ichToken < cchScript) {
102 <                if (endOfLine)
103 <                    ++lineCurrent;
104 <              continue;
105 <            }
106 <            break;
107 <        }
101 >        if (ichToken < cchScript) {
102 >          if (endOfLine)
103 >            ++lineCurrent;
104 >          continue;
105 >        }
106 >        break;
107 >      }
108  
109 <        if (tokCommand != Token::nada) {
110 <            if (lookingAtString()) {
111 <                std::string str = getUnescapedStringLiteral();
112 <                ltoken.push_back(Token(Token::string, str));
113 <                continue;
114 <            }
115 <            //if ((tokCommand & Token::specialstring) != 0 &&
116 <            //    lookingAtSpecialString()) {
117 <            //    std::string str = script.substr(ichToken, ichToken + cchToken);
118 <            //    ltoken.push_back(Token(Token::string, str));
119 <            //    continue;
120 <            //}
121 <            if (lookingAtDecimal((tokCommand & Token::negnums) != 0)) {
122 <                float value = lexi_cast<float>(script.substr(ichToken, cchToken));        
123 <                std::cout << "encount an decimal: " << value << std::endl;
124 <                ltoken.push_back(Token(Token::decimal, boost::any(value)));
125 <                continue;
126 <            }
126 <            if (lookingAtInteger((tokCommand & Token::negnums) != 0)) {
109 >      if (tokCommand != Token::nada) {
110 >        if (lookingAtString()) {
111 >          std::string str = getUnescapedStringLiteral();
112 >          ltoken.push_back(Token(Token::string, str));
113 >          continue;
114 >        }
115 >        //if ((tokCommand & Token::specialstring) != 0 &&
116 >        //    lookingAtSpecialString()) {
117 >        //    std::string str = script.substr(ichToken, ichToken + cchToken);
118 >        //    ltoken.push_back(Token(Token::string, str));
119 >        //    continue;
120 >        //}
121 >        if (lookingAtDecimal((tokCommand & Token::negnums) != 0)) {
122 >          float value = lexi_cast<float>(script.substr(ichToken, cchToken));        
123 >          ltoken.push_back(Token(Token::decimal, boost::any(value)));
124 >          continue;
125 >        }
126 >        if (lookingAtInteger((tokCommand & Token::negnums) != 0)) {
127  
128 <                int val = lexi_cast<int>(script.substr(ichToken, cchToken));
129 <                std::cout << "encount an integer: " << val << std::endl;
130 <                ltoken.push_back(Token(Token::integer,   boost::any(val)));
131 <                continue;
132 <            }
133 <        }
128 >          int val = lexi_cast<int>(script.substr(ichToken, cchToken));
129 >          ltoken.push_back(Token(Token::integer,   boost::any(val)));
130 >          continue;
131 >        }
132 >      }
133        
134 <        if (lookingAtLookupToken()) {
135 <            std::string ident = script.substr(ichToken, cchToken);
136 <            Token token;            
137 <            Token* pToken = TokenMap::getInstance()->getToken(ident);
138 <            if (pToken != NULL) {
139 <                token = *pToken;
140 <            } else {
141 <                token = Token(Token::identifier, ident);
142 <            }
134 >      if (lookingAtLookupToken()) {
135 >        std::string ident = script.substr(ichToken, cchToken);
136 >        Token token;            
137 >        Token* pToken = TokenMap::getInstance()->getToken(ident);
138 >        if (pToken != NULL) {
139 >          token = *pToken;
140 >        } else {
141 >          token = Token(Token::identifier, ident);
142 >        }
143              
144 <            int tok = token.tok;
144 >        int tok = token.tok;
145              
146 <            switch (tokCommand) {
147 <                case Token::nada:
148 <                    ichCurrentCommand = ichToken;
149 <                    //tokenCommand = token;
150 <                    tokCommand = tok;
151 <                    if ((tokCommand & Token::command) == 0)
152 <                    return commandExpected();
153 <                    break;
146 >        switch (tokCommand) {
147 >        case Token::nada:
148 >          ichCurrentCommand = ichToken;
149 >          //tokenCommand = token;
150 >          tokCommand = tok;
151 >          if ((tokCommand & Token::command) == 0)
152 >            return commandExpected();
153 >          break;
154  
155 <                case Token::define:
156 <                    if (ltoken.size() == 1) {
157 <                        // we are looking at the variable name
158 <                        if (tok != Token::identifier &&
159 <                        (tok & Token::predefinedset) != Token::predefinedset)
160 <                        return invalidExpressionToken(ident);
161 <                    } else {
162 <                    // we are looking at the expression
163 <                    if (tok != Token::identifier &&
164 <                        (tok & (Token::expression | Token::predefinedset)) == 0)
165 <                        return invalidExpressionToken(ident);
166 <                    }
155 >        case Token::define:
156 >          if (ltoken.size() == 1) {
157 >            // we are looking at the variable name
158 >            if (tok != Token::identifier &&
159 >                (tok & Token::predefinedset) != Token::predefinedset)
160 >              return invalidExpressionToken(ident);
161 >          } else {
162 >            // we are looking at the expression
163 >            if (tok != Token::identifier &&
164 >                (tok & (Token::expression | Token::predefinedset)) == 0)
165 >              return invalidExpressionToken(ident);
166 >          }
167                      
168 <                    break;
168 >          break;
169  
170 <                case Token::select:
171 <                    if (tok != Token::identifier && (tok & Token::expression) == 0)
172 <                        return invalidExpressionToken(ident);
173 <                break;
174 <            }
175 <            ltoken.push_back(token);
176 <            continue;
177 <        }
170 >        case Token::select:
171 >          if (tok != Token::identifier && (tok & Token::expression) == 0)
172 >            return invalidExpressionToken(ident);
173 >          break;
174 >        }
175 >        ltoken.push_back(token);
176 >        continue;
177 >      }
178  
179 <        if (ltoken.size() == 0) {
180 <            return commandExpected();
181 <        }
179 >      if (ltoken.size() == 0) {
180 >        return commandExpected();
181 >      }
182          
183 <        return unrecognizedToken();
183 >      return unrecognizedToken();
184      }
185  
186      return true;
# Line 206 | Line 205 | bool SelectionCompiler::internalCompile(){
205      if (ch == '\r') {
206        ++ichT;
207        if (ichT < cchScript && script[ichT] == '\n')
208 <          ++ichT;
208 >        ++ichT;
209      } else if (ch == '\n') {
210        ++ichT;
211      } else {
# Line 245 | Line 244 | bool SelectionCompiler::internalCompile(){
244      }
245      cchToken = ichT - ichToken;
246  
248
249    std::cout << "lookingAtString: encount " << script.substr(ichToken, cchToken) << std::endl;
247      return true;
248    }
249  
250    
251 < std::string SelectionCompiler::getUnescapedStringLiteral() {
251 >  std::string SelectionCompiler::getUnescapedStringLiteral() {
252      /** @todo */
253      std::string sb(cchToken - 2, ' ');
254      
# Line 259 | Line 256 | std::string SelectionCompiler::getUnescapedStringLiter
256      int ich = ichToken + 1;
257  
258      while (ich < ichMax) {
259 <        char ch = script[ich++];
260 <        if (ch == '\\' && ich < ichMax) {
261 <            ch = script[ich++];
262 <            switch (ch) {
263 <                case 'b':
264 <                    ch = '\b';
265 <                    break;
266 <                case 'n':
267 <                    ch = '\n';
268 <                    break;
269 <                case 't':
270 <                    ch = '\t';
271 <                    break;
272 <                case 'r':
273 <                    ch = '\r';
274 <                    // fall into
275 <                case '"':
276 <                case '\\':
277 <                case '\'':
278 <                break;
279 <                case 'x':
280 <                case 'u':
281 <                    int digitCount = ch == 'x' ? 2 : 4;
282 <                    if (ich < ichMax) {
283 <                        int unicode = 0;
284 <                        for (int k = digitCount; --k >= 0 && ich < ichMax; ) {
285 <                            char chT = script[ich];
286 <                            int hexit = getHexitValue(chT);
287 <                            if (hexit < 0)
288 <                                break;
289 <                            unicode <<= 4;
290 <                            unicode += hexit;
291 <                            ++ich;
292 <                        }
293 <                        ch = (char)unicode;
294 <                    }
295 <            }
296 <        }
297 <        sb.append(1, ch);
259 >      char ch = script[ich++];
260 >      if (ch == '\\' && ich < ichMax) {
261 >        ch = script[ich++];
262 >        switch (ch) {
263 >        case 'b':
264 >          ch = '\b';
265 >          break;
266 >        case 'n':
267 >          ch = '\n';
268 >          break;
269 >        case 't':
270 >          ch = '\t';
271 >          break;
272 >        case 'r':
273 >          ch = '\r';
274 >          // fall into
275 >        case '"':
276 >        case '\\':
277 >        case '\'':
278 >          break;
279 >        case 'x':
280 >        case 'u':
281 >          int digitCount = ch == 'x' ? 2 : 4;
282 >          if (ich < ichMax) {
283 >            int unicode = 0;
284 >            for (int k = digitCount; --k >= 0 && ich < ichMax; ) {
285 >              char chT = script[ich];
286 >              int hexit = getHexitValue(chT);
287 >              if (hexit < 0)
288 >                break;
289 >              unicode <<= 4;
290 >              unicode += hexit;
291 >              ++ich;
292 >            }
293 >            ch = (char)unicode;
294 >          }
295 >        }
296 >      }
297 >      sb.append(1, ch);
298      }
299  
300      return sb;
301 < }
301 >  }
302  
303 < int SelectionCompiler::getHexitValue(char ch) {
303 >  int SelectionCompiler::getHexitValue(char ch) {
304      if (ch >= '0' && ch <= '9')
305 <        return ch - '0';
305 >      return ch - '0';
306      else if (ch >= 'a' && ch <= 'f')
307 <        return 10 + ch - 'a';
307 >      return 10 + ch - 'a';
308      else if (ch >= 'A' && ch <= 'F')
309 <        return 10 + ch - 'A';
309 >      return 10 + ch - 'A';
310      else
311 <        return -1;
312 < }
311 >      return -1;
312 >  }
313  
314 < bool SelectionCompiler::lookingAtSpecialString() {
314 >  bool SelectionCompiler::lookingAtSpecialString() {
315      int ichT = ichToken;
316      char ch = script[ichT];
317      while (ichT < cchScript && ch != ';' && ch != '\r' && ch != '\n') {
318 <        ++ichT;
318 >      ++ichT;
319      }
320      cchToken = ichT - ichToken;
321      return cchToken > 0;
322 < }
322 >  }
323  
324 < bool SelectionCompiler::lookingAtDecimal(bool allowNegative) {
324 >  bool SelectionCompiler::lookingAtDecimal(bool allowNegative) {
325      if (ichToken == cchScript) {
326 <        return false;
326 >      return false;
327      }
328      
329      int ichT = ichToken;
330      if (script[ichT] == '-') {
331 <        ++ichT;
331 >      ++ichT;
332      }
333      bool digitSeen = false;
334      char ch = 'X';
335      while (ichT < cchScript && std::isdigit(ch = script[ichT])) {
336 <        ++ichT;
337 <        digitSeen = true;
336 >      ++ichT;
337 >      digitSeen = true;
338      }
339  
340      if (ichT == cchScript || ch != '.') {
341 <        return false;
341 >      return false;
342      }
343  
344      // to support DMPC.1, let's check the character before the dot
345      if (ch == '.' && (ichT > 0) && std::isalpha(script[ichT - 1])) {
346 <        return false;
346 >      return false;
347      }
348  
349      ++ichT;
350      while (ichT < cchScript && std::isdigit(script[ichT])) {
351 <        ++ichT;
352 <        digitSeen = true;
351 >      ++ichT;
352 >      digitSeen = true;
353      }
354      cchToken = ichT - ichToken;
355      return digitSeen;
356 < }
356 >  }
357  
358 < bool SelectionCompiler::lookingAtInteger(bool allowNegative) {
358 >  bool SelectionCompiler::lookingAtInteger(bool allowNegative) {
359      if (ichToken == cchScript) {
360 <        return false;
360 >      return false;
361      }
362      int ichT = ichToken;
363      if (allowNegative && script[ichToken] == '-') {
364 <        ++ichT;
364 >      ++ichT;
365      }
366      int ichBeginDigits = ichT;
367      while (ichT < cchScript && std::isdigit(script[ichT])) {
368 <        ++ichT;
368 >      ++ichT;
369      }
370      if (ichBeginDigits == ichT) {
371 <        return false;
371 >      return false;
372      }
373      cchToken = ichT - ichToken;
374      return true;
375 < }
375 >  }
376  
377 < bool SelectionCompiler::lookingAtLookupToken() {
377 >  bool SelectionCompiler::lookingAtLookupToken() {
378      if (ichToken == cchScript) {
379 <        return false;
379 >      return false;
380      }
381  
382      int ichT = ichToken;
383      char ch;
384      switch (ch = script[ichT++]) {
385 <        case '(':
386 <        case ')':
387 <        case ',':
388 <        case '*':
389 <        case '-':
390 <        case '[':
391 <        case ']':
392 <        case '+':
393 <        case ':':
394 <        case '@':
395 <        case '.':
396 <        case '%':
397 <        break;
398 <        case '&':
399 <        case '|':
400 <            if (ichT < cchScript && script[ichT] == ch) {
401 <                ++ichT;
402 <            }
403 <        break;
404 <        case '<':
405 <        case '=':
406 <        case '>':
407 <            if (ichT < cchScript && ((ch = script[ichT]) == '<' || ch == '=' || ch == '>')) {
408 <                ++ichT;
409 <            }
410 <            break;
411 <        case '/':
412 <        case '!':
413 <            if (ichT < cchScript && script[ichT] == '=') {
414 <                ++ichT;
415 <            }
416 <            break;
417 <        default:
421 <            if ((ch < 'a' || ch > 'z') && (ch < 'A' && ch > 'Z') && ch != '_') {
422 <                return false;
423 <            }
424 <        case '?': // include question marks in identifier for atom expressions
425 <            while (ichT < cchScript && !std::isspace(ch = script[ichT]) && (std::isalpha(ch) ||std::isdigit(ch) ||
426 <                ch == '_' || ch == '?') ) {
385 >    case '(':
386 >    case ')':
387 >    case ',':
388 >    case '[':
389 >    case ']':
390 >      break;
391 >    case '&':
392 >    case '|':
393 >      if (ichT < cchScript && script[ichT] == ch) {
394 >        ++ichT;
395 >      }
396 >      break;
397 >    case '<':
398 >    case '=':
399 >    case '>':
400 >      if (ichT < cchScript && ((ch = script[ichT]) == '<' || ch == '=' || ch == '>')) {
401 >        ++ichT;
402 >      }
403 >      break;
404 >    case '/':
405 >    case '!':
406 >      if (ichT < cchScript && script[ichT] == '=') {
407 >        ++ichT;
408 >      }
409 >      break;
410 >    default:
411 >      if ((ch < 'a' || ch > 'z') && (ch < 'A' && ch > 'Z') && ch != '_') {
412 >        return false;
413 >      }
414 >    case '*':
415 >    case '?': // include question marks in identifier for atom expressions
416 >      while (ichT < cchScript && !std::isspace(ch = script[ichT]) &&
417 >             (std::isalpha(ch) ||std::isdigit(ch) || ch == '_' || ch == '.' || ch == '*' || ch == '?' || ch == '+' || ch == '-' || ch == '[' || ch == ']') ){
418  
419 <                ++ichT;
420 <            }
421 <        break;
419 >        ++ichT;
420 >      }
421 >      break;
422      }
423  
424      cchToken = ichT - ichToken;
425  
435    std::cout << "lookingAtLookupToken: encount " << script.substr(ichToken, cchToken) << std::endl;
426      return true;
427 < }
427 >  }
428  
429 < bool SelectionCompiler::compileCommand(const std::vector<Token>& ltoken) {
429 >  bool SelectionCompiler::compileCommand(const std::vector<Token>& ltoken) {
430      const Token& tokenCommand = ltoken[0];
431      int tokCommand = tokenCommand.tok;
432  
433      atokenCommand = ltoken;
434      if ((tokCommand & Token::expressionCommand) != 0 && !compileExpression()) {
435 <        return false;
435 >      return false;
436      }
437      
438      return true;
439 < }
439 >  }
440  
441 < bool SelectionCompiler::compileExpression() {
441 >  bool SelectionCompiler::compileExpression() {
442      /** todo */
443      int i = 1;
444      int tokCommand = atokenCommand[0].tok;
445      if (tokCommand == Token::define) {
446 <        i = 2;
446 >      i = 2;
447      } else if ((tokCommand & Token::embeddedExpression) != 0) {
448 <        // look for the open parenthesis
449 <        while (i < atokenCommand.size() &&
450 <         atokenCommand[i].tok != Token::leftparen)
448 >      // look for the open parenthesis
449 >      while (i < atokenCommand.size() &&
450 >             atokenCommand[i].tok != Token::leftparen)
451          ++i;
452      }
453  
454      if (i >= atokenCommand.size()) {
455 <        return true;
455 >      return true;
456      }
457      return compileExpression(i);
458    }
459  
460                    
461 < bool SelectionCompiler::addTokenToPostfix(const Token& token) {
461 >  bool SelectionCompiler::addTokenToPostfix(const Token& token) {
462      ltokenPostfix.push_back(token);
463      return true;
464 < }
464 >  }
465  
466 < bool SelectionCompiler::compileExpression(int itoken) {
466 >  bool SelectionCompiler::compileExpression(int itoken) {
467      ltokenPostfix.clear();
468      for (int i = 0; i < itoken; ++i) {
469 <        addTokenToPostfix(atokenCommand[i]);
469 >      addTokenToPostfix(atokenCommand[i]);
470      }
471      
472      atokenInfix = atokenCommand;
# Line 484 | Line 474 | bool SelectionCompiler::compileExpression(int itoken)
474  
475      addTokenToPostfix(Token::tokenExpressionBegin);
476      if (!clauseOr()) {
477 <        return false;
477 >      return false;
478      }
479      
480      addTokenToPostfix(Token::tokenExpressionEnd);
481      if (itokenInfix != atokenInfix.size()) {
482 <        return endOfExpressionExpected();
482 >      return endOfExpressionExpected();
483      }
484  
485      atokenCommand = ltokenPostfix;
486      return true;
487 < }
487 >  }
488  
489 < Token SelectionCompiler::tokenNext() {
489 >  Token SelectionCompiler::tokenNext() {
490      if (itokenInfix == atokenInfix.size()) {
491 <        return Token();
491 >      return Token();
492      }
493      return atokenInfix[itokenInfix++];
494 < }
494 >  }
495  
496 < boost::any SelectionCompiler::valuePeek() {
496 >  boost::any SelectionCompiler::valuePeek() {
497      if (itokenInfix == atokenInfix.size()) {
498 <        return boost::any();
498 >      return boost::any();
499      } else {
500 <        return atokenInfix[itokenInfix].value;
500 >      return atokenInfix[itokenInfix].value;
501      }
502 < }
502 >  }
503  
504 < int SelectionCompiler::tokPeek() {
504 >  int SelectionCompiler::tokPeek() {
505      if (itokenInfix == atokenInfix.size()) {
506 <        return 0;
506 >      return 0;
507      }else {
508 <        return atokenInfix[itokenInfix].tok;
508 >      return atokenInfix[itokenInfix].tok;
509      }
510 < }
510 >  }
511  
512 < bool SelectionCompiler::clauseOr() {
512 >  bool SelectionCompiler::clauseOr() {
513      if (!clauseAnd()) {
514 <        return false;
514 >      return false;
515      }
516      
517      while (tokPeek() == Token::opOr) {
518 <        Token tokenOr = tokenNext();
519 <        if (!clauseAnd()) {
520 <            return false;
521 <        }
522 <        addTokenToPostfix(tokenOr);
518 >      Token tokenOr = tokenNext();
519 >      if (!clauseAnd()) {
520 >        return false;
521 >      }
522 >      addTokenToPostfix(tokenOr);
523      }
524      return true;
525 < }
525 >  }
526  
527 < bool SelectionCompiler::clauseAnd() {
527 >  bool SelectionCompiler::clauseAnd() {
528      if (!clauseNot()) {
529 <        return false;
529 >      return false;
530      }
531  
532      while (tokPeek() == Token::opAnd) {
533 <        Token tokenAnd = tokenNext();
534 <        if (!clauseNot()) {
535 <            return false;
536 <        }
537 <        addTokenToPostfix(tokenAnd);
533 >      Token tokenAnd = tokenNext();
534 >      if (!clauseNot()) {
535 >        return false;
536 >      }
537 >      addTokenToPostfix(tokenAnd);
538      }
539      return true;
540 < }
540 >  }
541  
542 < bool SelectionCompiler::clauseNot() {
542 >  bool SelectionCompiler::clauseNot() {
543      if (tokPeek() == Token::opNot) {
544 <        Token tokenNot = tokenNext();
545 <        if (!clauseNot()) {
546 <            return false;
547 <        }
548 <        return addTokenToPostfix(tokenNot);
544 >      Token tokenNot = tokenNext();
545 >      if (!clauseNot()) {
546 >        return false;
547 >      }
548 >      return addTokenToPostfix(tokenNot);
549      }
550      return clausePrimitive();
551 < }
551 >  }
552  
553 < bool SelectionCompiler::clausePrimitive() {
553 >  bool SelectionCompiler::clausePrimitive() {
554      int tok = tokPeek();
555      switch (tok) {
556 <        case Token::within:
557 <            return clauseWithin();
556 >    case Token::within:
557 >      return clauseWithin();
558  
559 <        case Token::asterisk:
560 <        case Token::identifier:
561 <            return clauseChemObjName();
559 >    case Token::asterisk:
560 >    case Token::identifier:
561 >      return clauseChemObjName();
562  
563 <        case Token::integer :
564 <            return clauseIndex();
565 <        default:
566 <            if ((tok & Token::atomproperty) == Token::atomproperty) {
567 <                return clauseComparator();
568 <            }
569 <            if ((tok & Token::predefinedset) != Token::predefinedset) {
570 <                break;
571 <            }
572 <            // fall into the code and below and just add the token
573 <        case Token::all:
574 <        case Token::none:
575 <            return addTokenToPostfix(tokenNext());
576 <        case Token::leftparen:
577 <            tokenNext();
578 <            if (!clauseOr()) {
579 <                return false;
580 <            }
581 <            if (tokenNext().tok != Token::rightparen) {
582 <                return rightParenthesisExpected();
583 <            }
584 <            return true;
563 >    case Token::integer :
564 >      return clauseIndex();
565 >    default:
566 >      if ((tok & Token::atomproperty) == Token::atomproperty) {
567 >        return clauseComparator();
568 >      }
569 >      if ((tok & Token::predefinedset) != Token::predefinedset) {
570 >        break;
571 >      }
572 >      // fall into the code and below and just add the token
573 >    case Token::all:
574 >    case Token::none:
575 >    case Token::hull:
576 >      return addTokenToPostfix(tokenNext());
577 >    case Token::leftparen:
578 >      tokenNext();
579 >      if (!clauseOr()) {
580 >        return false;
581 >      }
582 >      if (tokenNext().tok != Token::rightparen) {
583 >        return rightParenthesisExpected();
584 >      }
585 >      return true;
586      }
587      return unrecognizedExpressionToken();
588 < }
588 >  }
589  
590 < bool SelectionCompiler::clauseComparator() {
590 >  bool SelectionCompiler::clauseComparator() {
591      Token tokenAtomProperty = tokenNext();
592      Token tokenComparator = tokenNext();
593      if ((tokenComparator.tok & Token::comparator) == 0) {
594 <        return comparisonOperatorExpected();
594 >      return comparisonOperatorExpected();
595      }
596  
597      Token tokenValue = tokenNext();
598      if (tokenValue.tok != Token::integer && tokenValue.tok != Token::decimal) {
599 <        return numberExpected();
599 >      return numberExpected();
600      }
601      
602      float val;
603      if (tokenValue.value.type() == typeid(int)) {
604 <        val = boost::any_cast<int>(tokenValue.value);
604 >      val = boost::any_cast<int>(tokenValue.value);
605      } else if (tokenValue.value.type() == typeid(float)) {
606 <        val = boost::any_cast<float>(tokenValue.value);
606 >      val = boost::any_cast<float>(tokenValue.value);
607      } else {
608 <        return false;
608 >      return false;
609      }
610  
611      boost::any floatVal;
612      floatVal = val;
613      return addTokenToPostfix(Token(tokenComparator.tok,
614 <                       tokenAtomProperty.tok, floatVal));
615 < }
614 >                                   tokenAtomProperty.tok, floatVal));
615 >  }
616  
617 < bool SelectionCompiler::clauseWithin() {
617 >  bool SelectionCompiler::clauseWithin() {
618      tokenNext();                             // WITHIN
619      if (tokenNext().tok != Token::leftparen) {  // (
620 <        return leftParenthesisExpected();
620 >      return leftParenthesisExpected();
621      }
622      
623      boost::any distance;
624      Token tokenDistance = tokenNext();       // distance
625      switch(tokenDistance.tok) {
626 <        case Token::integer:
627 <        case Token::decimal:
628 <            distance = tokenDistance.value;
629 <            break;
630 <        default:
631 <            return numberOrKeywordExpected();
626 >    case Token::integer:
627 >    case Token::decimal:
628 >      distance = tokenDistance.value;
629 >      break;
630 >    default:
631 >      return numberOrKeywordExpected();
632      }
633  
634      if (tokenNext().tok != Token::opOr) {       // ,
635 <        return commaExpected();
635 >      return commaExpected();
636      }
637      
638      if (! clauseOr()) {                        // *expression*
639 <        return false;
639 >      return false;
640      }
641      
642      if (tokenNext().tok != Token::rightparen) { // )T
643 <        return rightParenthesisExpected();
643 >      return rightParenthesisExpected();
644      }
645      
646      return addTokenToPostfix(Token(Token::within, distance));
647 < }
647 >  }
648  
649 < bool SelectionCompiler::clauseChemObjName() {
650 <    std::string chemObjName;
651 <    int tok = tokPeek();
661 <    if (!clauseName(chemObjName)){
662 <        return false;
663 <    }
649 >  bool SelectionCompiler::clauseChemObjName() {
650 >    Token token = tokenNext();
651 >    if (token.tok == Token::identifier && token.value.type() == typeid(std::string)) {
652  
653 +      std::string name = boost::any_cast<std::string>(token.value);
654 +      if (isNameValid(name)) {
655 +        return addTokenToPostfix(Token(Token::name, name));
656 +      } else {
657 +        return compileError("invalid name: " + name);
658 +      }
659 +    }
660  
661 <    tok = tokPeek();
662 <    //allow two dot at most
663 <    if (tok == Token::dot) {
669 <        tokenNext();
670 <        chemObjName += ".";
671 <        if (!clauseName(chemObjName)) {
672 <            return false;
673 <        }
674 <        tok = tokPeek();
675 <        if (tok == Token::dot) {
676 <            tokenNext();
677 <            chemObjName += ".";
661 >    return false;
662 >        
663 >  }
664  
665 <            if (!clauseName(chemObjName)) {
666 <                return false;
667 <            }
668 <        }        
669 <    }
665 >  bool SelectionCompiler::isNameValid(const std::string& name) {
666 >    int nbracket = 0;
667 >    int ndot = 0;
668 >    for (int i =0 ; i < name.size(); ++i) {
669 >      switch(name[i]) {
670  
671 <    return addTokenToPostfix(Token(Token::name, chemObjName));
672 < }
673 <
674 < bool SelectionCompiler:: clauseName(std::string& name) {
675 <
676 <    int tok = tokPeek();
677 <
678 <    if (tok == Token::asterisk || tok == Token::identifier || tok == Token::integer) {
679 <
680 <        Token token = tokenNext();
695 <        if (token.value.type() == typeid(std::string)) {
696 <            name += boost::any_cast<std::string>(token.value);
697 <        } else if (token.value.type() == typeid(int)){
698 <            int intVal = boost::any_cast<int>(token.value);
699 <            char buffer[255];
700 <            sprintf(buffer,"%d", intVal);
701 <            name += buffer; /** @todo */
702 <            //name += toString<int>(intVal);
703 <        }
704 <        while(true){
705 <            tok = tokPeek();
706 <            switch (tok) {
707 <                case Token::asterisk :
708 <                    name += "*";
709 <                    tokenNext();
710 <                    break;
711 <                case Token::identifier :
712 <                    name += boost::any_cast<std::string>(tokenNext().value);
713 <                    break;
714 <                case Token::integer :
715 <                    name += toString(boost::any_cast<int>(tokenNext().value));
716 <                    break;
717 <                case Token::dot :
718 <                    return true;
719 <                default :
720 <                    return true;
721 <            }
722 <        }
723 <        
724 <    }else {
725 <        return false;
671 >      case '[' :
672 >        ++nbracket;
673 >        break;
674 >      case ']' :
675 >        --nbracket;
676 >        break;
677 >      case '.' :
678 >        ++ndot;
679 >        break;      
680 >      }
681      }
682  
683 < }
683 >    //only allow 3 dots at most
684 >    return (ndot <=3 && nbracket == 0) ? true : false;
685 >  }
686  
687 < bool SelectionCompiler::clauseIndex(){
687 >  bool SelectionCompiler::clauseIndex(){
688      Token token = tokenNext();
689      if (token.tok == Token::integer) {
690 <        int index = boost::any_cast<int>(token.value);
691 <        int tok = tokPeek();
692 <        std::cout << "Token::to is " << Token::to << ", tok = " << tok << std::endl;
693 <        if (tok == Token::to) {
694 <            tokenNext();
695 <            tok = tokPeek();
696 <            if (tok != Token::integer) {
697 <                return numberExpected();
698 <            }
690 >      int index = boost::any_cast<int>(token.value);
691 >      int tok = tokPeek();
692 >      std::cout << "Token::to is " << Token::to << ", tok = " << tok << std::endl;
693 >      if (tok == Token::to) {
694 >        tokenNext();
695 >        tok = tokPeek();
696 >        if (tok != Token::integer) {
697 >          return numberExpected();
698 >        }
699              
700 <            boost::any intVal = tokenNext().value;
701 <            int first = index;
702 <            if (intVal.type() != typeid(int)){
703 <                return false;
704 <            }
705 <            int second = boost::any_cast<int>(intVal);
700 >        boost::any intVal = tokenNext().value;
701 >        int first = index;
702 >        if (intVal.type() != typeid(int)){
703 >          return false;
704 >        }
705 >        int second = boost::any_cast<int>(intVal);
706  
707 <            return addTokenToPostfix(Token(Token::index, boost::any(std::make_pair(first, second))));
707 >        return addTokenToPostfix(Token(Token::index, boost::any(std::make_pair(first, second))));
708              
709 <        }else {
710 <            return addTokenToPostfix(Token(Token::index, boost::any(index)));
711 <        }
709 >      }else {
710 >        return addTokenToPostfix(Token(Token::index, boost::any(index)));
711 >      }
712      } else {
713 <        return numberExpected();
713 >      return numberExpected();
714      }
715 < }
715 >  }
716  
717   }

Comparing trunk/src/selection/SelectionCompiler.cpp (property svn:keywords):
Revision 303 by tim, Mon Feb 7 22:36:32 2005 UTC vs.
Revision 1523 by kstocke1, Fri Nov 19 20:27:02 2010 UTC

# Line 0 | Line 1
1 + Author Id Revision Date

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines