parse.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <vector>
00021 #include <map>
00022 
00023 #include <archon/util/text.H>
00024 #include <archon/util/unicode.H>
00025 
00026 #include <archon/x3d/server/script.H>
00027 #include <archon/x3d/server/parse.H>
00028 
00029 using namespace std;
00030 
00031 namespace Archon
00032 {
00033   using namespace Utilities;
00034 
00035   namespace X3D
00036   {
00037     bool Parser::validateIdentifier(string s)
00038     {
00039       ustring t = Unicode::decodeUtf8(s);
00040       if(!t.size()) return false;
00041       for(unsigned i=0; i<t.size(); ++i)
00042       {
00043         uchar u = t[i];
00044         if(u >= 0x80) continue;
00045         if(u <= 0x20 ||
00046            i == 0 && '0' <= u && u <= '9' ||
00047            u == '"' || u == '#' || u == '\'' ||
00048            '+' <= u && u <= '.' ||               //  + , - .
00049            '[' <= u && u <= ']' ||               //  [ \ ]
00050            u == '{' || u == '}' || u == 0x7f)
00051           return false;
00052       }
00053       return true;
00054     }
00055 
00056     void Parser::addNamedNode(string name, Ref<NodeBase> node)
00057     {
00058       try
00059       {
00060         node->setName(name);
00061       }
00062       catch(NodeNameInUseException &)
00063       {
00064         warning("Attempt to reuse node name '" + name + "'");
00065       }
00066     }
00067 
00068     void Parser::addRootGroupChild(Ref<ChildNode> c, Time stamp)
00069     {
00070       rootGroup->add(GroupingNode::childrenField, c, stamp);
00071     }
00072 
00073     void Parser::addRoute(string sourceNodeName, string sourceFieldName,
00074                           string targetNodeName, string targetFieldName)
00075     {
00076       const FieldBase *sourceField = 0;
00077       const FieldBase *targetField = 0;
00078 
00079       bool skip = false;
00080 
00081       Ref<NodeBase> sourceNode = lookupNode(sourceNodeName);
00082       if(!sourceNode)
00083       {
00084         warning("Undefined source node name '" + sourceNodeName +
00085                 "' (route ignored)");
00086         skip = true;
00087       }
00088       else
00089       {
00090         sourceField = sourceNode->lookupField(sourceFieldName);
00091         if(!sourceField)
00092         {
00093           warning("Source node type '" + sourceNode->getType()->getName() +
00094                   "' has no field named '" + sourceFieldName +
00095                   "' (route ignored)");
00096           skip = true;
00097         }
00098         else if(!sourceField->getIsEventSource())
00099         {
00100           warning(sourceNode->getType()->getName() + "." +
00101                   sourceField->getName() +
00102                   " cannot generate events (route ignored)");
00103           skip = true;
00104         }
00105       }
00106 
00107       Ref<NodeBase> targetNode = lookupNode(targetNodeName);
00108       if(!targetNode)
00109       {
00110         warning("Undefined target node name '" + targetNodeName +
00111                 "' (route ignored)");
00112         skip = true;
00113       }
00114       else
00115       {
00116         targetField = targetNode->lookupField(targetFieldName);
00117         if(!targetField)
00118         {
00119           warning("Target node type '" + targetNode->getType()->getName() +
00120                   "' has no field named '" + targetFieldName +
00121                   "' (route ignored)");
00122           skip = true;
00123         }
00124         else if(!targetField->getIsEventTarget())
00125         {
00126           warning(targetNode->getType()->getName() + "." +
00127                   targetField->getName() +
00128                   " cannot receive events (route ignored)");
00129           skip = true;
00130         }
00131       }
00132 
00133       // Self reference
00134       if(sourceField && targetField &&
00135          sourceNode == targetNode && sourceField == targetField)
00136       {
00137         const string s = sourceNode->getName() + "." + sourceField->getName();
00138         warning("Illegal route, source field '" + s +
00139                 "' and target field '" + s + "' is the same (route ignored)");
00140         skip = true;
00141       }
00142 
00143       const FieldType *fieldType = 0;
00144 
00145       // Type conformance
00146       if(sourceField && targetField)
00147       {
00148         fieldType = sourceField->getType();
00149         const FieldType *targetFieldType   = targetField->getType();
00150 
00155         if(fieldType != targetFieldType)
00156         {
00157           warning("Type mismatch, source field type is '" +
00158                   fieldType->getName() +
00159                   "' and target field type is '" +
00160                   targetFieldType->getName() + "' (route ignored)");
00161           skip = true;
00162         }
00163       
00168         if(const NodeFieldBase *sourceNodeField =
00169            dynamic_cast<const NodeFieldBase *>(sourceField))
00170         {
00171           const NodeFieldBase *targetNodeField =
00172             dynamic_cast<const NodeFieldBase *>(targetField);
00173           if(!sourceNodeField->getNodeType()->
00174              isDerivedFrom(targetNodeField->getNodeType()))
00175           {
00176             warning("Type mismatch, source field type is '" +
00177                     sourceNodeField->getNodeType()->getName() +
00178                     "' and target field type is '" +
00179                     targetNodeField->getNodeType()->getName() +
00180                     "' (route ignored)");
00181             skip = true;
00182           }
00183         }
00184       }
00185 
00186       if(skip) return;
00187 
00188       Route::add(sourceNode, sourceField, targetNode, targetField);
00189 
00190       /*
00191       logger->log("ROUTE:" + fieldType->getName() +
00192                   " " + sourceNode->getName() +
00193                   ":" + sourceNode->getType()->getName() +
00194                   "." + sourceField->getName() +
00195                   " TO " + targetNode->getName() +
00196                   ":" + targetNode->getType()->getName() +
00197                   "." + targetField->getName());
00198       */
00199     }
00200 
00201 
00202     int Parser::getNextCustomFieldIndex(Ref<CustomFieldNode> n)
00203     {
00204       return n->getNumberOfCustomFields();
00205     }
00206 
00207     void Parser::addScriptField(Ref<CustomFieldNode> n, Ref<CustomFieldBase> f)
00208     {
00209       if(!n->addCustomField(f))
00210         warning("Name of new field '" + f->getName() + "' clashes with "
00211                 "existing fields of the " + n->getType()->getName() +
00212                 " node (field ignored)");
00213     }
00214   }
00215 }

Generated on Sun Jul 30 22:55:49 2006 for Archon by  doxygen 1.4.4