diff options
-rw-r--r-- | base/main.cpp | 3 | ||||
-rw-r--r-- | gui/ThemeParser.cpp | 119 | ||||
-rw-r--r-- | gui/ThemeParser.h | 17 |
3 files changed, 124 insertions, 15 deletions
diff --git a/base/main.cpp b/base/main.cpp index 45e0aef728..d0da338e2a 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -43,6 +43,7 @@ #include "gui/newgui.h" #include "gui/message.h" #include "gui/InterfaceManager.h" +#include "gui/ThemeParser.h" #if defined(_WIN32_WCE) #include "backends/platform/wince/CELauncherDialog.h" @@ -70,6 +71,8 @@ static bool launcherDialog(OSystem &system) { #if 1 + GUI::ThemeParser parser; + parser.debug_testEval(); g_InterfaceManager.runGUI(); return true; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 26745ac5a6..73086e942c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -26,6 +26,8 @@ #include "common/util.h" #include "common/system.h" #include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" #include "gui/ThemeParser.h" @@ -46,39 +48,104 @@ inline bool isValidNameChar(char c) { c != '<' && 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\"/>*/" + "</drawdata>/* lol this is just a simple test*/"; + + _text = strdup(debug_config_text); + parseDrawData(); +} + + void ThemeParser::parserError(const char *error_string) { _state = kParserError; + printf("PARSER ERROR: %s\n", error_string); +} + +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) + printf(" Key %s = %s\n", t->_key.c_str(), t->_value.c_str()); + + if (closed) + _activeKey.pop(); + + _keyValues.clear(); +} + +void ThemeParser::parseKeyValue(Common::String &key_name) { + assert(_text[_pos++] == '='); + + while (isspace(_text[_pos])) + _pos++; + + Common::String data; + + if (_text[_pos] == '"') { + data += _text[_pos++]; + + while (_text[_pos] != '"') + data += _text[_pos++]; + + data += _text[_pos++]; + } else { + while (isValidNameChar(_text[_pos])) + data += _text[_pos++]; + } + + _keyValues[key_name] = data; } bool ThemeParser::parseDrawData() { _state = kParserNeedKey; + _pos = 0; + _keyValues.clear(); - while (_text[_pos++]) { - + while (_text[_pos]) { while (isspace(_text[_pos])) _pos++; // comment handling: skip everything between /* and */ - if (_text[_pos] == '/') { - if (_text[++_pos] != '*') { - parserError("Malformed comment string."); - return false; + if (_text[_pos] == '/' && _text[_pos + 1] == '*') { + _pos += 2; + while (_text[_pos++]) { + if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') + break; } - - _pos++; - - while (_text[_pos] != '*' && _text[_pos + 1] != '/') - _pos++; + continue; } switch (_state) { case kParserNeedKey: - if (_text[_pos] != '<') { + if (_text[_pos++] != '<') { parserError("Expecting key start."); return false; } + if (_text[_pos] == '/') { + _pos++; + _token.clear(); + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + if (_token == _activeKey.top()) { + _activeKey.pop(); + + while (isspace(_text[_pos]) || _text[_pos] == '>') + _pos++; + + break; + } else { + parserError("Unexpected closure."); + return false; + } + } + _state = kParserKeyNeedName; break; @@ -87,16 +154,38 @@ bool ThemeParser::parseDrawData() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - if (!isspace(_text[_pos])) { + if (!isspace(_text[_pos]) && _text[_pos] != '>') { parserError("Invalid character in token name."); return false; } _state = kParserKeyNeedToken; + _activeKey.push(_token); break; case kParserKeyNeedToken: _token.clear(); + + if ((_text[_pos] == '/' && _text[_pos + 1] == '>') || _text[_pos] == '>') { + bool closed = _text[_pos] == '/'; + parseActiveKey(closed); + _pos += closed ? 2 : 1; + _state = kParserNeedKey; + break; + } + + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + while (isspace(_text[_pos])) + _pos++; + + if (_text[_pos] != '=') { + parserError("Unexpected character after key name."); + return false; + } + + parseKeyValue(_token); break; default: @@ -104,6 +193,10 @@ bool ThemeParser::parseDrawData() { } } + if (_state != kParserNeedKey || !_activeKey.empty()) { + parserError("Unexpected end of file."); + } + return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c43088c36e..527d911620 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -30,10 +30,15 @@ #include "graphics/surface.h" #include "common/system.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/stack.h" + namespace GUI { class ThemeParser { +public: ThemeParser() {} ~ThemeParser() {} @@ -43,11 +48,16 @@ class ThemeParser { kParserKeyNeedSubkey, kParserNeedKey, kParserInComment, - kParserError + kParserError, + kParserSuccess }; bool parseDrawData(); + void parseKeyValue(Common::String &key_name); + void parseActiveKey(bool closed); void parserError(const char *error_string); + + void debug_testEval(); protected: int _pos; @@ -57,8 +67,11 @@ protected: Common::String _error; Common::String _token; + + Common::FixedStack<Common::String, 5> _activeKey; + Common::StringMap _keyValues; }; } -#endif
\ No newline at end of file +#endif |