ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-3.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

# User Rev Content
1 tim 1963 /*
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 *