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

Comparing:
trunk/src/selection/SelectionCompiler.cpp (file contents), Revision 288 by tim, Fri Feb 4 22:39:26 2005 UTC vs.
branches/development/src/selection/SelectionCompiler.cpp (file contents), Revision 1465 by chuckv, Fri Jul 9 23:08:25 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, ichToken + cchToken));          
123 <                ltoken.push_back(Token(Token::decimal, value));/**@todo*/
124 <                continue;
125 <            }
126 <            if (lookingAtInteger((tokCommand & Token::negnums) != 0)) {
127 <                std::string intString = script.substr(ichToken, ichToken + cchToken);
128 <                int val = lexi_cast<int>(intString);
129 <                ltoken.push_back(Token(Token::integer, val, intString));/**@todo*/
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 <            }
142 <            
143 <            int tok = token.tok;
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 >          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 >        }
143              
144 <            switch (tokCommand) {
145 <                case Token::nada:
146 <                    ichCurrentCommand = ichToken;
147 <                    //tokenCommand = token;
148 <                    tokCommand = tok;
149 <                    if ((tokCommand & Token::command) == 0)
150 <                    return commandExpected();
151 <                    break;
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;
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 204 | 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 242 | Line 243 | bool SelectionCompiler::internalCompile(){
243        previousCharBackslash = ch == '\\' ? !previousCharBackslash : false;
244      }
245      cchToken = ichT - ichToken;
246 +
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 254 | 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 1.ca, let's check the character after the dot
345 <    // to determine if it is an alpha
346 <    if (ch == '.' && (ichT + 1 < cchScript) && std::isalpha(script[ichT + 1])) {
345 <        return false;
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;
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:
418 <            if ((ch < 'a' || ch > 'z') && (ch < 'A' && ch > 'Z') && ch != '_') {
419 <                return false;
420 <            }
421 <        case '?': // include question marks in identifier for atom expressions
421 <            while (ichT < cchScript && !std::isspace(ch = script[ichT]) && (std::isalpha(ch) ||std::isdigit(ch) ||
422 <                ch == '_' || ch == '?') ) {
423 <
424 <                ++ichT;
425 <            }
426 <        break;
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;
422      }
423 +
424      cchToken = ichT - ichToken;
425 +
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 477 | 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();
562 <      
563 <        default:
564 <            if ((tok & Token::atomproperty) == Token::atomproperty) {
565 <                return clauseComparator();
566 <            }
567 <            if ((tok & Token::predefinedset) != Token::predefinedset) {
568 <                break;
569 <            }
570 <            // fall into the code and below and just add the token
571 <        case Token::all:
572 <        case Token::none:
573 <            return addTokenToPostfix(tokenNext());
574 <        case Token::leftparen:
575 <            tokenNext();
576 <            if (!clauseOr()) {
577 <                return false;
578 <            }
579 <            if (tokenNext().tok != Token::rightparen) {
580 <                return rightParenthesisExpected();
581 <            }
582 <            return true;
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;
585      }
586      return unrecognizedExpressionToken();
587 < }
587 >  }
588  
589 < bool SelectionCompiler::clauseComparator() {
589 >  bool SelectionCompiler::clauseComparator() {
590      Token tokenAtomProperty = tokenNext();
591      Token tokenComparator = tokenNext();
592      if ((tokenComparator.tok & Token::comparator) == 0) {
593 <        return comparisonOperatorExpected();
593 >      return comparisonOperatorExpected();
594      }
595  
596      Token tokenValue = tokenNext();
597      if (tokenValue.tok != Token::integer && tokenValue.tok != Token::decimal) {
598 <        return numberExpected();
598 >      return numberExpected();
599      }
600      
601      float val;
602      if (tokenValue.value.type() == typeid(int)) {
603 <        val = boost::any_cast<int>(tokenValue.value);
603 >      val = boost::any_cast<int>(tokenValue.value);
604      } else if (tokenValue.value.type() == typeid(float)) {
605 <        val = boost::any_cast<float>(tokenValue.value);
605 >      val = boost::any_cast<float>(tokenValue.value);
606      } else {
607 <        return false;
607 >      return false;
608      }
609  
610 +    boost::any floatVal;
611 +    floatVal = val;
612      return addTokenToPostfix(Token(tokenComparator.tok,
613 <                       tokenAtomProperty.tok, boost::any(val)));
614 < }
613 >                                   tokenAtomProperty.tok, floatVal));
614 >  }
615  
616 < bool SelectionCompiler::clauseWithin() {
616 >  bool SelectionCompiler::clauseWithin() {
617      tokenNext();                             // WITHIN
618      if (tokenNext().tok != Token::leftparen) {  // (
619 <        return leftParenthesisExpected();
619 >      return leftParenthesisExpected();
620      }
621      
622      boost::any distance;
623      Token tokenDistance = tokenNext();       // distance
624      switch(tokenDistance.tok) {
625 <        case Token::integer:
626 <            distance = float(tokenDistance.intValue);
627 <            break;
628 <        case Token::decimal:
629 <            distance = tokenDistance.value;
630 <            break;
630 <        default:
631 <            return numberOrKeywordExpected();
625 >    case Token::integer:
626 >    case Token::decimal:
627 >      distance = tokenDistance.value;
628 >      break;
629 >    default:
630 >      return numberOrKeywordExpected();
631      }
632  
633      if (tokenNext().tok != Token::opOr) {       // ,
634 <        return commaExpected();
634 >      return commaExpected();
635      }
636      
637      if (! clauseOr()) {                        // *expression*
638 <        return false;
638 >      return false;
639      }
640      
641      if (tokenNext().tok != Token::rightparen) { // )T
642 <        return rightParenthesisExpected();
642 >      return rightParenthesisExpected();
643      }
644      
645      return addTokenToPostfix(Token(Token::within, distance));
646 < }
646 >  }
647  
648 < bool SelectionCompiler::clauseChemObjName() {
649 <    std::string chemObjName;
650 <    int tok = tokPeek();
652 <    if (!clauseName(chemObjName)){
653 <        return false;
654 <    }
648 >  bool SelectionCompiler::clauseChemObjName() {
649 >    Token token = tokenNext();
650 >    if (token.tok == Token::identifier && token.value.type() == typeid(std::string)) {
651  
652 +      std::string name = boost::any_cast<std::string>(token.value);
653 +      if (isNameValid(name)) {
654 +        return addTokenToPostfix(Token(Token::name, name));
655 +      } else {
656 +        return compileError("invalid name: " + name);
657 +      }
658 +    }
659  
660 <    tok = tokPeek();
661 <    //allow two dot at most
662 <    if (tok == Token::dot) {
660 <        tokenNext();
661 <        chemObjName += ".";
662 <        if (!clauseName(chemObjName)) {
663 <            return false;
664 <        }
665 <        tok = tokPeek();
666 <        if (tok == Token::dot) {
667 <            tokenNext();
668 <            chemObjName += ".";
660 >    return false;
661 >        
662 >  }
663  
664 <            if (!clauseName(chemObjName)) {
665 <                return false;
666 <            }
667 <        }        
664 >  bool SelectionCompiler::isNameValid(const std::string& name) {
665 >    int nbracket = 0;
666 >    int ndot = 0;
667 >    for (int i =0 ; i < name.size(); ++i) {
668 >      switch(name[i]) {
669 >
670 >      case '[' :
671 >        ++nbracket;
672 >        break;
673 >      case ']' :
674 >        --nbracket;
675 >        break;
676 >      case '.' :
677 >        ++ndot;
678 >        break;      
679 >      }
680      }
681  
682 <    return addTokenToPostfix(Token(Token::name, chemObjName));
683 < }
682 >    //only allow 3 dots at most
683 >    return (ndot <=3 && nbracket == 0) ? true : false;
684 >  }
685  
686 < bool SelectionCompiler:: clauseName(std::string& name) {
686 >  bool SelectionCompiler::clauseIndex(){
687 >    Token token = tokenNext();
688 >    if (token.tok == Token::integer) {
689 >      int index = boost::any_cast<int>(token.value);
690 >      int tok = tokPeek();
691 >      std::cout << "Token::to is " << Token::to << ", tok = " << tok << std::endl;
692 >      if (tok == Token::to) {
693 >        tokenNext();
694 >        tok = tokPeek();
695 >        if (tok != Token::integer) {
696 >          return numberExpected();
697 >        }
698 >            
699 >        boost::any intVal = tokenNext().value;
700 >        int first = index;
701 >        if (intVal.type() != typeid(int)){
702 >          return false;
703 >        }
704 >        int second = boost::any_cast<int>(intVal);
705  
706 <    int tok = tokPeek();
707 <
708 <    if (tok == Token::asterisk || tok == Token::identifier) {
709 <        name += boost::any_cast<std::string>(tokenNext().value);
710 <        
711 <        while(true){
712 <            tok = tokPeek();
688 <            switch (tok) {
689 <                case Token::asterisk :
690 <                    name += "*";
691 <                    tokenNext();
692 <                    break;
693 <                case Token::identifier :
694 <                    name += boost::any_cast<std::string>(tokenNext().value);
695 <                    break;
696 <                case Token::integer :
697 <                    name += toString(boost::any_cast<int>(tokenNext().value));
698 <                    break;
699 <                case Token::dot :
700 <                    return true;
701 <                default :
702 <                    return true;
703 <            }
704 <        }
705 <        
706 <    }else {
707 <        return false;
706 >        return addTokenToPostfix(Token(Token::index, boost::any(std::make_pair(first, second))));
707 >            
708 >      }else {
709 >        return addTokenToPostfix(Token(Token::index, boost::any(index)));
710 >      }
711 >    } else {
712 >      return numberExpected();
713      }
714 +  }
715  
716   }
711
712
713 }

Comparing:
trunk/src/selection/SelectionCompiler.cpp (property svn:keywords), Revision 288 by tim, Fri Feb 4 22:39:26 2005 UTC vs.
branches/development/src/selection/SelectionCompiler.cpp (property svn:keywords), Revision 1465 by chuckv, Fri Jul 9 23:08:25 2010 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines