1. 程式人生 > >Ogre原始碼淺析——指令碼及其解析(三)

Ogre原始碼淺析——指令碼及其解析(三)

複製程式碼
  1     ConcreteNodeListPtr ScriptParser::parse(const ScriptTokenListPtr &tokens)
  2     {
  3         // MEMCATEGORY_GENERAL because SharedPtr can only free using that category
  4         ConcreteNodeListPtr nodes(OGRE_NEW_T(ConcreteNodeList, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);
  5 
  6         enum{READY, OBJECT};
  7         uint32 state = READY;
  8 
  9         ConcreteNode *parent = 0;
 10         ConcreteNodePtr node;
 11         ScriptToken *token = 0;
 12         ScriptTokenList::iterator i = tokens->begin(), end = tokens->end();
 13         while(i != end)
 14         {
 15             token = (*i).get();
 16 
 17             switch(state)
 18             {
 19             case READY:
 20                 if(token->type == TID_WORD)
 21                 {
 22                     if(token->lexeme == "import")
 23                     {
 24                         node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
 25                         node->token = token->lexeme;
 26                         node->file = token->file;
 27                         node->line = token->line;
 28                         node->type = CNT_IMPORT;
 29 
 30                         // The next token is the target
 31                         ++i;
 32                         if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
 33                             OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
 34                                 Ogre::String("expected import target at line ") + 
 35                                     Ogre::StringConverter::toString(node->line),
 36                                 "ScriptParser::parse");
 37                         ConcreteNodePtr temp(OGRE_NEW ConcreteNode());
 38                         temp->parent = node.get();
 39                         temp->file = (*i)->file;
 40                         temp->line = (*i)->line;
 41                         temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
 42                         if(temp->type == CNT_QUOTE)
 43                             temp->token = (*i)->lexeme.substr(1, token->lexeme.size() - 2);
 44                         else
 45                             temp->token = (*i)->lexeme;
 46                         node->children.push_back(temp);
 47 
 48                         // The second-next token is the source
 49                         ++i;
 50                         ++i;
 51                         if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
 52                             OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
 53                                 Ogre::String("expected import source at line ") + 
 54                                     Ogre::StringConverter::toString(node->line),
 55                                 "ScriptParser::parse");
 56                         temp = ConcreteNodePtr(OGRE_NEW ConcreteNode());
 57                         temp->parent = node.get();
 58                         temp->file = (*i)->file;
 59                         temp->line = (*i)->line;
 60                         temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
 61                         if(temp->type == CNT_QUOTE)
 62                             temp->token = (*i)->lexeme.substr(1, (*i)->lexeme.size() - 2);
 63                         else
 64                             temp->token = (*i)->lexeme;
 65                         node->children.push_back(temp);
 66 
 67                         // Consume all the newlines
 68                         i = skipNewlines(i, end);
 69 
 70                         // Insert the node
 71                         if(parent)
 72                         {
 73                             node->parent = parent;
 74                             parent->children.push_back(node);
 75                         }
 76                         else
 77                         {
 78                             node->parent = 0;
 79                             nodes->push_back(node);
 80                         }
 81                         node = ConcreteNodePtr();
 82                     }
 83                     else if(token->lexeme == "set")
 84                     {
 85                         node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
 86                         node->token = token->lexeme;
 87                         node->file = token->file;
 88                         node->line = token->line;
 89                         node->type = CNT_VARIABLE_ASSIGN;
 90 
 91                         // The next token is the variable
 92                         ++i;
 93                         if(i == end || (*i)->type != TID_VARIABLE)
 94                             OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
 95                                 Ogre::String("expected variable name at line ") + 
 96                                     Ogre::StringConverter::toString(node->line),
 97                                 "ScriptParser::parse");
 98                         ConcreteNodePtr temp(OGRE_NEW ConcreteNode());
 99                         temp->parent = node.get();
100                         temp->file = (*i)->file;
101                         temp->line = (*i)->line;
102                         temp->type = CNT_VARIABLE;
103                         temp->token = (*i)->lexeme;
104                         node->children.push_back(temp);
105 
106                         // The next token is the assignment
107                         ++i;
108                         if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
109                             OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
110                                 Ogre::String("expected variable value at line ") + 
111                                     Ogre::StringConverter::toString(node->line),
112                                 "ScriptParser::parse");
113                         temp = ConcreteNodePtr(OGRE_NEW ConcreteNode());
114                         temp->parent = node.get();
115                         temp->file = (*i)->file;
116                         temp->line = (*i)->line;
117                         temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
118                         if(temp->type == CNT_QUOTE)
119                             temp->token = (*i)->lexeme.substr(1, (*i)->lexeme.size() - 2);
120                         else
121                             temp->token = (*i)->lexeme;
122                         node->children.push_back(temp);
123 
124                         // Consume all the newlines
125                         i = skipNewlines(i, end);
126 
127                         // Insert the node
128                         if(parent)
129                         {
130                             node->parent = parent;
131                             parent->children.push_back(node);
132                         }
133                         else
134                         {
135                             node->parent = 0;
136                             nodes->push_back(node);
137                         }
138                         node = ConcreteNodePtr();
139                     }
140                     else
141                     {
142                         node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
143                         node->file = token->file;
144                         node->line = token->line;
145                         node->type = token->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
146                         if(node->type == CNT_QUOTE)
147                             node->token = token->lexeme.substr(1, token->lexeme.size() - 2);
148                         else
149                             node->token = token->lexeme;
150 
151                         // Insert the node
152                         if(parent)
153                         {
154                             node->parent = parent;
155                             parent->children.push_back(node);
156                         }
157                         else
158                         {
159                             node->parent = 0;
160                             nodes->push_back(node);
161                         }
162 
163                         // Set the parent
164                         parent = node.get();
165 
166                         // Switch states
167                         state = OBJECT;
168 
169                         node = ConcreteNodePtr();
170                     }
171                 }
172                 else if(token->type == TID_RBRACKET)
173                 {
174                     // Go up one level if we can
175                     if(parent)
176                         parent = parent->parent;
177 
178                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
179                     node->token = token->lexeme;
180                     node->file = token->file;
181                     node->line = token->line;
182                     node->type = CNT_RBRACE;
183 
184                     // Consume all the newlines
185                     i = skipNewlines(i, end);
186 
187                     // Insert the node
188                     if(parent)
189                     {
190                         node->parent = parent;
191                         parent->children.push_back(node);
192                     }
193                     else
194                     {
195                         node->parent = 0;
196                         nodes->push_back(node);
197                     }
198 
199                     // Move up another level
200                     if(parent)
201                         parent = parent->parent;
202 
203                     node = ConcreteNodePtr();
204                 }
205                 break;
206             case OBJECT:
207                 if(token->type == TID_NEWLINE)
208                 {
209                     // Look ahead to the next non-newline token and if it isn't an {, this was a property
210                     ScriptTokenList::iterator next = skipNewlines(i, end);
211                     if(next == end || (*next)->type != TID_LBRACKET)
212                     {
213                         // Ended a property here
214                         if(parent)
215                             parent = parent->parent;
216                         state = READY;
217                     }
218                 }
219                 else if(token->type == TID_COLON)
220                 {
221                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
222                     node->token = token->lexeme;
223                     node->file = token->file;
224                     node->line = token->line;
225                     node->type = CNT_COLON;
226 
227                     // The following token are the parent objects (base classes).
228                     // Require at least one of them.
229 
230                     ScriptTokenList::iterator j = i + 1;
231                     j = skipNewlines(j, end);
232                     if(j == end || ((*j)->type != TID_WORD && (*j)->type != TID_QUOTE)) {
233                         OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
234                             Ogre::String("expected object identifier at line ") + 
235                                     Ogre::StringConverter::toString(node->line),
236                             "ScriptParser::parse");
237                     }
238 
239                     while(j != end && ((*j)->type == TID_WORD || (*j)->type == TID_QUOTE))
240                     {
241                         ConcreteNodePtr tempNode = ConcreteNodePtr(OGRE_NEW ConcreteNode());
242                         tempNode->token = (*j)->lexeme;
243                         tempNode->file = (*j)->file;
244                         tempNode->line = (*j)->line;
245                         tempNode->type = (*j)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
246                         tempNode->parent = node.get();
247                         node->children.push_back(tempNode);
248                         ++j;
249                     }
250 
251                     // Move it backwards once, since the end of the loop moves it forwards again anyway
252                     j--;
253                     i = j;
254 
255                     // Insert the node
256                     if(parent)
257                     {
258                         node->parent = parent;
259                         parent->children.push_back(node);
260                     }
261                     else
262                     {
263                         node->parent = 0;
264                         nodes->push_back(node);
265                     }
266                     node = ConcreteNodePtr();
267                 }
268                 else if(token->type == TID_LBRACKET)
269                 {
270                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
271                     node->token = token->lexeme;
272                     node->file = token->file;
273                     node->line = token->line;
274                     node->type = CNT_LBRACE;
275 
276                     // Consume all the newlines
277                     i = skipNewlines(i, end);
278 
279                     // Insert the node
280                     if(parent)
281                     {
282                         node->parent = parent;
283                         parent->children.push_back(node);
284                     }
285                     else
286                     {
287                         node->parent = 0;
288                         nodes->push_back(node);
289                     }
290 
291                     // Set the parent
292                     parent = node.get();
293 
294                     // Change the state
295                     state = READY;
296 
297                     node = ConcreteNodePtr();
298                 }
299                 else if(token->type == TID_RBRACKET)
300                 {
301                     // Go up one level if we can
302                     if(parent)
303                         parent = parent->parent;
304 
305                     // If the parent is currently a { then go up again
306                     if(parent && parent->type == CNT_LBRACE && parent->parent)
307                         parent = parent->parent;
308 
309                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
310                     node->token = token->lexeme;
311                     node->file = token->file;
312                     node->line = token->line;
313                     node->type = CNT_RBRACE;
314 
315                     // Consume all the newlines
316                     i = skipNewlines(i, end);
317 
318                     // Insert the node
319                     if(parent)
320                     {
321                         node->parent = parent;
322                         parent->children.push_back(node);
323                     }
324                     else
325                     {
326                         node->parent = 0;
327                         nodes->push_back(node);
328                     }
329 
330                     // Move up another level
331                     if(parent)
332                         parent = parent->parent;
333 
334                     node = ConcreteNodePtr();
335                     state = READY;
336                 }
337                 else if(token->type == TID_VARIABLE)
338                 {
339                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
340                     node->token = token->lexeme;
341                     node->file = token->file;
342                     node->line = token->line;
343                     node->type = CNT_VARIABLE;
344 
345                     // Insert the node
346                     if(parent)
347                     {
348                         node->parent = parent;
349                         parent->children.push_back(node);
350                     }
351                     else
352                     {
353                         node->parent = 0;
354                         nodes->push_back(node);
355                     }
356                     node = ConcreteNodePtr();
357                 }
358                 else if(token->type == TID_QUOTE)
359                 {
360                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
361                     node->token = token->lexeme.substr(1, token->lexeme.size() - 2);
362                     node->file = token->file;
363                     node->line = token->line;
364                     node->type = CNT_QUOTE;
365 
366                     // Insert the node
367                     if(parent)
368                     {
369                         node->parent = parent;
370                         parent->children.push_back(node);
371                     }
372                     else
373                     {
374                         node->parent = 0;
375                         nodes->push_back(node);
376                     }
377                     node = ConcreteNodePtr();
378                 }
379                 else if(token->type == TID_WORD)
380                 {
381                     node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
382                     node->token = token->lexeme;
383                     node->file = token->file;
384                     node->line = token->line;
385                     node->type = CNT_WORD;
386 
387                     // Insert the node
388                     if(parent)
389                     {
390                         node->parent = parent;
391                         parent->children.push_back(node);
392                     }
393                     else
394                     {
395                         node->parent = 0;
396                         nodes->push_back(node);
397                     }
398                     node = ConcreteNodePtr();
399                 }
400                 break;
401             }
402 
403             ++i;
404         }
405 
406         return nodes;
407     }
複製程式碼