SNAP Library 2.1, User Reference
2013-09-25 10:47:25
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 00002 // Lexical-Chars 00003 void TLxChDef::SetUcCh(const TStr& Str){ 00004 for (int CC=1; CC<Str.Len(); CC++){ 00005 UcChV[Str[CC]-TCh::Mn]=TCh(Str[0]);} 00006 } 00007 00008 void TLxChDef::SetChTy(const TLxChTy& ChTy, const TStr& Str){ 00009 for (int CC=0; CC<Str.Len(); CC++){ 00010 ChTyV[Str[CC]-TCh::Mn]=TInt(ChTy);} 00011 } 00012 00013 TLxChDef::TLxChDef(const TLxChDefTy& ChDefTy): 00014 ChTyV(TCh::Vals), UcChV(TCh::Vals){ 00015 00016 if (ChDefTy==lcdtUsAscii){ 00017 // Character-Types 00018 ChTyV.PutAll(TInt(lctSpace)); 00019 SetChTy(lctNum, "0123456789"); 00020 SetChTy(lctAlpha, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 00021 SetChTy(lctAlpha, "abcdefghijklmnopqrstuvwxyz"); 00022 SetChTy(lctAlpha, "@_"); 00023 SetChTy(lctSSym, "\"'.,:;+-*/%!#|&<=>?()[]{}"); 00024 SetChTy(lctTerm, TStr(TCh::CrCh)); 00025 SetChTy(lctTerm, TStr(TCh::LfCh)); 00026 SetChTy(lctTerm, TStr(TCh::EofCh)); 00027 00028 // Upper-Case 00029 for (int Ch=TCh::Mn; Ch<=TCh::Mx; Ch++){UcChV[Ch-TCh::Mn]=TCh(char(Ch));} 00030 SetUcCh("Aa"); SetUcCh("Bb"); SetUcCh("Cc"); SetUcCh("Dd"); SetUcCh("Ee"); 00031 SetUcCh("Ff"); SetUcCh("Gg"); SetUcCh("Hh"); SetUcCh("Ii"); SetUcCh("Jj"); 00032 SetUcCh("Kk"); SetUcCh("Ll"); SetUcCh("Mm"); SetUcCh("Nn"); SetUcCh("Oo"); 00033 SetUcCh("Pp"); SetUcCh("Qq"); SetUcCh("Rr"); SetUcCh("Ss"); SetUcCh("Tt"); 00034 SetUcCh("Uu"); SetUcCh("Vv"); SetUcCh("Ww"); SetUcCh("Xx"); SetUcCh("Yy"); 00035 SetUcCh("Zz"); 00036 } else 00037 if (ChDefTy==lcdtYuAscii){ 00038 // Character-Types 00039 ChTyV.PutAll(TInt(lctSpace)); 00040 SetChTy(lctNum, "0123456789"); 00041 SetChTy(lctAlpha, "ABC^]D\\EFGHIJKLMNOPQRS[TUVWXYZ@"); 00042 SetChTy(lctAlpha, "abc~}d|efghijklmnopqrs{tuvwxyz`"); 00043 SetChTy(lctAlpha, "_"); 00044 SetChTy(lctSSym, "\".,:;+-*/%!#&<=>?()"); 00045 SetChTy(lctTerm, TStr(TCh::CrCh)); 00046 SetChTy(lctTerm, TStr(TCh::LfCh)); 00047 SetChTy(lctTerm, TStr(TCh::EofCh)); 00048 00049 // Upper-Case 00050 for (int Ch=TCh::Mn; Ch<=TCh::Mx; Ch++){UcChV[Ch-TCh::Mn]=TCh(char(Ch));} 00051 SetUcCh("Aa"); SetUcCh("Bb"); SetUcCh("Cc"); SetUcCh("^~"); SetUcCh("]}"); 00052 SetUcCh("Dd"); SetUcCh("\\|"); SetUcCh("Ee"); SetUcCh("Ff"); SetUcCh("Gg"); 00053 SetUcCh("Hh"); SetUcCh("Ii"); SetUcCh("Jj"); SetUcCh("Kk"); SetUcCh("Ll"); 00054 SetUcCh("Mm"); SetUcCh("Nn"); SetUcCh("Oo"); SetUcCh("Pp"); SetUcCh("Qq"); 00055 SetUcCh("Rr"); SetUcCh("Ss"); SetUcCh("[{"); SetUcCh("Tt"); SetUcCh("Uu"); 00056 SetUcCh("Vv"); SetUcCh("Ww"); SetUcCh("Xx"); SetUcCh("Yy"); SetUcCh("Zz"); 00057 SetUcCh("@`"); 00058 } else { 00059 Fail; 00060 } 00061 } 00062 00063 bool TLxChDef::IsNmStr(const TStr& Str) const { 00064 if (Str.Len()==0){return false;} 00065 if (!IsAlpha(Str.GetCh(0))){return false;} 00066 for (int ChN=1; ChN<Str.Len(); ChN++){ 00067 if (!IsAlNum(Str.GetCh(ChN))){return false;}} 00068 return true; 00069 } 00070 00071 TStr TLxChDef::GetUcStr(const TStr& Str) const { 00072 TChA UcStr; 00073 for (int ChN=0; ChN<Str.Len(); ChN++){ 00074 UcStr.AddCh(GetUc(Str.GetCh(ChN)));} 00075 return UcStr; 00076 } 00077 00078 00079 PLxChDef TLxChDef::GetChDef(const TLxChDefTy& ChDefTy){ 00080 static PLxChDef UsAsciiChDef=NULL; 00081 static PLxChDef YuAsciiChDef=NULL; 00082 switch (ChDefTy){ 00083 case lcdtUsAscii: 00084 if (UsAsciiChDef.Empty()){UsAsciiChDef=TLxChDef::New(lcdtUsAscii);} 00085 return UsAsciiChDef; 00086 case lcdtYuAscii: 00087 if (YuAsciiChDef.Empty()){YuAsciiChDef=TLxChDef::New(lcdtYuAscii);} 00088 return YuAsciiChDef; 00089 default: Fail; return NULL; 00090 } 00091 } 00092 00093 //TLxChDef& TLxChDef::GetChDefRef(const TLxChDefTy& ChDefTy){ 00094 // switch (ChDefTy){ 00095 // case lcdtUsAscii: return *UsAsciiChDef; 00096 // case lcdtYuAscii: return *YuAsciiChDef; 00097 // default: Fail; return *UsAsciiChDef;; 00098 // } 00099 //} 00100 00102 // Lexical-Symbols 00103 const TStr TLxSymStr::UndefStr="<undefined>"; 00104 const TStr TLxSymStr::LnStr="<line>"; 00105 const TStr TLxSymStr::TabStr="<tab>"; 00106 const TStr TLxSymStr::IntStr="<integer>"; 00107 const TStr TLxSymStr::FltStr="<float>"; 00108 const TStr TLxSymStr::StrStr="<string>"; 00109 const TStr TLxSymStr::IdStrStr="<id-string>"; 00110 const TStr TLxSymStr::QStrStr="<q-string>"; 00111 const TStr TLxSymStr::PeriodStr="."; 00112 const TStr TLxSymStr::DPeriodStr=".."; 00113 const TStr TLxSymStr::CommaStr=","; 00114 const TStr TLxSymStr::ColonStr=":"; 00115 const TStr TLxSymStr::DColonStr="::"; 00116 const TStr TLxSymStr::SemicolonStr=";"; 00117 const TStr TLxSymStr::PlusStr="+"; 00118 const TStr TLxSymStr::MinusStr="-"; 00119 const TStr TLxSymStr::AsteriskStr="*"; 00120 const TStr TLxSymStr::SlashStr="/"; 00121 const TStr TLxSymStr::PercentStr="%"; 00122 const TStr TLxSymStr::ExclamationStr="!"; 00123 const TStr TLxSymStr::VBarStr="|"; 00124 const TStr TLxSymStr::AmpersandStr="&"; 00125 const TStr TLxSymStr::QuestionStr="?"; 00126 const TStr TLxSymStr::HashStr="#"; 00127 const TStr TLxSymStr::EqStr="="; 00128 const TStr TLxSymStr::NEqStr="<>"; 00129 const TStr TLxSymStr::LssStr="<"; 00130 const TStr TLxSymStr::GtrStr=">"; 00131 const TStr TLxSymStr::LEqStr="<="; 00132 const TStr TLxSymStr::GEqStr=">="; 00133 const TStr TLxSymStr::LParenStr="("; 00134 const TStr TLxSymStr::RParenStr=")"; 00135 const TStr TLxSymStr::LBracketStr="["; 00136 const TStr TLxSymStr::RBracketStr="]"; 00137 const TStr TLxSymStr::LBraceStr="{"; 00138 const TStr TLxSymStr::RBraceStr="}"; 00139 const TStr TLxSymStr::EolnStr="<end-of-line>"; 00140 const TStr TLxSymStr::EofStr="<end-of-file>"; 00141 00142 TStr TLxSymStr::GetSymStr(const TLxSym& Sym){ 00143 switch (Sym){ 00144 case syUndef: return UndefStr; 00145 case syLn: return LnStr; 00146 case syTab: return TabStr; 00147 case syInt: return IntStr; 00148 case syFlt: return FltStr; 00149 case syStr: return StrStr; 00150 case syIdStr: return IdStrStr; 00151 case syQStr: return QStrStr; 00152 case syPeriod: return PeriodStr; 00153 case syDPeriod: return DPeriodStr; 00154 case syComma: return CommaStr; 00155 case syColon: return ColonStr; 00156 case syDColon: return DColonStr; 00157 case sySemicolon: return SemicolonStr; 00158 case syPlus: return PlusStr; 00159 case syMinus: return MinusStr; 00160 case syAsterisk: return AsteriskStr; 00161 case sySlash: return SlashStr; 00162 case syPercent: return PercentStr; 00163 case syExclamation: return ExclamationStr; 00164 case syVBar: return VBarStr; 00165 case syAmpersand: return AmpersandStr; 00166 case syQuestion: return QuestionStr; 00167 case syHash: return HashStr; 00168 case syEq: return EqStr; 00169 case syNEq: return NEqStr; 00170 case syLss: return LssStr; 00171 case syGtr: return GtrStr; 00172 case syLEq: return LEqStr; 00173 case syGEq: return GEqStr; 00174 case syLParen: return LParenStr; 00175 case syRParen: return RParenStr; 00176 case syLBracket: return LBracketStr; 00177 case syRBracket: return RBracketStr; 00178 case syLBrace: return LBraceStr; 00179 case syRBrace: return RBraceStr; 00180 case syEoln: return EolnStr; 00181 case syEof: return EofStr; 00182 default: Fail; return TStr(); 00183 } 00184 } 00185 00186 TLxSym TLxSymStr::GetSSym(const TStr& Str){ 00187 static TStrIntH StrToLxSymH(100); 00188 if (StrToLxSymH.Len()==0){ 00189 StrToLxSymH.AddDat(PeriodStr, syPeriod); 00190 StrToLxSymH.AddDat(DPeriodStr, syDPeriod); 00191 StrToLxSymH.AddDat(CommaStr, syComma); 00192 StrToLxSymH.AddDat(ColonStr, syColon); 00193 StrToLxSymH.AddDat(DColonStr, syDColon); 00194 StrToLxSymH.AddDat(SemicolonStr, sySemicolon); 00195 StrToLxSymH.AddDat(PlusStr, syPlus); 00196 StrToLxSymH.AddDat(MinusStr, syMinus); 00197 StrToLxSymH.AddDat(AsteriskStr, syAsterisk); 00198 StrToLxSymH.AddDat(SlashStr, sySlash); 00199 StrToLxSymH.AddDat(PercentStr, syPercent); 00200 StrToLxSymH.AddDat(ExclamationStr, syExclamation); 00201 StrToLxSymH.AddDat(VBarStr, syVBar); 00202 StrToLxSymH.AddDat(AmpersandStr, syAmpersand); 00203 StrToLxSymH.AddDat(QuestionStr, syQuestion); 00204 StrToLxSymH.AddDat(HashStr, syHash); 00205 StrToLxSymH.AddDat(EqStr, syEq); 00206 StrToLxSymH.AddDat(NEqStr, syNEq); 00207 StrToLxSymH.AddDat(LssStr, syLss); 00208 StrToLxSymH.AddDat(GtrStr, syGtr); 00209 StrToLxSymH.AddDat(LEqStr, syLEq); 00210 StrToLxSymH.AddDat(GEqStr, syGEq); 00211 StrToLxSymH.AddDat(LParenStr, syLParen); 00212 StrToLxSymH.AddDat(RParenStr, syRParen); 00213 StrToLxSymH.AddDat(LBracketStr, syLBracket); 00214 StrToLxSymH.AddDat(RBracketStr, syRBracket); 00215 StrToLxSymH.AddDat(LBraceStr, syLBrace); 00216 StrToLxSymH.AddDat(RBraceStr, syRBrace); 00217 } 00218 int KeyId=StrToLxSymH.GetKeyId(Str); 00219 if (KeyId==-1){ 00220 return syUndef; 00221 } else { 00222 return TLxSym(int(StrToLxSymH[KeyId])); 00223 } 00224 } 00225 00226 bool TLxSymStr::IsSep(const TLxSym& PrevSym, const TLxSym& Sym){ 00227 static TFSet SepPrevSymSet=TFSet()| 00228 syUndef|syColon|syDColon|syEq| 00229 syLParen|syRParen|syLBracket|syRBracket|syLBrace|syRBrace| 00230 syEoln|syEof; 00231 00232 static TFSet SepSymSet=TFSet()| 00233 syPeriod|syComma|syColon|syDColon|sySemicolon| 00234 syEq| 00235 syExclamation|syQuestion| 00236 syLParen|syRParen|syLBracket|syRBracket|syLBrace|syRBrace| 00237 syEoln|syEof; 00238 00239 return !SepPrevSymSet.In(PrevSym) && !SepSymSet.In(Sym); 00240 } 00241 00243 // Lexical-Symbol-State 00244 TILxSymSt::TILxSymSt(): 00245 Sym(syUndef), 00246 Str(), UcStr(), CmtStr(), 00247 Bool(false), Int(0), Flt(0), 00248 SymLnN(-1), SymLnChN(-1), SymChN(-1){} 00249 00250 TILxSymSt::TILxSymSt(const TILxSymSt& SymSt): 00251 Sym(SymSt.Sym), 00252 Str(SymSt.Str), UcStr(SymSt.UcStr), CmtStr(SymSt.CmtStr), 00253 Bool(SymSt.Bool), Int(SymSt.Int), Flt(SymSt.Flt), 00254 SymLnN(SymSt.SymLnN), SymLnChN(SymSt.SymLnChN), SymChN(SymSt.SymChN){Fail;} 00255 00256 TILxSymSt::TILxSymSt(TILx& Lx): 00257 Sym(Lx.Sym), 00258 Str(Lx.Str), UcStr(Lx.UcStr), CmtStr(Lx.CmtStr), 00259 Bool(Lx.Bool), Int(Lx.Int), Flt(Lx.Flt), 00260 SymLnN(Lx.SymLnN), SymLnChN(Lx.SymLnChN), SymChN(Lx.SymChN){} 00261 00262 void TILxSymSt::Restore(TILx& Lx){ 00263 Lx.Sym=Sym; 00264 Lx.Str=Str; Lx.UcStr=UcStr; Lx.CmtStr=CmtStr; 00265 Lx.Bool=Bool; Lx.Int=Int; Lx.Flt=Flt; 00266 Lx.SymLnN=SymLnN; Lx.SymLnChN=SymLnChN; Lx.SymChN=Lx.SymChN;} 00267 00269 // Lexical-Input 00270 TILx::TILx(const PSIn& _SIn, const TFSet& OptSet, const TLxChDefTy& ChDefTy): 00271 ChDef(TLxChDef::GetChDef(ChDefTy)), 00272 SIn(_SIn), RSIn(*SIn), 00273 PrevCh(' '), Ch(' '), LnN(0), LnChN(0-1), ChN(0-1), 00274 PrevSymStStack(), RwStrH(50), 00275 IsCmtAlw(false), IsRetEoln(false), IsSigNum(false), 00276 IsUniStr(false), IsCsSens(false), IsExcept(false), 00277 IsTabSep(false), IsList(false), 00278 Sym(syUndef), 00279 Str(), UcStr(), CmtStr(), 00280 Bool(false), Int(0), Flt(0), 00281 SymLnN(-1), SymLnChN(-1), SymChN(-1){ 00282 for (int Opt=0; Opt<iloMx; Opt++){ 00283 if (OptSet.In(Opt)){SetOpt(Opt, true);}} 00284 } 00285 00286 void TILx::SetOpt(const int& Opt, const bool& Val){ 00287 switch (Opt){ 00288 case iloCmtAlw: IsCmtAlw=Val; break; 00289 case iloRetEoln: IsRetEoln=Val; break; 00290 case iloSigNum: IsSigNum=Val; break; 00291 case iloUniStr: IsUniStr=Val; break; 00292 case iloCsSens: IsCsSens=Val; break; 00293 case iloExcept: IsExcept=Val; break; 00294 case iloTabSep: IsTabSep=Val; break; 00295 case iloList: IsList=Val; break; 00296 default: Fail; 00297 } 00298 } 00299 00300 TLxSym TILx::AddRw(const TStr& Str){ 00301 IAssert(RwStrH.Len()<syMxRw-syMnRw+1); 00302 TStr UcStr=ChDef->GetUcStr(Str); 00303 IAssert(!RwStrH.IsKey(UcStr)); 00304 TLxSym RwSym=TLxSym(syMnRw+RwStrH.Len()); 00305 RwStrH.AddDat(Str, TInt(int(RwSym))); 00306 return RwSym; 00307 } 00308 00309 PSIn TILx::GetSIn(const char& SepCh){ 00310 IAssert(PrevSymStStack.Empty()); 00311 while ((Ch!=TCh::EofCh)&&(Ch!=SepCh)){GetCh();} 00312 return SIn; 00313 } 00314 00315 TLxSym TILx::GetSym(const TFSet& Expect){ 00316 CmtStr.Clr(); 00317 if (!PrevSymStStack.Empty()){ 00318 // symbols already on the stack 00319 PrevSymStStack.Top().Restore(*this); PrevSymStStack.Pop(); 00320 } else 00321 if (Expect.In(syLn)){ 00322 // symbol is the whole line string 00323 if (Ch==TCh::EofCh){ 00324 Sym=syEof; 00325 } else { 00326 Str.Clr(); 00327 if (IsBof()){GetCh();} 00328 while (!ChDef->IsTerm(Ch)){Str.AddCh(Ch); GetCh();} 00329 bool _IsRetEoln=IsRetEoln; IsRetEoln=true; 00330 GetSym(TFSet()|syEoln|syEof); Sym=syLn; 00331 IsRetEoln=_IsRetEoln; 00332 } 00333 } else 00334 if (IsTabSep){ 00335 // symbol is between tab characters 00336 if (IsBof()){GetCh();} 00337 if (Ch==TCh::TabCh){ // tab character 00338 Sym=syTab; GetCh(); 00339 } else 00340 if (ChDef->IsTerm(Ch)){ // eoln & eof characters 00341 bool _IsRetEoln=IsRetEoln; IsRetEoln=true; IsTabSep=false; 00342 GetSym(TFSet()|syEoln|syEof); 00343 IsRetEoln=_IsRetEoln; IsTabSep=true; 00344 } else { 00345 Str.Clr(); 00346 while ((!ChDef->IsTerm(Ch))&&(Ch!=TCh::TabCh)){ 00347 Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00348 Sym=syStr; QuoteP=false; 00349 } 00350 } else { 00351 // usual symbol 00352 while (ChDef->IsSpace(Ch)){GetCh();} 00353 SymLnN=LnN; SymLnChN=LnChN; SymChN=ChN; 00354 00355 if (ChDef->IsAlpha(Ch)){ 00356 if (IsUniStr){Sym=syStr;} else {Sym=syIdStr;} 00357 Str.Clr(); UcStr.Clr(); QuoteP=false; 00358 do {Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch));} 00359 while (ChDef->IsAlNum(GetCh())); 00360 if (!RwStrH.Empty()){ 00361 TStr RwStr=Str; if (!IsCsSens){RwStr=UcStr;} 00362 int SymKeyId=RwStrH.GetKeyId(RwStr); 00363 if (SymKeyId!=-1){Sym=TLxSym(int(RwStrH[SymKeyId]));} 00364 } 00365 if (Expect.In(syBool)){ 00366 Sym=syBool; IAssert(TBool::IsValStr(Str)); 00367 Bool=TBool::GetValFromStr(Str); 00368 } 00369 } else 00370 if ((Ch=='"')||(Ch=='\'')){ 00371 if (IsUniStr){Sym=syStr;} else {Sym=syQStr;} 00372 Str.Clr(); UcStr.Clr(); QuoteP=true; QuoteCh=Ch; 00373 GetCh(); 00374 forever{ 00375 while ((Ch!=QuoteCh)&&(Ch!='\\')&&(Ch!=TCh::EofCh)){ 00376 Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00377 if (Ch==TCh::EofCh){ 00378 Sym=syUndef; break; 00379 } else if (Ch==QuoteCh){ 00380 GetCh(); break; 00381 } else { 00382 GetCh(); 00383 switch (Ch){ 00384 case '"': Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00385 case '\\': Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00386 case '\'': Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00387 case '/': Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00388 case 'b': Str.AddCh('\b'); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00389 case 'f': Str.AddCh('\f'); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00390 case 'n': Str.AddCh('\n'); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00391 case 'r': Str.AddCh('\r'); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00392 case 't': Str.AddCh('\t'); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh(); break; 00393 case 'u': { 00394 // unicode character, represented using 4 hexadecimal digits 00395 GetCh(); EAssertR(TCh::IsHex(Ch), "Invalid hexadecimal digit in unicode escape"); 00396 int UChCd = TCh::GetHex(Ch); 00397 GetCh(); EAssertR(TCh::IsHex(Ch), "Invalid hexadecimal digit in unicode escape"); 00398 UChCd = 16 * UChCd + TCh::GetHex(Ch); 00399 GetCh(); EAssertR(TCh::IsHex(Ch), "Invalid hexadecimal digit in unicode escape"); 00400 UChCd = 16 * UChCd + TCh::GetHex(Ch); 00401 GetCh(); EAssertR(TCh::IsHex(Ch), "Invalid hexadecimal digit in unicode escape"); 00402 UChCd = 16 * UChCd + TCh::GetHex(Ch); 00403 // get as UTF8 encoded characters 00404 TUnicode::EncodeUtf8(UChCd, Str); 00405 TUnicode::EncodeUtf8(UChCd, UcStr); } 00406 GetCh(); break; 00407 default: Sym=syUndef; break; 00408 } 00409 if (Sym==syUndef){ 00410 throw PExcept(new TExcept("Invalid Escape Sequence in Quoted String"));} 00411 } 00412 } 00413 } else 00414 if ((ChDef->IsNum(Ch))||(IsSigNum&&((Ch=='+')||(Ch=='-')))){ 00415 Str.Clr(); bool IntP=true; 00416 do {Str.AddCh(Ch);} while (ChDef->IsNum(GetCh())); 00417 if (Expect.In(syFlt)){ 00418 if (Ch=='.'){ 00419 Str.AddCh(Ch); IntP=false; 00420 while (ChDef->IsNum(GetCh())){Str.AddCh(Ch);} 00421 } 00422 if ((Ch=='e')||(Ch=='E')){ 00423 Str.AddCh(Ch); GetCh(); IntP=false; 00424 if ((Ch=='+')||(Ch=='-')){Str.AddCh(Ch); GetCh();} 00425 while (ChDef->IsNum(Ch)){Str.AddCh(Ch); GetCh();} 00426 } 00427 } 00428 UcStr=Str; 00429 if (IntP&&(Expect.In(syInt))){ 00430 Sym=syInt; Int=atoi(Str.CStr()); 00431 } else { 00432 Sym=syFlt; Flt=atof(Str.CStr()); 00433 } 00434 } else 00435 if ((Ch==TCh::CrCh)||(Ch==TCh::LfCh)){ 00436 Sym=syEoln; 00437 if (Ch==TCh::CrCh){if (GetCh()==TCh::LfCh){GetCh();}} else 00438 if (Ch==TCh::LfCh){if (GetCh()==TCh::CrCh){GetCh();}} 00439 LnN++; LnChN=0; if (!IsRetEoln){GetSym(Expect);} 00440 } else 00441 if (Ch=='/'){ 00442 GetCh(); 00443 if ((IsCmtAlw)&&(Ch=='/')){ 00444 TChA _CmtStr; 00445 do {_CmtStr+=GetCh();} while (!ChDef->IsTerm(Ch)); 00446 _CmtStr.Pop(); _CmtStr.Trunc(); 00447 if (Ch==TCh::CrCh){ 00448 if (GetCh()==TCh::LfCh){GetCh();} 00449 } else 00450 if (Ch==TCh::LfCh){ 00451 if (GetCh()==TCh::CrCh){GetCh();} 00452 } 00453 if (IsRetEoln){Sym=syEoln;} else {GetSym(Expect);} 00454 CmtStr=_CmtStr; 00455 } else 00456 if (Ch=='*'){ 00457 TChA _CmtStr; 00458 do { 00459 while (GetCh()!='*'){_CmtStr+=Ch;} 00460 _CmtStr+=GetCh(); 00461 } while (Ch!='/'); 00462 _CmtStr.Pop(); _CmtStr.Pop(); _CmtStr.Trunc(); 00463 GetCh(); GetSym(Expect); 00464 CmtStr=_CmtStr; 00465 } else { 00466 Sym=sySlash; 00467 } 00468 } else 00469 if (Ch==TCh::EofCh){ 00470 Sym=syEof; 00471 } else { 00472 switch (Ch){ 00473 case '.': 00474 if (GetCh()=='.'){Sym=syDPeriod; GetCh();} 00475 else {Sym=syPeriod;} break; 00476 case ',': Sym=syComma; GetCh(); break; 00477 case ':': 00478 if (GetCh()==':'){Sym=syDColon; GetCh();} 00479 else {Sym=syColon;} break; 00480 case ';': Sym=sySemicolon; GetCh(); break; 00481 case '+': Sym=syPlus; GetCh(); break; 00482 case '-': Sym=syMinus; GetCh(); break; 00483 case '*': Sym=syAsterisk; GetCh(); break; 00484 case '/': Sym=sySlash; GetCh(); break; 00485 case '%': Sym=syPercent; GetCh(); break; 00486 case '!': Sym=syExclamation; GetCh(); break; 00487 case '|': Sym=syVBar; GetCh(); break; 00488 case '&': Sym=syAmpersand; GetCh(); break; 00489 case '=': Sym=syEq; GetCh(); break; 00490 case '<': 00491 GetCh(); 00492 if (Ch=='='){Sym=syLEq; GetCh();} 00493 else if (Ch=='>'){Sym=syNEq; GetCh();} 00494 else {Sym=syLss;} break; 00495 case '>': 00496 if (GetCh()=='='){Sym=syGEq; GetCh();} 00497 else {Sym=syGtr;} break; 00498 case '?': Sym=syQuestion; GetCh(); break; 00499 case '#': 00500 if (IsCmtAlw){ 00501 TChA _CmtStr; 00502 do {_CmtStr+=GetCh();} while (!ChDef->IsTerm(Ch)); 00503 _CmtStr.Pop(); _CmtStr.Trunc(); 00504 if (Ch==TCh::CrCh){ 00505 if (GetCh()==TCh::LfCh){GetCh();} 00506 } else 00507 if (Ch==TCh::LfCh){ 00508 if (GetCh()==TCh::CrCh){GetCh();} 00509 } 00510 if (IsRetEoln){Sym=syEoln;} else {GetSym(Expect);} 00511 CmtStr=_CmtStr; 00512 } else { 00513 Sym=syHash; GetCh(); 00514 } 00515 break; 00516 case '(': Sym=syLParen; GetCh(); break; 00517 case ')': Sym=syRParen; GetCh(); break; 00518 case '[': Sym=syLBracket; GetCh(); break; 00519 case ']': Sym=syRBracket; GetCh(); break; 00520 case '{': Sym=syLBrace; GetCh(); break; 00521 case '}': Sym=syRBrace; GetCh(); break; 00522 default: Sym=syUndef; GetCh(); break; 00523 } 00524 } 00525 } 00526 00527 if ((!Expect.In(Sym))&&(!Expect.Empty())){ 00528 if (IsExcept){ 00529 TStr MsgStr= 00530 TStr("Unexpected symbol (")+GetSymStr()+") ["+GetFPosStr()+"]"; 00531 throw PExcept(new TExcept(MsgStr)); 00532 } else { 00533 Fail; 00534 } 00535 } 00536 return Sym; 00537 } 00538 00539 TStr TILx::GetStrToCh(const char& ToCh){ 00540 Sym=syStr; Str.Clr(); UcStr.Clr(); 00541 while ((Ch!=ToCh)&&(Ch!=TCh::EofCh)){ 00542 Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00543 return Str; 00544 } 00545 00546 TStr TILx::GetStrToEolnOrCh(const char& ToCh){ 00547 Sym=syStr; Str.Clr(); UcStr.Clr(); 00548 while ((Ch!=ToCh)&&(Ch!=TCh::CrCh)&&(Ch!=TCh::LfCh)&&(Ch!=TCh::EofCh)){ 00549 Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00550 return Str; 00551 } 00552 00553 TStr TILx::GetStrToEoln(const bool& DoTrunc){ 00554 Sym=syStr; Str.Clr(); UcStr.Clr(); 00555 while ((Ch!=TCh::CrCh)&&(Ch!=TCh::LfCh)&&(Ch!=TCh::EofCh)){ 00556 Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00557 if (DoTrunc){Str.ToTrunc(); UcStr.ToTrunc();} 00558 return Str; 00559 } 00560 00561 TStr TILx::GetStrToEolnAndCh(const char& ToCh){ 00562 Sym=syStr; Str.Clr(); UcStr.Clr(); 00563 if (IsBof()){GetCh();} 00564 forever { 00565 if (Ch==TCh::EofCh){break;} 00566 if (((ChN==0)||(PrevCh==TCh::CrCh)||(PrevCh==TCh::LfCh))&&(Ch==ToCh)){ 00567 GetCh(); break;} 00568 else {Str.AddCh(Ch); UcStr.AddCh(ChDef->GetUc(Ch)); GetCh();} 00569 } 00570 return Str; 00571 } 00572 00573 void TILx::SkipToEoln(){ 00574 while ((Ch!=TCh::CrCh)&&(Ch!=TCh::LfCh)&&(Ch!=TCh::EofCh)){ 00575 GetCh();} 00576 if (Ch==TCh::CrCh){if (GetCh()==TCh::LfCh){GetCh();}} else 00577 if (Ch==TCh::LfCh){if (GetCh()==TCh::CrCh){GetCh();}} 00578 } 00579 00580 TLxSym TILx::PeekSym(const int& Syms){ 00581 TILxSymSt CurSymSt(*this); 00582 TSStack<TILxSymSt> SymStStack; 00583 for (int SymN=0; SymN<Syms; SymN++){ 00584 GetSym(); SymStStack.Push(TILxSymSt(*this));} 00585 TLxSym PeekedSym=Sym; 00586 while (!SymStStack.Empty()){ 00587 SymStStack.Top().Restore(*this); SymStStack.Pop(); 00588 PutSym(); 00589 } 00590 CurSymSt.Restore(*this); 00591 return PeekedSym; 00592 } 00593 00594 TStr TILx::GetSymStr() const { 00595 switch (Sym){ 00596 case syInt: return Str; 00597 case syFlt: return Str; 00598 case syStr: return Str; 00599 case syIdStr: return Str; 00600 case syQStr: return Str; 00601 default: 00602 if ((syMnRw<=Sym)&&(Sym<=syMxRw)){return Str;} 00603 else {return TLxSymStr::GetSymStr(Sym);} 00604 } 00605 } 00606 00607 TStr TILx::GetFPosStr() const { 00608 TChA ChA; 00609 ChA+="File:"; ChA+=SIn->GetSNm(); 00610 ChA+=" Line:"; ChA+=TInt::GetStr(LnN+1); 00611 ChA+=" Char:"; ChA+=TInt::GetStr(LnChN); 00612 return ChA; 00613 } 00614 00615 TStr TILx::GetQStr(const TStr& Str, const bool& QuoteP, const char& QuoteCh){ 00616 if (QuoteP){ 00617 TChA ChA; 00618 ChA+=QuoteCh; 00619 int StrLen=Str.Len(); 00620 for (int ChN=0; ChN<StrLen; ChN++){ 00621 char Ch=Str.CStr()[ChN]; 00622 if (Ch==QuoteCh){ChA+=QuoteCh; ChA+=QuoteCh;} 00623 else {ChA+=Ch;} 00624 } 00625 ChA+=QuoteCh; 00626 return ChA; 00627 } else { 00628 return Str; 00629 } 00630 } 00631 00632 void TILx::GetVarBoolV(const TStr& VarNm, TBoolV& BoolV, const bool& NewLn){ 00633 BoolV.Clr(); 00634 GetVar(VarNm, true, NewLn); 00635 while (GetSym(syRBracket, syBool)==syQStr){ 00636 BoolV.Add(Bool); if (NewLn){GetEoln();}} 00637 if (NewLn){GetEoln();} 00638 } 00639 00640 void TILx::GetVarIntV(const TStr& VarNm, TIntV& IntV, const bool& NewLn){ 00641 IntV.Clr(); 00642 GetVar(VarNm, true, NewLn); 00643 while (GetSym(syRBracket, syInt)==syInt){ 00644 IntV.Add(Int); if (NewLn){GetEoln();}} 00645 if (NewLn){GetEoln();} 00646 } 00647 00648 void TILx::GetVarFltV(const TStr& VarNm, TFltV& FltV, const bool& NewLn){ 00649 FltV.Clr(); 00650 GetVar(VarNm, true, NewLn); 00651 while (GetSym(syRBracket, syFlt)==syFlt){ 00652 FltV.Add(Flt); if (NewLn){GetEoln();}} 00653 if (NewLn){GetEoln();} 00654 } 00655 00656 void TILx::GetVarStrV(const TStr& VarNm, TStrV& StrV, const bool& NewLn){ 00657 StrV.Clr(); 00658 GetVar(VarNm, true, NewLn); 00659 while (GetSym(syRBracket, syQStr)==syQStr){ 00660 StrV.Add(Str); if (NewLn){GetEoln();}} 00661 if (NewLn){GetEoln();} 00662 } 00663 00664 void TILx::GetVarStrPrV(const TStr& VarNm, TStrPrV& StrPrV, const bool& NewLn){ 00665 StrPrV.Clr(); 00666 GetVar(VarNm, true, NewLn); 00667 while (GetSym(syRBracket, syLBracket)==syLBracket){ 00668 TStr Str1=GetQStr(); TStr Str2=GetQStr(); 00669 GetSym(syRBracket); 00670 StrPrV.Add(TStrPr(Str1, Str2)); if (NewLn){GetEoln();} 00671 } 00672 if (NewLn){GetEoln();} 00673 } 00674 00675 void TILx::GetVarStrVV(const TStr& VarNm, TVec<TStrV>& StrVV, const bool& NewLn){ 00676 StrVV.Clr(); 00677 GetVar(VarNm, true, NewLn); 00678 while (GetSym(syRBracket, syLBracket)==syLBracket){ 00679 StrVV.Add(); 00680 while (GetSym(syQStr, syRBracket)==syQStr){ 00681 StrVV.Last().Add(Str);} 00682 if (NewLn){GetEoln();} 00683 } 00684 if (NewLn){GetEoln();} 00685 } 00686 00687 void TILx::GetLnV(const TStr& FNm, TStrV& LnV){ 00688 TFIn SIn(FNm); LnV.Clr(); TChA Ln; 00689 if (!SIn.Eof()){ 00690 char Ch=SIn.GetCh(); 00691 while (!SIn.Eof()){ 00692 if ((Ch==TCh::CrCh)||(Ch==TCh::LfCh)){ 00693 if (!SIn.Eof()){ 00694 char PrevCh=Ch; Ch=SIn.GetCh(); 00695 if (!SIn.Eof()){ 00696 if (PrevCh==TCh::CrCh){if (Ch==TCh::LfCh){Ch=SIn.GetCh();}} else 00697 if (PrevCh==TCh::LfCh){if (Ch==TCh::CrCh){Ch=SIn.GetCh();}} 00698 } 00699 } 00700 LnV.Add(Ln); Ln.Clr(); 00701 } else { 00702 Ln+=Ch; Ch=SIn.GetCh(); 00703 } 00704 } 00705 if (!Ln.Empty()){ 00706 LnV.Add(Ln);} 00707 } 00708 } 00709 00711 // Lexical-Output 00712 void TOLx::PutSep(const TLxSym& Sym){ 00713 if (TLxSymStr::IsSep(PrevSym, Sym)){ 00714 if (IsTabSep){RSOut.PutCh(TCh::TabCh);} else {RSOut.PutCh(' ');}} 00715 PrevSym=Sym; 00716 } 00717 00718 TOLx::TOLx(const PSOut& _SOut, const TFSet& OptSet, const TLxChDefTy& ChDefTy): 00719 ChDef(TLxChDef::GetChDef(ChDefTy)), SOut(_SOut), RSOut(*SOut), 00720 IsCmtAlw(false), IsFrcEoln(false), IsSigNum(false), 00721 IsUniStr(false), IsCsSens(false), IsTabSep(false), IsVarIndent(false), 00722 VarIndentLev(0), 00723 RwStrH(50), RwSymH(50), PrevSym(syUndef){ 00724 for (int Opt=0; Opt<oloMx; Opt++){ 00725 if (OptSet.In(Opt)){SetOpt(Opt, true);}} 00726 } 00727 00728 void TOLx::SetOpt(const int& Opt, const bool& Val){ 00729 switch (Opt){ 00730 case oloCmtAlw: IsCmtAlw=Val; break; 00731 case oloFrcEoln: IsFrcEoln=Val; break; 00732 case oloSigNum: IsSigNum=Val; break; 00733 case oloUniStr: IsUniStr=Val; break; 00734 case oloCsSens: IsCsSens=Val; break; 00735 case oloTabSep: IsTabSep=Val; break; 00736 case oloVarIndent: IsVarIndent=Val; break; 00737 default: Fail; 00738 } 00739 } 00740 00741 TLxSym TOLx::AddRw(const TStr& Str){ 00742 IAssert(RwStrH.Len()<syMxRw-syMnRw+1); 00743 TStr UcStr=ChDef->GetUcStr(Str); 00744 IAssert(!RwStrH.IsKey(UcStr)); 00745 TLxSym RwSym=TLxSym(syMnRw+RwStrH.Len()); 00746 RwStrH.AddDat(Str, TInt(int(RwSym))); 00747 RwSymH.AddDat(TInt(int(RwSym)), Str); 00748 return RwSym; 00749 } 00750 00751 void TOLx::PutSym(const TLxSym& Sym){ 00752 TStr Str; 00753 if ((syMnRw<=Sym)&&(Sym<=syMxRw)){ 00754 Str=Str=RwSymH[Sym]; 00755 } else { 00756 Str=TLxSymStr::GetSymStr(Sym); 00757 } 00758 PutSep(Sym); RSOut.PutStr(Str); 00759 } 00760 00761 void TOLx::PutVarBoolV(const TStr& VarNm, const TBoolV& BoolV, 00762 const bool& NewLn, const bool& CheckIdStr){ 00763 PutVar(VarNm, true, NewLn, CheckIdStr); 00764 for (int BoolN=0; BoolN<BoolV.Len(); BoolN++){ 00765 if (IsVarIndent){PutIndent(VarIndentLev);} 00766 PutBool(BoolV[BoolN]); 00767 if (NewLn){PutLn();} 00768 } 00769 PutVarEnd(true, NewLn); 00770 } 00771 00772 void TOLx::PutVarIntV(const TStr& VarNm, const TIntV& IntV, 00773 const bool& NewLn, const bool& CheckIdStr){ 00774 PutVar(VarNm, true, NewLn, CheckIdStr); 00775 for (int IntN=0; IntN<IntV.Len(); IntN++){ 00776 if (IsVarIndent){PutIndent(VarIndentLev);} 00777 PutInt(IntV[IntN]); 00778 if (NewLn){PutLn();} 00779 } 00780 PutVarEnd(true, NewLn); 00781 } 00782 00783 void TOLx::PutVarFltV(const TStr& VarNm, const TFltV& FltV, 00784 const bool& NewLn, const bool& CheckIdStr){ 00785 PutVar(VarNm, true, NewLn, CheckIdStr); 00786 for (int FltN=0; FltN<FltV.Len(); FltN++){ 00787 if (IsVarIndent){PutIndent(VarIndentLev);} 00788 PutFlt(FltV[FltN]); 00789 if (NewLn){PutLn();} 00790 } 00791 PutVarEnd(true, NewLn); 00792 } 00793 00794 void TOLx::PutVarStrV(const TStr& VarNm, const TStrV& StrV, 00795 const bool& NewLn, const bool& CheckIdStr){ 00796 PutVar(VarNm, true, NewLn, CheckIdStr); 00797 for (int StrN=0; StrN<StrV.Len(); StrN++){ 00798 if (IsVarIndent){PutIndent(VarIndentLev);} 00799 PutQStr(StrV[StrN]); 00800 if (NewLn){PutLn();} 00801 } 00802 PutVarEnd(true, NewLn); 00803 } 00804 00805 void TOLx::PutVarStrPrV(const TStr& VarNm, const TStrPrV& StrPrV, 00806 const bool& NewLn, const bool& CheckIdStr){ 00807 PutVar(VarNm, true, NewLn, CheckIdStr); 00808 for (int StrPrN=0; StrPrN<StrPrV.Len(); StrPrN++){ 00809 if (IsVarIndent){PutIndent(VarIndentLev);} 00810 PutSym(syLBracket); 00811 PutQStr(StrPrV[StrPrN].Val1); PutQStr(StrPrV[StrPrN].Val2); 00812 PutSym(syRBracket); 00813 if (NewLn){PutLn();} 00814 } 00815 PutVarEnd(true, NewLn); 00816 } 00817 00818 void TOLx::PutVarStrVV(const TStr& VarNm, const TVec<TStrV>& StrVV, 00819 const bool& NewLn, const bool& CheckIdStr){ 00820 PutVar(VarNm, true, NewLn, CheckIdStr); 00821 for (int StrVN=0; StrVN<StrVV.Len(); StrVN++){ 00822 if (IsVarIndent){PutIndent(VarIndentLev);} 00823 PutSym(syLBracket); 00824 for (int StrN=0; StrN<StrVV[StrVN].Len(); StrN++){ 00825 PutQStr(StrVV[StrVN][StrN]);} 00826 PutSym(syRBracket); 00827 if (NewLn){PutLn();} 00828 } 00829 PutVarEnd(true, NewLn); 00830 } 00831 00833 // Preprocessor 00834 char TPreproc::GetCh(){ 00835 Assert(Ch!=TCh::EofCh); 00836 PrevCh=Ch; 00837 Ch=((SIn->Eof()) ? TCh::EofCh : SIn->GetCh()); 00838 //putchar(Ch); 00839 return Ch; 00840 } 00841 00842 bool TPreproc::IsSubstId(const TStr& SubstId, TStr& SubstValStr) const { 00843 if (SubstIdToKeyIdValPrVH.IsKey(SubstId)){ 00844 const TStrPrV& KeyIdValPrV=SubstIdToKeyIdValPrVH.GetDat(SubstId); 00845 for (int KeyN=0; KeyN<KeyIdValPrV.Len(); KeyN++){ 00846 if (SubstKeyIdV.IsIn(KeyIdValPrV[KeyN].Val1)){ 00847 SubstValStr=KeyIdValPrV[KeyN].Val2; 00848 return true; 00849 } 00850 } 00851 return false; 00852 } else { 00853 return false; 00854 } 00855 } 00856 00857 TPreproc::TPreproc(const TStr& InFNm, const TStr& OutFNm, 00858 const TStr& SubstFNm, const TStrV& _SubstKeyIdV): 00859 SIn(), SubstKeyIdV(_SubstKeyIdV), 00860 PrevCh('\0'), Ch('\0'){ 00861 // load substitution file 00862 if (!SubstFNm.Empty()){ 00863 PXmlDoc XmlDoc=TXmlDoc::LoadTxt(SubstFNm); 00864 // get list of substitutions 00865 TXmlTokV SubstTokV; XmlDoc->GetTok()->GetTagTokV("Subst", SubstTokV); 00866 for (int SubstTokN=0; SubstTokN<SubstTokV.Len(); SubstTokN++){ 00867 PXmlTok SubstTok=SubstTokV[SubstTokN]; 00868 // get substitution-id 00869 TStr SubstId=SubstTok->GetArgVal("Id", ""); 00870 if (!SubstId.Empty()){ 00871 // create substitution 00872 TStrPrV& KeyIdValPrV=SubstIdToKeyIdValPrVH.AddDat(SubstId); 00873 // get list of substitution-strings 00874 TXmlTokV StrTokV; SubstTok->GetTagTokV("Str", StrTokV); 00875 for (int StrTokN=0; StrTokN<StrTokV.Len(); StrTokN++){ 00876 PXmlTok StrTok=StrTokV[StrTokN]; 00877 // get key-value pair 00878 TStr KeyId=StrTok->GetArgVal("Key", ""); 00879 TStr ValStr=StrTok->GetTokStr(false); 00880 // assign key-value-pair 00881 if (!KeyId.Empty()){ 00882 KeyIdValPrV.Add(TStrPr(KeyId, ValStr)); 00883 } 00884 } 00885 } 00886 } 00887 } 00888 // substitution 00889 // open files 00890 SIn=TFIn::New(InFNm); 00891 PSOut SOut=TFOut::New(OutFNm); 00892 // set copy & ignore mode 00893 bool CopyModeP=false; bool IgnoreModeP=false; 00894 GetCh(); 00895 while (Ch!=TCh::EofCh){ 00896 if (isalpha(Ch)||(((PrevCh=='\0')||(PrevCh=='\r')||(PrevCh=='\n'))&&(Ch=='#'))){ 00897 // collect identifier 00898 TChA IdChA; 00899 do { 00900 IdChA+=Ch; GetCh(); 00901 } while ((Ch!=TCh::EofCh)&&(isalnum(Ch))); 00902 // check identifier 00903 if (IdChA=="#ifdef"){ 00904 // collect condition-key-id 00905 TChA CondKeyIdChA; 00906 while ((Ch!=TCh::EofCh)&&(Ch!='\n')&&(Ch!='\r')){ 00907 CondKeyIdChA+=Ch; GetCh();} 00908 // skip eoln 00909 if (Ch=='\n'){GetCh(); if (Ch=='\r'){GetCh();}} 00910 else if (Ch=='\r'){GetCh(); if (Ch=='\n'){GetCh();}} 00911 // check for key 00912 CondKeyIdChA.Trunc(); 00913 IAssert(CopyModeP==false); 00914 IAssert(IgnoreModeP==false); 00915 if (SubstKeyIdV.IsIn(CondKeyIdChA)){ 00916 CopyModeP=true; IgnoreModeP=false; 00917 } else { 00918 CopyModeP=false; IgnoreModeP=true; 00919 } 00920 } else 00921 if (IdChA=="#endif"){ 00922 // move to eoln 00923 while ((Ch!=TCh::EofCh)&&(Ch!='\n')&&(Ch!='\r')){ 00924 GetCh();} 00925 // skip eoln 00926 if (Ch=='\n'){GetCh(); if (Ch=='\r'){GetCh();}} 00927 else if (Ch=='\r'){GetCh(); if (Ch=='\n'){GetCh();}} 00928 // reset copy&ignore modes 00929 IAssert(CopyModeP||IgnoreModeP); 00930 CopyModeP=false; IgnoreModeP=false; 00931 } else { 00932 // substitution or add id-as-seen 00933 TStr SubstValStr; 00934 if ((!CopyModeP)&&(IsSubstId(IdChA, SubstValStr))){ 00935 if (!IgnoreModeP){SOut->PutStr(SubstValStr);} 00936 } else { 00937 if (!IgnoreModeP){SOut->PutStr(IdChA);} 00938 } 00939 } 00940 } else { 00941 // single character 00942 if (!IgnoreModeP){SOut->PutCh(Ch);} 00943 GetCh(); 00944 } 00945 } 00946 } 00947