Logo Search packages:      
Sourcecode: falconpl version File versions  Download package

Item * Falcon::VMachine::findLocalVariable ( const String name  )  const

Returns the value of a local variable. This function searces for a variable in the local context, and eventually in the global context if not locally found. The function also parses accessors as the "." dot operator or the [] array access operator, but it doesn't support range accessors or function calls.

The returned pointer is the place where the variable is physically stored.

If the variable cannot be found, 0 is returned.

Parameters:
name the variable to be found
Returns:
the physical pointer to the variable storage, or 0 on failure.

Definition at line 2310 of file vm.cpp.

References Falcon::String::append(), Falcon::Item::asObject(), findLocalSymbolItem(), Falcon::String::getCharAt(), Falcon::Item::isArray(), Falcon::Item::isDict(), Falcon::Item::isObject(), Falcon::String::length(), and Falcon::String::size().

Referenced by expandString().

{
   // item to be returned.
   Item *itm = 0;
   String sItemName;
   uint32 squareLevel = 0;
   uint32 len = name.length();

   typedef enum {
      initial,
      firstToken,
      interToken,
      dotAccessor,
      squareAccessor,
      postSquareAccessor,
      singleQuote,
      doubleQuote,
      strEscapeSingle,
      strEscapeDouble,
   } t_state;

   t_state state = initial;

   uint32 pos = 0;
   while( pos <= len )
   {
      // little trick: force a ' ' at len
      uint32 chr;
      if( pos == len )
         chr = ' ';
      else
         chr = name.getCharAt( pos );

      switch( state )
      {
         case initial:
            if( vmIsWhiteSpace( chr ) )
            {
               pos++;
               continue;
            }
            if( chr < 'A' )
               return 0;

            state = firstToken;
            sItemName.append( chr );
         break;

         //===================================================
         // Parse first token. It must be a valid local symbol
         case firstToken:
            if ( vmIsWhiteSpace( chr ) || chr == '.' || chr == '[' )
            {
               itm = findLocalSymbolItem( sItemName );

               // item not found?
               if( itm == 0 )
                  return 0;

               // set state accordingly to chr.
               goto resetState;
            }
            else if ( vmIsTokenChr( chr ) )
            {
               sItemName.append( chr );
            }
            else {
               // invalid format
               return 0;
            }
         break;

         //===================================================
         // Parse a dot accessor.
         //
         case dotAccessor:
            // wating for a complete token.

            if ( vmIsWhiteSpace( chr ) || chr == '.' || chr == '[' )
            {
               // ignore leading ws.
               if( sItemName.size() == 0 && vmIsWhiteSpace( chr ) )
                  break;

               // access the item. We know it's an object or we wouldn't be in this state.
               itm = itm->asObject()->getProperty( sItemName );
               if ( itm == 0 )
                  return 0;

               // set state accordingly to chr.
               goto resetState;
            }
            else if ( vmIsTokenChr( chr ) )
            {
               sItemName.append( chr );
            }
            else
               return 0;
         break;

         //===================================================
         // Parse the square accessor; from [ to matching ]

         case squareAccessor:
            // wating for complete square token.
            switch( chr )
            {
               case '[':
                  squareLevel++;
                  sItemName.append( chr );
               break;

               case ']':
                  if( --squareLevel == 0 )
                  {
                     itm = parseSquareAccessor( *itm, sItemName );
                     if( itm == 0 )
                        return 0;

                     goto resetState;
                  }
                  else
                     sItemName.append( chr );
               break;

               case '\'':
                  sItemName.append( chr );
                  state = singleQuote;
               break;

               case '"':
                  sItemName.append( chr );
                  state = doubleQuote;
               break;

               default:
                  sItemName.append( chr );
            }
         break;

         case postSquareAccessor:
            // wating for complete square token.
            if( chr == ']' )
            {
               if( --squareLevel == 0 )
               {
                  itm = parseSquareAccessor( *itm, sItemName );
                  if( itm == 0 )
                     return 0;

                  goto resetState;
               }
               else
                  sItemName.append( chr );
            }
            else if( ! vmIsWhiteSpace( chr ) )
            {
               return 0;
            }
         break;


         //===================================================
         // Parse the double quote inside suqare accessor
         case doubleQuote:
            switch( chr )
            {
               case '\\': state = strEscapeDouble; break;
               case '"': state = postSquareAccessor;  // do not break
               default:
                  sItemName.append( chr );
            }
         break;

         //===================================================
         // Parse the single quote inside suqare accessor
         case singleQuote:
            switch( chr )
            {
               case '\\': state = strEscapeSingle; break;
               case '\'': state = squareAccessor;  // do not break
               default:
                  sItemName.append( chr );
            }
         break;

         //===================================================
         // Parse the double quote inside suqare accessor
         case strEscapeDouble:
            sItemName.append( chr );
            state = doubleQuote;
         break;

         //===================================================
         // Parse the single quote inside suqare accessor
         case strEscapeSingle:
            sItemName.append( chr );
            state = singleQuote;
         break;

         //===================================================
         // Parse the space between tokens.
         case interToken:
            switch( chr ) {
               case '.':
                  if( ! itm->isObject() )
                     return 0;
                  state = dotAccessor;
               break;

               case '[':
                  if( ! itm->isDict() && ! itm->isArray() )
                     return 0;

                  state = squareAccessor;
                  squareLevel = 1;
               break;

               default:
                  if( ! vmIsWhiteSpace( chr ) )
                     return 0;
            }
         break;
      }

      // end the loop here
      pos++;
      continue;

      // state reset area.
resetState:

      sItemName.size(0); // clear sItemName.

      switch( chr ) {
         case '.':
            if( ! itm->isObject() )
               return 0;
            state = dotAccessor;
         break;

         case '[':
            if( ! itm->isDict() && ! itm->isArray() )
               return 0;

            state = squareAccessor;
            squareLevel = 1;
         break;

         default:
            state = interToken;
      }

      // end of loop, increment pos.
      pos++;
   }

   // if the state is not "interToken" we have an incomplete parse
   if( state != interToken )
      return 0;

   // Success
   return itm;
}


Generated by  Doxygen 1.6.0   Back to index