00001
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <ctype.h>
00015
00016 #include "CTB.hxx"
00017 #include "CTB_Trace.hxx"
00018 #include "CTBosFill.hxx"
00019 #include "CTBexceptionBugcheck.hxx"
00020
00021 #include "CTBxmlLexer.hxx"
00022
00033
00035
00036 CTBxmlLexer::CTBxmlLexer()
00037 : mi_mode(0),
00038 mi_nline_t(1),
00039 mi_ncolumn_t(1),
00040 mi_nline_s(1),
00041 mi_ncolumn_s(1)
00042 {
00043 CTB_Trace("CTBxmlLexer()");
00044 }
00045
00046
00048
00049 void CTBxmlLexer::Get(istream& is, CTBxmlLexerToken& lt)
00050 {
00051 CTB_Trace("CTBxmlLexer::Get(istream&, CTBxmlLexerToken&)");
00052 int i_c1;
00053 int i_quote;
00054
00055 mi_nline_t = mi_nline_s;
00056 mi_ncolumn_t = mi_ncolumn_s;
00057
00058 lt.Clear();
00059
00060 i_c1 = GetChar(is);
00061
00062 if (i_c1 == EOF) {
00063 if (is.eof()) {
00064 lt.Type(CTBxmlLexerToken::eof);
00065 } else {
00066 lt.Type(CTBxmlLexerToken::fail);
00067 }
00068 return;
00069 }
00070
00071 lt += (char) i_c1;
00072
00073 switch (mi_mode) {
00074
00075 case tagordata:
00076 if (i_c1 == '<') {
00077 int i_cp = is.peek();
00078
00079 if (i_cp == '/') {
00080 lt += (char) GetChar(is);
00081 lt.Type(CTBxmlLexerToken::etagopen);
00082 return;
00083 }
00084
00085 if (i_cp == '?') {
00086 lt += (char) GetChar(is);
00087 lt.Type(CTBxmlLexerToken::piopen);
00088 return;
00089 }
00090
00091 if (i_cp == '!') {
00092 lt += (char) GetChar(is);
00093
00094 if (is.peek() == '-') {
00095 lt += (char) GetChar(is);
00096 if (is.peek() == '-') {
00097 int i_cstate = 0;
00098
00099 lt += (char) GetChar(is);
00100
00101 for (;;) {
00102 int i_c2 = GetChar(is);
00103
00104 if (i_c2 == EOF) {
00105 lt.Type(CTBxmlLexerToken::fail);
00106 return;
00107 }
00108
00109 lt += (char) i_c2;
00110 switch (i_cstate) {
00111 case 0:
00112 if (i_c2 == '-') i_cstate = 1;
00113 break;
00114 case 1:
00115 i_cstate = (i_c2 == '-') ? 2 : 0;
00116 break;
00117 case 2:
00118 if (i_c2 == '>') {
00119 lt.Type(CTBxmlLexerToken::comment);
00120 return;
00121 }
00122 if (i_c2 != '-') i_cstate = 0;
00123 break;
00124 }
00125 }
00126 return;
00127
00128 } else {
00129 lt.Type(CTBxmlLexerToken::fail);
00130 return;
00131 }
00132 }
00133
00134 lt.Type(CTBxmlLexerToken::defopen);
00135 return;
00136 }
00137
00138 lt.Type(CTBxmlLexerToken::tagopen);
00139 return;
00140 }
00141
00142 if (i_c1 == '&') {
00143 GetEntity(is,lt);
00144 return;
00145 }
00146
00147 if (isspace(i_c1)) {
00148 GetWhite(is,lt);
00149 return;
00150 }
00151
00152 lt.Type(CTBxmlLexerToken::data);
00153 for (;;) {
00154 int i_c2 = is.peek();
00155
00156 if (i_c2 == EOF) break;
00157 if (isspace(i_c2)) break;
00158 if (i_c2 == '<' || i_c2 == '&') break;
00159
00160 lt += (char) GetChar(is);
00161 }
00162 return;
00163
00164 case tagattr:
00165 if (i_c1 == '/') {
00166 if (is.peek() == '>') {
00167 lt += (char) GetChar(is);
00168 lt.Type(CTBxmlLexerToken::etagclose);
00169 return;
00170 }
00171 return;
00172 }
00173
00174 if (i_c1 == '?') {
00175 if (is.peek() == '>') {
00176 lt += (char) GetChar(is);
00177 lt.Type(CTBxmlLexerToken::piclose);
00178 return;
00179 }
00180 return;
00181 }
00182
00183 if (i_c1 == '>') {
00184 lt.Type(CTBxmlLexerToken::tagclose);
00185 return;
00186 }
00187
00188 if (i_c1 == '=') {
00189 lt.Type(CTBxmlLexerToken::equal);
00190 return;
00191 }
00192
00193 if (isspace(i_c1)) {
00194 GetWhite(is,lt);
00195 return;
00196 }
00197
00198 if (isalpha(i_c1) || i_c1 == '_' || i_c1 == ':') {
00199 GetName(is,lt);
00200 return;
00201 }
00202 return;
00203
00204 case attrval:
00205 if (i_c1 == '\'') {
00206 lt.Type(CTBxmlLexerToken::squote);
00207 return;
00208 }
00209
00210 if (i_c1 == '"') {
00211 lt.Type(CTBxmlLexerToken::dquote);
00212 return;
00213 }
00214
00215 if (isspace(i_c1)) {
00216 GetWhite(is,lt);
00217 return;
00218 }
00219
00220 if (isalpha(i_c1) || i_c1 == '_' || i_c1 == ':') {
00221 GetName(is,lt);
00222 return;
00223 }
00224 return;
00225
00226 case valsquote:
00227 case valdquote:
00228 i_quote = (mi_mode == valsquote) ? '\'' : '"';
00229
00230 if (mi_mode == valsquote && i_c1 == '\'') {
00231 lt.Type(CTBxmlLexerToken::squote);
00232 return;
00233 }
00234
00235 if (mi_mode == valdquote && i_c1 == '"') {
00236 lt.Type(CTBxmlLexerToken::dquote);
00237 return;
00238 }
00239
00240 if (i_c1 == '&') {
00241 GetEntity(is,lt);
00242 return;
00243 }
00244
00245 if (isspace(i_c1)) {
00246 GetWhite(is,lt);
00247 return;
00248 }
00249
00250 lt.Type(CTBxmlLexerToken::data);
00251 for (;;) {
00252 int i_c2 = is.peek();
00253
00254 if (i_c2 == EOF) break;
00255 if (isspace(i_c2)) break;
00256 if (i_c2 == '<' || i_c2 == '&') break;
00257 if (i_c2 == i_quote) break;
00258
00259 lt += (char) GetChar(is);
00260 }
00261 return;
00262
00263 default:
00264 throw CTBexceptionBugcheck("illegal state","CTBxmlLexer::Get()");
00265 }
00266 return;
00267 }
00268
00269
00271
00272 void CTBxmlLexer::Clear()
00273 {
00274 CTB_Trace("CTBxmlLexer::Clear()");
00275
00276 mi_nline_t = 1;
00277 mi_ncolumn_t = 1;
00278 mi_nline_s = 1;
00279 mi_ncolumn_s = 1;
00280 return;
00281 }
00282
00283
00285
00286 void CTBxmlLexer::Dump(int i_indent, ostream& os, const char* p_text) const
00287 {
00288 CTBosFill bl(i_indent);
00289
00290 os << bl << "--CTBxmlLexer ";
00291 if (p_text) os << p_text;
00292 os << " @ " << this << endl;
00293
00294 os << bl << " mi_mode: " << mi_mode << endl;
00295 os << bl << " mi_nline_t: " << mi_nline_t << endl;
00296 os << bl << " mi_ncolumn_t: " << mi_ncolumn_t << endl;
00297 os << bl << " mi_nline_s: " << mi_nline_s << endl;
00298 os << bl << " mi_ncolumn_s: " << mi_ncolumn_s << endl;
00299
00300 return;
00301 }
00302
00303
00305
00306 int CTBxmlLexer::GetChar(istream& is)
00307 {
00308 CTB_Trace("CTBxmlLexer::GetChar(istream&)");
00309 int i_char = is.get();
00310
00311 if (i_char != EOF) {
00312 if (i_char == '\n') {
00313 mi_nline_s += 1;
00314 mi_ncolumn_s = 1;
00315 } else {
00316 mi_ncolumn_s += 1;
00317 }
00318 }
00319 return i_char;
00320 }
00321
00322
00324
00325 void CTBxmlLexer::GetEntity(istream& is, CTBxmlLexerToken& lt)
00326 {
00327 CTB_Trace("CTBxmlLexer::GetEntity(istream&, CTBxmlLexerToken&)");
00328
00329 if (is.peek() == '#') {
00330 lt += (char) GetChar(is);
00331 lt.Type(CTBxmlLexerToken::charref);
00332 } else {
00333 lt.Type(CTBxmlLexerToken::entref);
00334 }
00335
00336 for (;;) {
00337 int i_c2 = GetChar(is);
00338
00339 if (i_c2 == EOF) {
00340 lt.Type(CTBxmlLexerToken::fail);
00341 return;
00342 }
00343
00344 lt += (char) i_c2;
00345 if (i_c2 == ';') break;
00346 }
00347 return;
00348 }
00349
00350
00352
00353 void CTBxmlLexer::GetWhite(istream& is, CTBxmlLexerToken& lt)
00354 {
00355 CTB_Trace("CTBxmlLexer::GetWhite(istream&, CTBxmlLexerToken&)");
00356
00357 lt.Type(CTBxmlLexerToken::white);
00358 while(isspace(is.peek())) {
00359 lt += (char) GetChar(is);
00360 }
00361 return;
00362 }
00363
00364
00366
00367 void CTBxmlLexer::GetName(istream& is, CTBxmlLexerToken& lt)
00368 {
00369 CTB_Trace("CTBxmlLexer::GetName(istream&, CTBxmlLexerToken&)");
00370
00371 lt.Type(CTBxmlLexerToken::name);
00372 for (;;) {
00373 int i_c2 = is.peek();
00374 if (isalnum(i_c2) || i_c2 == '.' || i_c2 == '-' ||
00375 i_c2 == '_' || i_c2 == ':') {
00376 lt += GetChar(is);
00377 } else {
00378 break;
00379 }
00380 }
00381 return;
00382 }
00383
00384
00385
00396
00398
00399 void CTBxmlLexerToken::ToStream(ostream& os) const
00400 {
00401 os << "type: ";
00402
00403 switch (Type()) {
00404 case invalid: os << "invalid"; break;
00405 case fail: os << "fail"; break;
00406 case eof: os << "eof"; break;
00407 case tagopen: os << "tagopen"; break;
00408 case etagopen: os << "etagopen"; break;
00409 case tagclose: os << "tagclose"; break;
00410 case etagclose: os << "etagclose"; break;
00411 case comment: os << "comment"; break;
00412 case defopen: os << "defopen"; break;
00413 case piopen: os << "piopen"; break;
00414 case piclose: os << "piclose"; break;
00415 case charref: os << "charref"; break;
00416 case entref: os << "entref"; break;
00417 case equal: os << "equal"; break;
00418 case squote: os << "squote"; break;
00419 case dquote: os << "dquote"; break;
00420 case name: os << "name"; break;
00421 case white: os << "white"; break;
00422 case data: os << "data"; break;
00423 default: os << "???"; break;
00424 }
00425
00426 os << " -- \"" << m_text.Escape() << "\"";
00427
00428 return;
00429 }
00430
00431
00433
00434 void CTBxmlLexerToken::Dump(int i_indent, ostream& os, const char* p_text) const
00435 {
00436 CTBosFill bl(i_indent);
00437
00438 os << bl << "--CTBxmlLexerToken ";
00439 if (p_text) os << p_text;
00440 os << " @ " << this << endl;
00441
00442 os << bl << " mi_type: " << mi_type << endl;
00443 m_text.Dump(i_indent+2,os,"m_text");
00444
00445 return;
00446 }