Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "TsBuilder.h"
00025 # include "TsErrataUtil.h"
00026 # include "TsConfigLexer.h"
00027 # include "TsConfigGrammar.hpp"
00028 # include <stdlib.h>
00029
00030
00031 # define PRE "Configuration Parser: "
00032
00033 namespace {
00034
00035
00036
00037 size_t unescape_string(char* text, size_t len) {
00038 size_t zret = len;
00039
00040 char* dst = static_cast<char*>(memchr(text, '\\', len));
00041 if (dst) {
00042 char* limit = text + len;
00043 char* src = dst + 1;
00044 for ( *dst++ = *src++ ; src < limit ; ++src )
00045 if ('\\' != *src) *dst++ = *src;
00046 else if (++src < limit) *dst++ = *src;
00047 else *dst++ = '\\';
00048 zret = dst - text;
00049 }
00050 return zret;
00051 }
00052 }
00053
00054 namespace ts { namespace config {
00055
00056 Builder&
00057 Builder::init() {
00058
00059
00060
00061
00062
00063
00064 memset(_dispatch, 0, sizeof(_dispatch));
00065
00066 for ( size_t i = 0 ; i < TS_CONFIG_N_EVENT_TYPES ; ++i) {
00067 _dispatch[i]._ptr = this;
00068 _handlers.handler[i]._f = &self::dispatch;
00069 _handlers.handler[i]._data = &(_dispatch[i]);
00070 }
00071
00072 _dispatch[TsConfigEventGroupOpen]._method = &self::groupOpen;
00073 _dispatch[TsConfigEventGroupName]._method = &self::groupName;
00074 _dispatch[TsConfigEventGroupClose]._method = &self::groupClose;
00075 _dispatch[TsConfigEventListOpen]._method = &self::listOpen;
00076 _dispatch[TsConfigEventListClose]._method = &self::listClose;
00077 _dispatch[TsConfigEventPathOpen]._method = &self::pathOpen;
00078 _dispatch[TsConfigEventPathTag]._method = &self::pathTag;
00079 _dispatch[TsConfigEventPathIndex]._method = &self::pathIndex;
00080 _dispatch[TsConfigEventPathClose]._method = &self::pathClose;
00081 _dispatch[TsConfigEventLiteralValue]._method = &self::literalValue;
00082 _dispatch[TsConfigEventInvalidToken]._method = &self::invalidToken;
00083
00084 _handlers.error._data = this;
00085 _handlers.error._f = &self::syntaxErrorDispatch;
00086
00087 return *this;
00088 }
00089
00090
00091
00092 void
00093 Builder::dispatch(void* data, Token* token) {
00094 if (data) {
00095 Handler* handler = reinterpret_cast<Handler*>(data);
00096 if (handler->_ptr) {
00097 if (handler->_method) {
00098 ((handler->_ptr)->*(handler->_method))(*token);
00099 } else {
00100 msg::logf(msg::WARN, PRE "Unable to dispatch event - no method.");
00101 }
00102 } else {
00103 msg::logf(msg::WARN, PRE "Unable to dispatch event - no builder.");
00104 }
00105 } else {
00106 msg::logf(msg::WARN, PRE "Unable to dispatch event - no handler.");
00107 }
00108 }
00109
00110 int
00111 Builder::syntaxErrorDispatch(void* data, char const* text) {
00112 return reinterpret_cast<Builder*>(data)->syntaxError(text);
00113 }
00114
00115 int
00116 Builder::syntaxError(char const* text) {
00117 msg::logf(_errata, msg::WARN,
00118 "Syntax error '%s' near line %d, column %d.",
00119 text, tsconfiglex_current_line(), tsconfiglex_current_col()
00120 );
00121 return 0;
00122 }
00123
00124 Rv<Configuration>
00125 Builder::build(Buffer const& buffer) {
00126 _v = _config.getRoot();
00127 _errata.clear();
00128 tsconfig_parse_buffer(&_handlers, buffer._ptr, buffer._size);
00129 return MakeRv(_config, _errata);
00130 }
00131
00132 void
00133 Builder::groupOpen(Token const& token) {
00134 _v = _v.makeGroup(_name);
00135 _v.setSource(token._loc._line, token._loc._col);
00136 }
00137 void Builder::groupClose(Token const&) {
00138 _v = _v.getParent();
00139 }
00140 void Builder::groupName(Token const& token) {
00141 _name.set(token._s, token._n);
00142 }
00143 void Builder::listOpen(Token const& token) {
00144 _v = _v.makeList(_name);
00145 _v.setSource(token._loc._line, token._loc._col);
00146 }
00147 void Builder::listClose(Token const&) {
00148 _v = _v.getParent();
00149 }
00150
00151 void Builder::pathOpen(Token const&) {
00152 _path.reset();
00153 _extent.reset();
00154 }
00155 void Builder::pathTag(Token const& token) {
00156 _path.append(Buffer(token._s, token._n));
00157 if (_extent._ptr) {
00158 _extent._size = token._s - _extent._ptr + token._n;
00159 } else {
00160 _extent.set(token._s, token._n);
00161 _loc = token._loc;
00162 }
00163 }
00164 void Builder::pathIndex(Token const& token){
00165
00166
00167
00168 _path.append(Buffer(0, static_cast<size_t>(atol(token._s))));
00169 if (_extent._ptr) _extent._size = token._s - _extent._ptr + token._n;
00170 else _extent.set(token._s, token._n);
00171 }
00172
00173 void Builder::pathClose(Token const&) {
00174 Rv<Value> cv = _v.makePath(_path, _name);
00175 if (cv.isOK()) {
00176 cv.result().setText(_extent).setSource(_loc._line, _loc._col);
00177
00178
00179 _extent._ptr[_extent._size] = 0;
00180 }
00181 _name.reset();
00182 _extent.reset();
00183 }
00184
00185 void Builder::literalValue(Token const& token) {
00186 Rv<Value> cv;
00187 Buffer text(token._s, token._n);
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 if (INTEGER == token._type) {
00198 cv = _v.makeInteger(text, _name);
00199 token._s[token._n] = 0;
00200 } else if (STRING == token._type) {
00201 ++text._ptr, text._size -= 2;
00202 text._size = unescape_string(text._ptr, text._size);
00203 text._ptr[text._size] = 0;
00204 cv = _v.makeString(text, _name);
00205 } else {
00206 msg::logf(_errata, msg::WARN, PRE "Unexpected literal type %d.", token._type);
00207 }
00208 if (!cv.isOK()) _errata.pull(cv.errata());
00209 if (cv.result()) cv.result().setSource(token._loc._line, token._loc._col);
00210 _name.set(0,0);
00211 }
00212 void Builder::invalidToken(Token const&) { }
00213
00214 }}