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

bool Common::XMLParser::parse (  ) 

The actual parsing function. Parses the loaded data stream, returns true if successful.

Definition at line 249 of file xmlparser.cpp.

References _activeKey, _token, buildLayout(), cleanup(), closeKey(), Common::XMLParser::ParserNode::depth, Common::XMLParser::ParserNode::header, Common::XMLParser::ParserNode::ignore, Common::XMLParser::ParserNode::layout, Common::XMLParser::ParserNode::name, parseActiveKey(), parseKeyValue(), parserError(), parseToken(), Common::ReadStream::readByte(), Common::SeekableReadStream::seek(), skipComments(), and skipSpaces().

                      {
      if (_stream == 0)
            return parserError("XML stream not ready for reading.");

      // Make sure we are at the start of the stream.
      _stream->seek(0, SEEK_SET);

      if (_XMLkeys == 0)
            buildLayout();

      while (!_activeKey.empty())
            freeNode(_activeKey.pop());

      cleanup();

      bool activeClosure = false;
      bool activeHeader = false;
      bool selfClosure;

      _state = kParserNeedHeader;
      _activeKey.clear();

      _char = _stream->readByte();

      while (_char && _state != kParserError) {
            if (skipSpaces())
                  continue;

            if (skipComments())
                  continue;

            switch (_state) {
            case kParserNeedHeader:
            case kParserNeedKey:
                  if (_char != '<') {
                        parserError("Parser expecting key start.");
                        break;
                  }

                  if ((_char = _stream->readByte()) == 0) {
                        parserError("Unexpected end of file.");
                        break;
                  }

                  if (_state == kParserNeedHeader) {
                        if (_char != '?') {
                              parserError("Expecting XML header.");
                              break;
                        }

                        _char = _stream->readByte();
                        activeHeader = true;
                  } else if (_char == '/') {
                        _char = _stream->readByte();
                        activeClosure = true;
                  } else if (_char == '?') {
                        parserError("Unexpected header. There may only be one XML header per file.");
                        break;
                  }

                  _state = kParserNeedKeyName;
                  break;

            case kParserNeedKeyName:
                  if (!parseToken()) {
                        parserError("Invalid key name.");
                        break;
                  }

                  if (activeClosure) {
                        if (_activeKey.empty() || _token != _activeKey.top()->name) {
                              parserError("Unexpected closure.");
                              break;
                        }
                  } else {
                        ParserNode *node = allocNode(); //new ParserNode;
                        node->name = _token;
                        node->ignore = false;
                        node->header = activeHeader;
                        node->depth = _activeKey.size();
                        node->layout = 0;
                        _activeKey.push(node);
                  }

                  _state = kParserNeedPropertyName;
                  break;

            case kParserNeedPropertyName:
                  if (activeClosure) {
                        if (!closeKey()) {
                              parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str());
                              break;
                        }

                        activeClosure = false;

                        if (_char != '>')
                              parserError("Invalid syntax in key closure.");
                        else
                              _state = kParserNeedKey;

                        _char = _stream->readByte();
                        break;
                  }

                  selfClosure = false;

                  if (_char == '/' || (_char == '?' && activeHeader)) {
                        selfClosure = true;
                        _char = _stream->readByte();
                  }

                  if (_char == '>') {
                        if (activeHeader && !selfClosure) {
                              parserError("XML Header must be self-closed.");
                        } else if (parseActiveKey(selfClosure)) {
                              _char = _stream->readByte();
                              _state = kParserNeedKey;
                        }

                        activeHeader = false;
                        break;
                  }

                  if (selfClosure)
                        parserError("Expecting key closure after '/' symbol.");
                  else if (!parseToken())
                        parserError("Error when parsing key value.");
                  else
                        _state = kParserNeedPropertyOperator;

                  break;

            case kParserNeedPropertyOperator:
                  if (_char != '=')
                        parserError("Syntax error after key name.");
                  else
                        _state = kParserNeedPropertyValue;

                  _char = _stream->readByte();
                  break;

            case kParserNeedPropertyValue:
                  if (!parseKeyValue(_token))
                        parserError("Invalid key value.");
                  else
                        _state = kParserNeedPropertyName;

                  break;

            default:
                  break;
            }
      }

      if (_state == kParserError)
            return false;

      if (_state != kParserNeedKey || !_activeKey.empty())
            return parserError("Unexpected end of file.");

      return true;
}


Generated by  Doxygen 1.6.0   Back to index