ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/selection/SelectionCompiler.cpp
Revision: 1364
Committed: Wed Oct 7 20:49:50 2009 UTC (15 years, 6 months ago) by cli2
Original Path: trunk/src/selection/SelectionCompiler.cpp
File size: 18307 byte(s)
Log Message:
Bug fixes in the SelectionEvaluator and SelectionCompiler
Added print option in Restraints

File Contents

# User Rev Content
1 tim 279 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
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
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40     */
41    
42     #include "selection/SelectionCompiler.hpp"
43 tim 281 #include "utils/StringUtils.hpp"
44 tim 279 namespace oopse {
45    
46 cli2 1364 bool SelectionCompiler::compile(const std::string& filename,
47     const std::string& script) {
48 tim 279
49     this->filename = filename;
50     this->script = script;
51     lineNumbers.clear();
52     lineIndices.clear();
53     aatokenCompiled.clear();
54    
55 tim 281 if (internalCompile()) {
56 gezelter 507 return true;
57 tim 279 }
58    
59     int icharEnd;
60 tim 281 if ((icharEnd = script.find('\r', ichCurrentCommand)) == std::string::npos &&
61     (icharEnd = script.find('\n', ichCurrentCommand)) == std::string::npos) {
62 gezelter 507 icharEnd = script.size();
63 tim 279 }
64     errorLine = script.substr(ichCurrentCommand, icharEnd);
65     return false;
66 gezelter 507 }
67 tim 279
68 gezelter 507 bool SelectionCompiler::internalCompile(){
69 tim 279
70     cchScript = script.size();
71     ichToken = 0;
72     lineCurrent = 1;
73    
74     error = false;
75    
76 tim 281 //std::vector<Token> lltoken;
77     aatokenCompiled.clear();
78 tim 279 std::vector<Token> ltoken;
79    
80 tim 281 Token tokenCommand;
81     int tokCommand = Token::nada;
82 tim 279
83     for ( ; true; ichToken += cchToken) {
84 gezelter 507 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 tim 279
101 gezelter 507 if (ichToken < cchScript) {
102     if (endOfLine)
103     ++lineCurrent;
104     continue;
105     }
106     break;
107     }
108 tim 279
109 gezelter 507 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 tim 295
128 gezelter 507 int val = lexi_cast<int>(script.substr(ichToken, cchToken));
129     ltoken.push_back(Token(Token::integer, boost::any(val)));
130     continue;
131     }
132     }
133 tim 279
134 gezelter 507 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 tim 279
144 gezelter 507 int tok = token.tok;
145 tim 279
146 gezelter 507 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 tim 279
155 gezelter 507 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 tim 279
168 gezelter 507 break;
169 tim 279
170 gezelter 507 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 tim 279
179 gezelter 507 if (ltoken.size() == 0) {
180     return commandExpected();
181     }
182 tim 279
183 gezelter 507 return unrecognizedToken();
184 tim 279 }
185    
186     return true;
187     }
188    
189    
190     bool SelectionCompiler::lookingAtLeadingWhitespace() {
191    
192     int ichT = ichToken;
193     while (ichT < cchScript && std::isspace(script[ichT])) {
194     ++ichT;
195     }
196     cchToken = ichT - ichToken;
197     return cchToken > 0;
198     }
199    
200     bool SelectionCompiler::lookingAtEndOfLine() {
201     if (ichToken == cchScript)
202     return true;
203     int ichT = ichToken;
204     char ch = script[ichT];
205     if (ch == '\r') {
206     ++ichT;
207     if (ichT < cchScript && script[ichT] == '\n')
208 gezelter 507 ++ichT;
209 tim 279 } else if (ch == '\n') {
210     ++ichT;
211     } else {
212     return false;
213     }
214     cchToken = ichT - ichToken;
215     return true;
216     }
217    
218     bool SelectionCompiler::lookingAtEndOfStatement() {
219     if (ichToken == cchScript || script[ichToken] != ';')
220     return false;
221     cchToken = 1;
222     return true;
223     }
224    
225     bool SelectionCompiler::lookingAtString() {
226     if (ichToken == cchScript)
227     return false;
228     if (script[ichToken] != '"')
229     return false;
230     // remove support for single quote
231     // in order to use it in atom expressions
232     // char chFirst = script.charAt(ichToken);
233     // if (chFirst != '"' && chFirst != '\'')
234     // return false;
235     int ichT = ichToken + 1;
236     // while (ichT < cchScript && script.charAt(ichT++) != chFirst)
237     char ch;
238 tim 281 bool previousCharBackslash = false;
239 tim 279 while (ichT < cchScript) {
240 tim 281 ch = script[ichT++];
241 tim 279 if (ch == '"' && !previousCharBackslash)
242     break;
243     previousCharBackslash = ch == '\\' ? !previousCharBackslash : false;
244     }
245     cchToken = ichT - ichToken;
246 tim 295
247 tim 279 return true;
248     }
249    
250    
251 gezelter 507 std::string SelectionCompiler::getUnescapedStringLiteral() {
252 tim 281 /** @todo */
253     std::string sb(cchToken - 2, ' ');
254    
255 tim 279 int ichMax = ichToken + cchToken - 1;
256     int ich = ichToken + 1;
257    
258     while (ich < ichMax) {
259 gezelter 507 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 tim 279 }
299    
300 tim 281 return sb;
301 gezelter 507 }
302 tim 279
303 gezelter 507 int SelectionCompiler::getHexitValue(char ch) {
304 tim 279 if (ch >= '0' && ch <= '9')
305 gezelter 507 return ch - '0';
306 tim 279 else if (ch >= 'a' && ch <= 'f')
307 gezelter 507 return 10 + ch - 'a';
308 tim 279 else if (ch >= 'A' && ch <= 'F')
309 gezelter 507 return 10 + ch - 'A';
310 tim 279 else
311 gezelter 507 return -1;
312     }
313 tim 279
314 gezelter 507 bool SelectionCompiler::lookingAtSpecialString() {
315 tim 279 int ichT = ichToken;
316     char ch = script[ichT];
317     while (ichT < cchScript && ch != ';' && ch != '\r' && ch != '\n') {
318 gezelter 507 ++ichT;
319 tim 279 }
320     cchToken = ichT - ichToken;
321     return cchToken > 0;
322 gezelter 507 }
323 tim 279
324 gezelter 507 bool SelectionCompiler::lookingAtDecimal(bool allowNegative) {
325 tim 279 if (ichToken == cchScript) {
326 gezelter 507 return false;
327 tim 279 }
328    
329     int ichT = ichToken;
330     if (script[ichT] == '-') {
331 gezelter 507 ++ichT;
332 tim 279 }
333 tim 281 bool digitSeen = false;
334 tim 279 char ch = 'X';
335     while (ichT < cchScript && std::isdigit(ch = script[ichT])) {
336 gezelter 507 ++ichT;
337     digitSeen = true;
338 tim 279 }
339    
340     if (ichT == cchScript || ch != '.') {
341 gezelter 507 return false;
342 tim 279 }
343    
344 tim 303 // to support DMPC.1, let's check the character before the dot
345     if (ch == '.' && (ichT > 0) && std::isalpha(script[ichT - 1])) {
346 gezelter 507 return false;
347 tim 279 }
348    
349     ++ichT;
350     while (ichT < cchScript && std::isdigit(script[ichT])) {
351 gezelter 507 ++ichT;
352     digitSeen = true;
353 tim 279 }
354     cchToken = ichT - ichToken;
355     return digitSeen;
356 gezelter 507 }
357 tim 279
358 gezelter 507 bool SelectionCompiler::lookingAtInteger(bool allowNegative) {
359 tim 279 if (ichToken == cchScript) {
360 gezelter 507 return false;
361 tim 279 }
362     int ichT = ichToken;
363     if (allowNegative && script[ichToken] == '-') {
364 gezelter 507 ++ichT;
365 tim 279 }
366     int ichBeginDigits = ichT;
367     while (ichT < cchScript && std::isdigit(script[ichT])) {
368 gezelter 507 ++ichT;
369 tim 279 }
370     if (ichBeginDigits == ichT) {
371 gezelter 507 return false;
372 tim 279 }
373     cchToken = ichT - ichToken;
374     return true;
375 gezelter 507 }
376 tim 279
377 gezelter 507 bool SelectionCompiler::lookingAtLookupToken() {
378 tim 279 if (ichToken == cchScript) {
379 gezelter 507 return false;
380 tim 279 }
381    
382     int ichT = ichToken;
383     char ch;
384     switch (ch = script[ichT++]) {
385 gezelter 507 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 tim 288
419 gezelter 507 ++ichT;
420     }
421     break;
422 tim 279 }
423 tim 295
424 tim 279 cchToken = ichT - ichToken;
425 tim 295
426 tim 279 return true;
427 gezelter 507 }
428 tim 279
429 gezelter 507 bool SelectionCompiler::compileCommand(const std::vector<Token>& ltoken) {
430 tim 281 const Token& tokenCommand = ltoken[0];
431 tim 279 int tokCommand = tokenCommand.tok;
432 tim 281
433     atokenCommand = ltoken;
434     if ((tokCommand & Token::expressionCommand) != 0 && !compileExpression()) {
435 gezelter 507 return false;
436 tim 279 }
437 tim 281
438 tim 279 return true;
439 gezelter 507 }
440 tim 279
441 gezelter 507 bool SelectionCompiler::compileExpression() {
442 tim 279 /** todo */
443     int i = 1;
444     int tokCommand = atokenCommand[0].tok;
445 tim 281 if (tokCommand == Token::define) {
446 gezelter 507 i = 2;
447 tim 281 } else if ((tokCommand & Token::embeddedExpression) != 0) {
448 gezelter 507 // look for the open parenthesis
449     while (i < atokenCommand.size() &&
450     atokenCommand[i].tok != Token::leftparen)
451 tim 279 ++i;
452     }
453 tim 281
454     if (i >= atokenCommand.size()) {
455 gezelter 507 return true;
456 tim 281 }
457 tim 279 return compileExpression(i);
458     }
459    
460    
461 gezelter 507 bool SelectionCompiler::addTokenToPostfix(const Token& token) {
462 tim 279 ltokenPostfix.push_back(token);
463     return true;
464 gezelter 507 }
465 tim 279
466 gezelter 507 bool SelectionCompiler::compileExpression(int itoken) {
467 tim 281 ltokenPostfix.clear();
468     for (int i = 0; i < itoken; ++i) {
469 gezelter 507 addTokenToPostfix(atokenCommand[i]);
470 tim 281 }
471    
472 tim 279 atokenInfix = atokenCommand;
473     itokenInfix = itoken;
474    
475 tim 281 addTokenToPostfix(Token::tokenExpressionBegin);
476 tim 279 if (!clauseOr()) {
477 gezelter 507 return false;
478 tim 279 }
479    
480 tim 281 addTokenToPostfix(Token::tokenExpressionEnd);
481     if (itokenInfix != atokenInfix.size()) {
482 gezelter 507 return endOfExpressionExpected();
483 tim 279 }
484    
485     atokenCommand = ltokenPostfix;
486     return true;
487 gezelter 507 }
488 tim 279
489 gezelter 507 Token SelectionCompiler::tokenNext() {
490 tim 281 if (itokenInfix == atokenInfix.size()) {
491 gezelter 507 return Token();
492 tim 281 }
493     return atokenInfix[itokenInfix++];
494 gezelter 507 }
495 tim 279
496 gezelter 507 boost::any SelectionCompiler::valuePeek() {
497 tim 281 if (itokenInfix == atokenInfix.size()) {
498 gezelter 507 return boost::any();
499 tim 279 } else {
500 gezelter 507 return atokenInfix[itokenInfix].value;
501 tim 279 }
502 gezelter 507 }
503 tim 279
504 gezelter 507 int SelectionCompiler::tokPeek() {
505 tim 281 if (itokenInfix == atokenInfix.size()) {
506 gezelter 507 return 0;
507 tim 279 }else {
508 gezelter 507 return atokenInfix[itokenInfix].tok;
509 tim 279 }
510 gezelter 507 }
511 tim 279
512 gezelter 507 bool SelectionCompiler::clauseOr() {
513 tim 279 if (!clauseAnd()) {
514 gezelter 507 return false;
515 tim 279 }
516    
517 tim 281 while (tokPeek() == Token::opOr) {
518 gezelter 507 Token tokenOr = tokenNext();
519     if (!clauseAnd()) {
520     return false;
521     }
522     addTokenToPostfix(tokenOr);
523 tim 279 }
524     return true;
525 gezelter 507 }
526 tim 279
527 gezelter 507 bool SelectionCompiler::clauseAnd() {
528 tim 279 if (!clauseNot()) {
529 gezelter 507 return false;
530 tim 279 }
531    
532 tim 281 while (tokPeek() == Token::opAnd) {
533 gezelter 507 Token tokenAnd = tokenNext();
534     if (!clauseNot()) {
535     return false;
536     }
537     addTokenToPostfix(tokenAnd);
538 tim 279 }
539     return true;
540 gezelter 507 }
541 tim 279
542 gezelter 507 bool SelectionCompiler::clauseNot() {
543 tim 281 if (tokPeek() == Token::opNot) {
544 gezelter 507 Token tokenNot = tokenNext();
545     if (!clauseNot()) {
546     return false;
547     }
548     return addTokenToPostfix(tokenNot);
549 tim 279 }
550     return clausePrimitive();
551 gezelter 507 }
552 tim 279
553 gezelter 507 bool SelectionCompiler::clausePrimitive() {
554 tim 279 int tok = tokPeek();
555     switch (tok) {
556 gezelter 507 case Token::within:
557     return clauseWithin();
558 tim 283
559 gezelter 507 case Token::asterisk:
560     case Token::identifier:
561     return clauseChemObjName();
562 tim 295
563 gezelter 507 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 tim 279 }
586     return unrecognizedExpressionToken();
587 gezelter 507 }
588 tim 279
589 gezelter 507 bool SelectionCompiler::clauseComparator() {
590 tim 279 Token tokenAtomProperty = tokenNext();
591     Token tokenComparator = tokenNext();
592 tim 281 if ((tokenComparator.tok & Token::comparator) == 0) {
593 gezelter 507 return comparisonOperatorExpected();
594 tim 279 }
595    
596     Token tokenValue = tokenNext();
597 tim 288 if (tokenValue.tok != Token::integer && tokenValue.tok != Token::decimal) {
598 gezelter 507 return numberExpected();
599 tim 279 }
600 tim 288
601     float val;
602     if (tokenValue.value.type() == typeid(int)) {
603 gezelter 507 val = boost::any_cast<int>(tokenValue.value);
604 tim 288 } else if (tokenValue.value.type() == typeid(float)) {
605 gezelter 507 val = boost::any_cast<float>(tokenValue.value);
606 tim 288 } else {
607 gezelter 507 return false;
608 tim 288 }
609    
610 tim 295 boost::any floatVal;
611     floatVal = val;
612 tim 281 return addTokenToPostfix(Token(tokenComparator.tok,
613 gezelter 507 tokenAtomProperty.tok, floatVal));
614     }
615 tim 279
616 gezelter 507 bool SelectionCompiler::clauseWithin() {
617 tim 279 tokenNext(); // WITHIN
618 tim 281 if (tokenNext().tok != Token::leftparen) { // (
619 gezelter 507 return leftParenthesisExpected();
620 tim 279 }
621    
622 tim 281 boost::any distance;
623 tim 279 Token tokenDistance = tokenNext(); // distance
624     switch(tokenDistance.tok) {
625 gezelter 507 case Token::integer:
626     case Token::decimal:
627     distance = tokenDistance.value;
628     break;
629     default:
630     return numberOrKeywordExpected();
631 tim 279 }
632    
633 tim 281 if (tokenNext().tok != Token::opOr) { // ,
634 gezelter 507 return commaExpected();
635 tim 279 }
636    
637     if (! clauseOr()) { // *expression*
638 gezelter 507 return false;
639 tim 279 }
640    
641 tim 281 if (tokenNext().tok != Token::rightparen) { // )T
642 gezelter 507 return rightParenthesisExpected();
643 tim 279 }
644    
645 tim 281 return addTokenToPostfix(Token(Token::within, distance));
646 gezelter 507 }
647 tim 279
648 gezelter 507 bool SelectionCompiler::clauseChemObjName() {
649 tim 452 Token token = tokenNext();
650     if (token.tok == Token::identifier && token.value.type() == typeid(std::string)) {
651 tim 279
652 gezelter 507 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 tim 452 }
659 tim 288
660 tim 452 return false;
661    
662 gezelter 507 }
663 tim 279
664 gezelter 507 bool SelectionCompiler::isNameValid(const std::string& name) {
665     int nbracket = 0;
666 tim 452 int ndot = 0;
667     for (int i =0 ; i < name.size(); ++i) {
668 gezelter 507 switch(name[i]) {
669 tim 283
670 gezelter 507 case '[' :
671     ++nbracket;
672     break;
673     case ']' :
674     --nbracket;
675     break;
676     case '.' :
677     ++ndot;
678     break;
679     }
680 tim 283 }
681    
682 tim 452 //only allow 3 dots at most
683     return (ndot <=3 && nbracket == 0) ? true : false;
684 gezelter 507 }
685 tim 279
686 gezelter 507 bool SelectionCompiler::clauseIndex(){
687 tim 295 Token token = tokenNext();
688     if (token.tok == Token::integer) {
689 gezelter 507 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 tim 295
699 gezelter 507 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 tim 283
706 gezelter 507 return addTokenToPostfix(Token(Token::index, boost::any(std::make_pair(first, second))));
707 tim 295
708 gezelter 507 }else {
709     return addTokenToPostfix(Token(Token::index, boost::any(index)));
710     }
711 tim 295 } else {
712 gezelter 507 return numberExpected();
713 tim 295 }
714 gezelter 507 }
715 tim 295
716     }

Properties

Name Value
svn:executable *