ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/selection/SelectionCompiler.cpp
Revision: 1963
Committed: Wed Feb 2 12:51:25 2005 UTC (19 years, 5 months ago) by tim
File size: 19659 byte(s)
Log Message:
add SelectionCompiler.cpp

File Contents

# Content
1 /*
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 namespace oopse {
44
45 bool SelectionCompiler::compile(const std::string& filename, const std::string& script) {
46
47 this->filename = filename;
48 this->script = script;
49 lineNumbers.clear();
50 lineIndices.clear();
51 aatokenCompiled.clear();
52
53 if (internalcompile()) {
54 return true;
55 }
56
57 int icharEnd;
58 if ((icharEnd = script.find('\r', ichCurrentCommand)) == std::string:npos &&
59 (icharEnd = script.find('\n', ichCurrentCommand)) == std::string:npos) {
60 icharEnd = script.size();
61 }
62 errorLine = script.substr(ichCurrentCommand, icharEnd);
63 return false;
64 }
65
66 bool SelectionCompiler::internalCompile(){
67
68 cchScript = script.size();
69 ichToken = 0;
70 lineCurrent = 1;
71
72 error = false;
73
74 std::vector<Token> lltoken;
75 std::vector<Token> ltoken;
76
77 //Token tokenCommand = null;
78 int tokCommand = Token.nada;
79
80 for ( ; true; ichToken += cchToken) {
81 if (lookingAtLeadingWhitespace())
82 continue;
83 if (lookingAtComment())
84 continue;
85 boolean endOfLine = lookingAtEndOfLine();
86 if (endOfLine || lookingAtEndOfStatement()) {
87 if (tokCommand != Token.nada) {
88 if (! compileCommand(ltoken)) {
89 return false;
90 }
91 lltoken.push_back(atokenCommand);
92 /** @todo*/
93 int iCommand = lltoken.size();
94 lineNumbers[iCommand] = lineCurrent;
95 lineIndices[iCommand] = (short) ichCurrentCommand;
96 ltoken.clear();
97 tokCommand = Token.nada;
98 }
99
100 if (ichToken < cchScript) {
101 if (endOfLine)
102 ++lineCurrent;
103 continue;
104 }
105 break;
106 }
107
108 if (tokCommand != Token.nada) {
109 if (lookingAtString()) {
110 std::string str = getUnescapedStringLiteral();
111 ltoken.push_back(Token(Token.string, str));
112 continue;
113 }
114 if ((tokCommand & Token.specialstring) != 0 &&
115 lookingAtSpecialString()) {
116 std::string str = script.substr(ichToken, ichToken + cchToken);
117 ltoken.push_back(Token(Token.string, str));
118 continue;
119 }
120 if (lookingAtDecimal((tokCommand & Token.negnums) != 0)) {
121 float value = lexi_cast<float>((script.substr(ichToken, ichToken + cchToken));
122 ltoken.push_back(Token(Token.decimal, new Float(value)));/**@todo*/
123 continue;
124 }
125 if (lookingAtInteger((tokCommand & Token.negnums) != 0)) {
126 std::string intString = script.substr(ichToken, ichToken + cchToken);
127 int val = lexi_cast<int>(intString);
128 ltoken.push_back(new Token(Token.integer, val, intString));/**@todo*/
129 continue;
130 }
131 }
132
133 if (lookingAtLookupToken()) {
134 std::string ident = script.subst(ichToken, ichToken + cchToken);
135
136 /**@todo */
137 Token token = (Token) Token.map.get(ident);
138 if (token == NULL) {
139
140 }
141 Token token(Token.identifier, ident);
142
143
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 && tok != Token.set &&
164 (tok & (Token.expression | Token.predefinedset)) == 0)
165 return invalidExpressionToken(ident);
166 }
167
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 }
178
179 if (ltoken.size() == 0) {
180 return commandExpected();
181 }
182
183 return unrecognizedToken();
184 }
185
186 aatokenCompiled.push_back(lltoken);
187 return true;
188 }
189
190
191 bool SelectionCompiler::lookingAtLeadingWhitespace() {
192
193 int ichT = ichToken;
194 while (ichT < cchScript && std::isspace(script[ichT])) {
195 ++ichT;
196 }
197 cchToken = ichT - ichToken;
198 return cchToken > 0;
199 }
200
201 bool SelectionCompiler::lookingAtEndOfLine() {
202 if (ichToken == cchScript)
203 return true;
204 int ichT = ichToken;
205 char ch = script[ichT];
206 if (ch == '\r') {
207 ++ichT;
208 if (ichT < cchScript && script[ichT] == '\n')
209 ++ichT;
210 } else if (ch == '\n') {
211 ++ichT;
212 } else {
213 return false;
214 }
215 cchToken = ichT - ichToken;
216 return true;
217 }
218
219 bool SelectionCompiler::lookingAtEndOfStatement() {
220 if (ichToken == cchScript || script[ichToken] != ';')
221 return false;
222 cchToken = 1;
223 return true;
224 }
225
226 bool SelectionCompiler::lookingAtString() {
227 if (ichToken == cchScript)
228 return false;
229 if (script[ichToken] != '"')
230 return false;
231 // remove support for single quote
232 // in order to use it in atom expressions
233 // char chFirst = script.charAt(ichToken);
234 // if (chFirst != '"' && chFirst != '\'')
235 // return false;
236 int ichT = ichToken + 1;
237 // while (ichT < cchScript && script.charAt(ichT++) != chFirst)
238 char ch;
239 boolean previousCharBackslash = false;
240 while (ichT < cchScript) {
241 ch = script.[ichT++];
242 if (ch == '"' && !previousCharBackslash)
243 break;
244 previousCharBackslash = ch == '\\' ? !previousCharBackslash : false;
245 }
246 cchToken = ichT - ichToken;
247 return true;
248 }
249
250
251 std::string SelectionCompiler::getUnescapedStringLiteral() {
252 StringBuffer sb = new StringBuffer(cchToken - 2);
253 int ichMax = ichToken + cchToken - 1;
254 int ich = ichToken + 1;
255
256 while (ich < ichMax) {
257 char ch = script[ich++];
258 if (ch == '\\' && ich < ichMax) {
259 ch = script[ich++];
260 switch (ch) {
261 case 'b':
262 ch = '\b';
263 break;
264 case 'n':
265 ch = '\n';
266 break;
267 case 't':
268 ch = '\t';
269 break;
270 case 'r':
271 ch = '\r';
272 // fall into
273 case '"':
274 case '\\':
275 case '\'':
276 break;
277 case 'x':
278 case 'u':
279 int digitCount = ch == 'x' ? 2 : 4;
280 if (ich < ichMax) {
281 int unicode = 0;
282 for (int k = digitCount; --k >= 0 && ich < ichMax; ) {
283 char chT = script[ich];
284 int hexit = getHexitValue(chT);
285 if (hexit < 0)
286 break;
287 unicode <<= 4;
288 unicode += hexit;
289 ++ich;
290 }
291 ch = (char)unicode;
292 }
293 }
294 }
295 sb.append(ch);
296 }
297
298 return "" + sb;
299 }
300
301 static int SelectionCompiler::getHexitValue(char ch) {
302 if (ch >= '0' && ch <= '9')
303 return ch - '0';
304 else if (ch >= 'a' && ch <= 'f')
305 return 10 + ch - 'a';
306 else if (ch >= 'A' && ch <= 'F')
307 return 10 + ch - 'A';
308 else
309 return -1;
310 }
311
312 bool SelectionCompiler::lookingAtSpecialString() {
313 int ichT = ichToken;
314 char ch = script[ichT];
315 while (ichT < cchScript && ch != ';' && ch != '\r' && ch != '\n') {
316 ++ichT;
317 }
318 cchToken = ichT - ichToken;
319 return cchToken > 0;
320 }
321
322 bool SelectionCompiler::lookingAtDecimal(boolean allowNegative) {
323 if (ichToken == cchScript) {
324 return false;
325 }
326
327 int ichT = ichToken;
328 if (script[ichT] == '-') {
329 ++ichT;
330 }
331 boolean digitSeen = false;
332 char ch = 'X';
333 while (ichT < cchScript && std::isdigit(ch = script[ichT])) {
334 ++ichT;
335 digitSeen = true;
336 }
337
338 if (ichT == cchScript || ch != '.') {
339 return false;
340 }
341
342 // to support 1.ca, let's check the character after the dot
343 // to determine if it is an alpha
344 if (ch == '.' && (ichT + 1 < cchScript) && std::isalpha(script[ichT + 1])) {
345 return false;
346 }
347
348 ++ichT;
349 while (ichT < cchScript && std::isdigit(script[ichT])) {
350 ++ichT;
351 digitSeen = true;
352 }
353 cchToken = ichT - ichToken;
354 return digitSeen;
355 }
356
357 bool SelectionCompiler::lookingAtInteger(boolean allowNegative) {
358 if (ichToken == cchScript) {
359 return false;
360 }
361 int ichT = ichToken;
362 if (allowNegative && script[ichToken] == '-') {
363 ++ichT;
364 }
365 int ichBeginDigits = ichT;
366 while (ichT < cchScript && std::isdigit(script[ichT])) {
367 ++ichT;
368 }
369 if (ichBeginDigits == ichT) {
370 return false;
371 }
372 cchToken = ichT - ichToken;
373 return true;
374 }
375
376 bool SelectionCompiler::lookingAtLookupToken() {
377 if (ichToken == cchScript) {
378 return false;
379 }
380
381 int ichT = ichToken;
382 char ch;
383 switch (ch = script[ichT++]) {
384 case '(':
385 case ')':
386 case ',':
387 case '*':
388 case '-':
389 case '[':
390 case ']':
391 case '+':
392 case ':':
393 case '@':
394 case '.':
395 case '%':
396 break;
397 case '&':
398 case '|':
399 if (ichT < cchScript && script[ichT] == ch) {
400 ++ichT;
401 }
402 break;
403 case '<':
404 case '=':
405 case '>':
406 if (ichT < cchScript && ((ch = script[ichT]) == '<' || ch == '=' || ch == '>')) {
407 ++ichT;
408 }
409 break;
410 case '/':
411 case '!':
412 if (ichT < cchScript && script[ichT] == '=') {
413 ++ichT;
414 }
415 break;
416 default:
417 if ((ch < 'a' || ch > 'z') && (ch < 'A' && ch > 'Z') && ch != '_') {
418 return false;
419 }
420 case '?': // include question marks in identifier for atom expressions
421 while (ichT < cchScript && (std::isalpha(ch = script[ichT]) ||std::isdigit(ch) ||
422 ch == '_' || ch == '?') ||(ch == '^' && ichT > ichToken && std::isdigit(script[ichT - 1]))) {
423 // hack for insertion codes embedded in an atom expression :-(
424 // select c3^a
425 ++ichT;
426 }
427 break;
428 }
429 cchToken = ichT - ichToken;
430 return true;
431 }
432
433 bool SelectionCompiler::compileCommand(Vector ltoken) {
434 /** todo */
435 Token tokenCommand = (Token)ltoken.firstElement();
436 int tokCommand = tokenCommand.tok;
437
438 atokenCommand = new Token[ltoken.size()];
439 ltoken.copyInto(atokenCommand);
440 if ((tokCommand & Token.expressionCommand) != 0 && !compileExpression()) {
441 return false;
442 }
443 return true;
444 }
445
446 bool SelectionCompiler::compileExpression() {
447 /** todo */
448 int i = 1;
449 int tokCommand = atokenCommand[0].tok;
450 if (tokCommand == Token.define)
451 i = 2;
452 else if ((tokCommand & Token.embeddedExpression) != 0) {
453 // look for the open parenthesis
454 while (i < atokenCommand.length &&
455 atokenCommand[i].tok != Token.leftparen)
456 ++i;
457 }
458 if (i >= atokenCommand.length)
459 return true;
460 return compileExpression(i);
461 }
462
463
464 bool SelectionCompiler::addTokenToPostfix(Token token) {
465 ltokenPostfix.push_back(token);
466 return true;
467 }
468
469 bool SelectionCompiler::compileExpression(int itoken) {
470 ltokenPostfix = new Vector();
471 for (int i = 0; i < itoken; ++i)
472 addTokenToPostfix(atokenCommand[i]);
473
474 atokenInfix = atokenCommand;
475 itokenInfix = itoken;
476
477 addTokenToPostfix(Token.tokenExpressionBegin);
478 if (!clauseOr()) {
479 return false;
480 }
481
482 addTokenToPostfix(Token.tokenExpressionEnd);
483 if (itokenInfix != atokenInfix.length) {
484 return endOfExpressionExpected();
485 }
486
487 atokenCommand = ltokenPostfix;
488 return true;
489 }
490
491 Token SelectionCompiler::tokenNext() {
492 if (itokenInfix == atokenInfix.length)
493 return null;
494 return atokenInfix[itokenInfix++];
495 }
496
497 Object SelectionCompiler::valuePeek() {
498 if (itokenInfix == atokenInfix.length) {
499 return null;
500 } else {
501 return atokenInfix[itokenInfix].value;
502 }
503 }
504
505 int SelectionCompiler::tokPeek() {
506 if (itokenInfix == atokenInfix.length) {
507 return 0;
508 }else {
509 return atokenInfix[itokenInfix].tok;
510 }
511 }
512
513 bool SelectionCompiler::clauseOr() {
514 if (!clauseAnd()) {
515 return false;
516 }
517
518 while (tokPeek() == Token.opOr) {
519 Token tokenOr = tokenNext();
520 if (!clauseAnd()) {
521 return false;
522 }
523 addTokenToPostfix(tokenOr);
524 }
525 return true;
526 }
527
528 bool SelectionCompiler::clauseAnd() {
529 if (!clauseNot()) {
530 return false;
531 }
532
533 while (tokPeek() == Token.opAnd) {
534 Token tokenAnd = tokenNext();
535 if (!clauseNot()) {
536 return false;
537 }
538 addTokenToPostfix(tokenAnd);
539 }
540 return true;
541 }
542
543 bool SelectionCompiler::clauseNot() {
544 if (tokPeek() == Token.opNot) {
545 Token tokenNot = tokenNext();
546 if (!clauseNot()) {
547 return false;
548 }
549 return addTokenToPostfix(tokenNot);
550 }
551 return clausePrimitive();
552 }
553
554 bool SelectionCompiler::clausePrimitive() {
555 int tok = tokPeek();
556 switch (tok) {
557 case Token.within:
558 return clauseWithin();
559 case Token.hyphen: // selecting a negative residue spec
560 case Token.integer:
561 case Token.seqcode:
562 case Token.asterisk:
563 case Token.leftsquare:
564 case Token.identifier:
565 case Token.x:
566 case Token.y:
567 case Token.z:
568 case Token.colon:
569 return clauseResidueSpec();
570 default:
571 if ((tok & Token.atomproperty) == Token.atomproperty) {
572 return clauseComparator();
573 }
574 if ((tok & Token.predefinedset) != Token.predefinedset) {
575 break;
576 }
577 // fall into the code and below and just add the token
578 case Token.all:
579 case Token.none:
580 return addTokenToPostfix(tokenNext());
581 case Token.leftparen:
582 tokenNext();
583 if (!clauseOr()) {
584 return false;
585 }
586 if (tokenNext().tok != Token.rightparen) {
587 return rightParenthesisExpected();
588 }
589 return true;
590 }
591 return unrecognizedExpressionToken();
592 }
593
594 bool SelectionCompiler::clauseComparator() {
595 Token tokenAtomProperty = tokenNext();
596 Token tokenComparator = tokenNext();
597 if ((tokenComparator.tok & Token.comparator) == 0) {
598 return comparisonOperatorExpected();
599 }
600
601 Token tokenValue = tokenNext();
602 if (tokenValue.tok != Token.integer) {
603 return integerExpected();
604 }
605 int val = tokenValue.intValue;
606 // note that a comparator instruction is a complicated instruction
607 // int intValue is the tok of the property you are comparing
608 // the value against which you are comparing is stored as an Integer
609 // in the object value
610 return addTokenToPostfix(new Token(tokenComparator.tok,
611 tokenAtomProperty.tok,
612 new Integer(val)));
613 }
614
615 bool SelectionCompiler::clauseWithin() {
616 tokenNext(); // WITHIN
617 if (tokenNext().tok != Token.leftparen) { // (
618 return leftParenthesisExpected();
619 }
620
621 Object distance;
622 Token tokenDistance = tokenNext(); // distance
623 switch(tokenDistance.tok) {
624 case Token.integer:
625 distance = new Float((tokenDistance.intValue * 4) / 1000f);
626 break;
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();
636 }
637
638 if (! clauseOr()) { // *expression*
639 return false;
640 }
641
642 if (tokenNext().tok != Token.rightparen) { // )T
643 return rightParenthesisExpected();
644 }
645
646 return addTokenToPostfix(new Token(Token.within, distance));
647 }
648
649 bool SelectionCompiler:: clauseChemObject() {
650 }
651
652 bool SelectionCompiler:: clauseMolecule() {
653 }
654
655 bool SelectionCompiler:: clauseMolName() {
656 }
657
658 bool SelectionCompiler:: clauseMolIndex() {
659 }
660
661 bool SelectionCompiler:: clauseName() {
662 }
663
664 bool SelectionCompiler:: clauseIndex() {
665 }
666
667 bool SelectionCompiler:: clauseStuntDoubleName() {
668 }
669
670 bool SelectionCompiler:: clauseStuntDoubleIndex() {
671 }
672
673 }

Properties

Name Value
svn:executable *