From ace171e22f98f9f9195447893b12fcf4ea79561c Mon Sep 17 00:00:00 2001
From: Vicent Marti
Date: Thu, 12 Jun 2008 23:13:58 +0000
Subject: Parser update.
svn-id: r32686
---
 gui/ThemeParser.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++++++------
 gui/ThemeParser.h   |  17 +++++++-
 2 files changed, 121 insertions(+), 15 deletions(-)
(limited to 'gui')
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 =
+		""
+		""
+		"/**/"
+		"/* 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 _activeKey;
+	Common::StringMap _keyValues;
 };
 
 }
 
-#endif
\ No newline at end of file
+#endif
-- 
cgit v1.2.3