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

Code * Parser::parse ( const SourceLineList &  lines  ) 

This is the actual parsing function, make sure to use parseUsingChild instead (???)

TODO sanity check label name and then do error like "Bad label"

Definition at line 162 of file parser.cpp.

References Code::append(), Statement::bracedCode, Field::compulsory(), Statement::content, getBracedCode(), Field::key(), Microbe::makePic(), mistake(), processAssignment(), processStatement(), Microbe::resetDest(), PIC14::setCode(), PIC14::setParser(), PIC14::Slabel(), Field::string(), SourceLine::text(), Statement::text(), and Field::type().

Referenced by Microbe::compile(), and parseWithChild().

{
      StatementList sList;
      m_pPic = mb->makePic();
      m_code = new Code();
      m_pPic->setCode( m_code );
      m_pPic->setParser(this);
      m_bPassedEnd = false;
      
      /* First pass
         ==========
         
         Here we go through the code making each line into a statement object,
         looking out for braced code as we go, if we find it then we put then
         we make attach the braced code to the statment.
      */   

      SourceLineList::const_iterator end = lines.end();
      for ( SourceLineList::const_iterator slit = lines.begin(); slit != end; ++slit )
      {
            Statement s;
            s.content = *slit;
            
            // Check to see if the line after next is a brace
            SourceLineList::const_iterator previous = slit;
            if ( (++slit != end) && (*slit).text() == "{" )
                  s.bracedCode = getBracedCode( & slit, end );
            else
                  slit = previous;
            
            if ( !s.text().isEmpty() )
                  sList.append(s);
      }
      
      mb->resetDest();
      
      for( StatementList::Iterator sit = sList.begin(); sit != sList.end(); ++sit )
      {
            m_currentSourceLine = (*sit).content;
            
            QString line = (*sit).text();
            
            QString command; // e.g. "delay", "for", "subroutine", "increment", etc
            {
                  int spacepos = line.find(' ');
                  if ( spacepos >= 0 )
                        command = line.left( spacepos );
                  else
                        command = line;
            }
            OutputFieldMap fieldMap;
            
            if ( (*sit).content.line() >= 0 )
                  m_code->append( new Instr_sourceCode( QString("#MSRC\t%1; %2\t%3").arg( (*sit).content.line() + 1 ).arg( (*sit).content.url() ).arg( (*sit).content.text() ) ));
            bool showBracesInSource = (*sit).hasBracedCode();
            if ( showBracesInSource )
                  m_code->append(new Instr_sourceCode("{"));

            // Use the first token in the line to look up the statement type
            DefinitionMap::Iterator dmit = m_definitionMap.find(command);
            if(dmit == m_definitionMap.end())
            {
                  if( !processAssignment( (*sit).text() ) )
                  {
                        // Not an assignement, maybe a label
                        if( (*sit).isLabel() ) 
                        {
                              QString label = (*sit).text().left( (*sit).text().length() - 1 );
                              ///TODO sanity check label name and then do error like "Bad label"
                              m_pPic->Slabel( label );
                        }
                        else
                              mistake( Microbe::Microbe::UnknownStatement );
                  }
                  
                  continue; // Give up on the current statement
            }
            StatementDefinition definition = dmit.data();
            
            // Start at the first white space character following the statement name
            int newPosition = 0;
            int position = command.length() + 1;
            
            // Temporaries for use inside the switch
            Field nextField;
            Statement nextStatement;
            
            bool errorInLine = false;
            bool finishLine = false;

            for( StatementDefinition::Iterator sdit = definition.begin(); sdit != definition.end(); ++sdit )
            {
                  // If there is an error, or we have finished the statement,
                  // the stop. If we are at the end of a line in a multiline, then
                  // break to fall through to the next line
                  if( errorInLine || finishLine) break;
            
                  Field field = (*sdit);
                  QString token;
                  
                  bool saveToken = false;
                  bool saveBraced = false;
                  bool saveSingleLine = false;
                  
                  switch(field.type())
                  {     
                        case (Field::Label):
                        case (Field::Variable):
                        case (Field::Name):
                        {
                              newPosition = line.find( ' ', position );
                              if(position == newPosition)
                              {
                                    newPosition = -1;
                                    token = line.mid(position);
                              }
                              else token = line.mid(position, newPosition - position);
                              if( token.isEmpty() )
                              {
                                    if(field.type() == Field::Label)
                                          mistake( Microbe::Microbe::LabelExpected );
                                    else if (field.type() == Field::Variable)
                                          mistake( Microbe::VariableExpected );
                                    else // field.type() == Field::Name
                                          mistake( Microbe::NameExpected );
                                    errorInLine = true;
                                    continue;
                              }
                              position = newPosition;
                              saveToken = true;
                              break;
                        }
                              
                        case (Field::Expression):
                        {
                              // This is slightly different, as there is nothing
                              // in particular that delimits an expression, we just have to
                              // look at what comes next and hope we can use that.
                              StatementDefinition::Iterator it(sdit);
                              ++it;
                              if( it != definition.end() )
                              {
                                    nextField = (*it);
                                    if(nextField.type() == Field::FixedString) 
                                          newPosition = line.find(QRegExp("\\b" + nextField.string() + "\\b"));
                                    // Although code is not neccessarily braced, after an expression it is the only
                                    // sensilbe way to have it.
                                    else if(nextField.type() == Field::Code)
                                    {
                                          newPosition = line.find("{");
                                          if(newPosition == -1) newPosition = line.length() + 1;
                                    }
                                    else if(nextField.type() == Field::Newline)
                                          newPosition = line.length()+1;
                                    else kdDebug() << "Bad statement definition - awkward field type after expression";
                              }
                              else newPosition = line.length() + 1;
                              if(newPosition == -1)
                              {
                                    // Something was missing, we'll just play along for now,
                                    // the next iteration will catch whatever was supposed to be there
                              }
                              token = line.mid(position, newPosition - position);
                              position = newPosition;
                              saveToken = true;
                        }
                        break;
                              
                        case (Field::PinList):
                        {
                              // For now, just assume that the list of pins will continue to the end of the tokens.
                              // (we could check until we come across a non-pin, but no command has that format at
                              // the moment).
                              
                              token = line.mid( position + 1 );
                              position = line.length() + 1;
                              if ( token.isEmpty() )
                                    mistake( Microbe::PinListExpected );
                              else
                                    saveToken = true;
                              
                              break;
                        }
                              
                        case (Field::Code):
                              if ( !(*sit).hasBracedCode() )
                              {
                                    saveSingleLine = true;
                                    token = line.mid(position);
                                    position = line.length() + 1;
                              }
                              else if( position != -1  && position <= int(line.length()) )
                              {
                                    mistake( Microbe::UnexpectedStatementBeforeBracket );
                                    errorInLine = true;
                                    continue;
                              }
                              else                          
                              {
                                    // Because of the way the superstructure parsing works there is no
                                    // 'next line' as it were, the braced code is attached to the current line.
                                    saveBraced = true;
                              }
                              break;
                              
                        case (Field::FixedString):
                        {
                              // Is the string found, and is it starting in the right place?
                              int stringPosition  = line.find(QRegExp("\\b"+field.string()+"\\b"));
                              if( stringPosition != position || stringPosition == -1 )
                              {
                                    if( !field.compulsory() )
                                    {
                                          position = -1;
                                          // Skip the next field
                                          ++sdit;
                                          continue;
                                    }
                                    else
                                    {
                                          // Otherwise raise an appropriate error
                                          mistake( Microbe::FixedStringExpected, field.string() );
                                          errorInLine = true;
                                          continue;
                                    }
                              }
                              else
                              {
                                    position += field.string().length() + 1;
                              }
                        }
                              break;
                              
                        case (Field::Newline):
                              // It looks like the best way to handle this is to just actually
                              // look at the next line, and see if it begins with an expected fixed
                              // string.
                              
                              // Assume there is a next field, it would be silly if there weren't.
                              nextField = *(++StatementDefinition::Iterator(sdit));
                              if( nextField.type() == Field::FixedString )
                              {
                                    nextStatement = *(++StatementList::Iterator(sit));
                                    newPosition = nextStatement.text().find(QRegExp("\\b" + nextField.string() + "\\b"));
                                    if(newPosition != 0)
                                    {
                                          // If the next field is optional just carry on as nothing happened,
                                          // the next line will be processed as a new statement
                                          if(!nextField.compulsory()) continue;
                                          
                                    }
                                    position = 0;
                                    line = (*(++sit)).text();
                                    m_currentSourceLine = (*sit).content;
                              }
                              
                              break;
                              
                        case (Field::None):
                              // Do nothing
                              break;
                  }
                  
                  if ( saveToken )
                        fieldMap[field.key()] = OutputField( token );
                  
                  if ( saveSingleLine )
                  {
                        SourceLineList list;
                        list << SourceLine( token, 0, -1 );
                        fieldMap[field.key()] = OutputField( list );
                  }
                  
                  if ( saveBraced )
                        fieldMap[field.key()] = OutputField( (*sit).bracedCode );
                  // If position = -1, we have reached the end of the line.
            }
            
            // See if we got to the end of the line, but not all fields had been
            // processed.
            if( position != -1  && position <= int(line.length()) )
            {
                  mistake( Microbe::TooManyTokens );
                  errorInLine = true;
            }
            
            if( errorInLine ) continue;
                  
            // Everything has been parsed up, so send it off for processing.
            processStatement( command, fieldMap );

            if( showBracesInSource )
                  m_code->append(new Instr_sourceCode("}"));
      }
      
      delete m_pPic;
      return m_code;
}


Generated by  Doxygen 1.6.0   Back to index