diff options
author | Vicent Marti | 2008-06-13 09:24:41 +0000 |
---|---|---|
committer | Vicent Marti | 2008-06-13 09:24:41 +0000 |
commit | e0d7301cb04a99927091fdf51cec2d88fb68ad52 (patch) | |
tree | 346920f21cbe88c66530d3f8763ed32395034cca | |
parent | ace171e22f98f9f9195447893b12fcf4ea79561c (diff) | |
download | scummvm-rg350-e0d7301cb04a99927091fdf51cec2d88fb68ad52.tar.gz scummvm-rg350-e0d7301cb04a99927091fdf51cec2d88fb68ad52.tar.bz2 scummvm-rg350-e0d7301cb04a99927091fdf51cec2d88fb68ad52.zip |
Parser update. Variable depth.
svn-id: r32690
-rw-r--r-- | gui/ThemeParser.cpp | 64 | ||||
-rw-r--r-- | gui/ThemeParser.h | 21 |
2 files changed, 64 insertions, 21 deletions
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 73086e942c..c75340ada2 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -43,20 +43,18 @@ namespace GUI { inline bool isValidNameChar(char c) { - return !isspace(c) && c != '/' && c != '*' && c != '\\' && - c != '|' && c != '"' && c != '\'' && c != ',' && - c != '<' && c != '>' && c != '='; + return isalnum(c) || c == '_'; } void ThemeParser::debug_testEval() { static const char *debug_config_text = "<drawdata id = \"background_default\" cache = true>" "<draw func = \"roundedsq\" /*/fill = \"gradient\" gradient_start = \"255, 255, 128\" gradient_end = \"128, 128, 128\" size = \"auto\"/>" - "/*<draw func = \"roundedsq\" fill = \"none\" color = \"0, 0, 0\" size = \"auto\"/>*/" + "<draw func = \"roundedsq\" fill = \"none\" color = \"0, 0, 0\" size = \"auto\"/>" "</drawdata>/* lol this is just a simple test*/"; _text = strdup(debug_config_text); - parseDrawData(); + parse(); } @@ -65,20 +63,42 @@ void ThemeParser::parserError(const char *error_string) { printf("PARSER ERROR: %s\n", error_string); } +void ThemeParser::parserCallback_DRAW() { + printf("Draw callback!\n"); +} + +void ThemeParser::parserCallback_DRAWDATA() { + printf("Drawdata callback!\n"); +} + void ThemeParser::parseActiveKey(bool closed) { printf("Parsed key %s.\n", _activeKey.top().c_str()); - for (Common::StringMap::const_iterator t = _keyValues.begin(); t != _keyValues.end(); ++t) + if (!_callbacks.contains(_activeKey.top())) { + parserError("Unhandled value inside key."); + return; + } + + // Don't you just love C++ syntax? Water clear. + (this->*(_callbacks[_activeKey.top()]))(); + + for (Common::StringMap::const_iterator t = _keyValues.top().begin(); t != _keyValues.top().end(); ++t) printf(" Key %s = %s\n", t->_key.c_str(), t->_value.c_str()); - if (closed) + if (closed) { + _keyValues.pop(); _activeKey.pop(); - - _keyValues.clear(); + } } void ThemeParser::parseKeyValue(Common::String &key_name) { assert(_text[_pos++] == '='); + assert(_keyValues.empty() == false); + + if (_keyValues.top().contains(key_name)) { + parserError("Repeated value inside key."); + return; + } while (isspace(_text[_pos])) _pos++; @@ -97,16 +117,20 @@ void ThemeParser::parseKeyValue(Common::String &key_name) { data += _text[_pos++]; } - _keyValues[key_name] = data; + _keyValues.top()[key_name] = data; } -bool ThemeParser::parseDrawData() { +bool ThemeParser::parse() { _state = kParserNeedKey; _pos = 0; _keyValues.clear(); + _activeKey.clear(); while (_text[_pos]) { + if (_state == kParserError) + break; + while (isspace(_text[_pos])) _pos++; @@ -124,7 +148,7 @@ bool ThemeParser::parseDrawData() { case kParserNeedKey: if (_text[_pos++] != '<') { parserError("Expecting key start."); - return false; + break; } if (_text[_pos] == '/') { @@ -133,8 +157,9 @@ bool ThemeParser::parseDrawData() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - if (_token == _activeKey.top()) { + if (!_activeKey.empty() && _token == _activeKey.top()) { _activeKey.pop(); + _keyValues.pop(); while (isspace(_text[_pos]) || _text[_pos] == '>') _pos++; @@ -142,10 +167,11 @@ bool ThemeParser::parseDrawData() { break; } else { parserError("Unexpected closure."); - return false; + break; } } + _keyValues.push(Common::StringMap()); _state = kParserKeyNeedName; break; @@ -156,7 +182,7 @@ bool ThemeParser::parseDrawData() { if (!isspace(_text[_pos]) && _text[_pos] != '>') { parserError("Invalid character in token name."); - return false; + break; } _state = kParserKeyNeedToken; @@ -182,17 +208,21 @@ bool ThemeParser::parseDrawData() { if (_text[_pos] != '=') { parserError("Unexpected character after key name."); - return false; + break; } parseKeyValue(_token); break; default: - return false; + break; } } + if (_state == kParserError) { + return false; + } + if (_state != kParserNeedKey || !_activeKey.empty()) { parserError("Unexpected end of file."); } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 527d911620..22ad50a333 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -38,8 +38,15 @@ namespace GUI { class ThemeParser { + static const int PARSER_MAX_DEPTH = 4; + typedef void (ThemeParser::*PARSER_CALLBACK)(); + public: - ThemeParser() {} + ThemeParser() { + _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; + _callbacks["draw"] = &ThemeParser::parserCallback_DRAW; + } + ~ThemeParser() {} enum ParserState { @@ -52,14 +59,18 @@ public: kParserSuccess }; - bool parseDrawData(); + bool parse(); void parseKeyValue(Common::String &key_name); void parseActiveKey(bool closed); + void parserError(const char *error_string); void debug_testEval(); protected: + void parserCallback_DRAW(); + void parserCallback_DRAWDATA(); + int _pos; char *_text; @@ -68,8 +79,10 @@ protected: Common::String _error; Common::String _token; - Common::FixedStack<Common::String, 5> _activeKey; - Common::StringMap _keyValues; + Common::FixedStack<Common::String, PARSER_MAX_DEPTH> _activeKey; + Common::FixedStack<Common::StringMap, PARSER_MAX_DEPTH> _keyValues; + + Common::HashMap<Common::String, PARSER_CALLBACK, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _callbacks; }; } |