nodes2string.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2002 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2003 Apple Computer, Inc.
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public License
00018  *  along with this library; see the file COPYING.LIB.  If not, write to
00019  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  *  Boston, MA 02110-1301, USA.
00021  *
00022  */
00023 
00024 #include "nodes.h"
00025 
00026 namespace KJS {
00030   class SourceStream {
00031   public:
00032     enum Format {
00033       Endl, Indent, Unindent
00034     };
00035 
00036     UString toString() const { return str; }
00037     SourceStream& operator<<(const Identifier &);
00038     SourceStream& operator<<(const KJS::UString &);
00039     SourceStream& operator<<(const char *);
00040     SourceStream& operator<<(char);
00041     SourceStream& operator<<(Format f);
00042     SourceStream& operator<<(const Node *);
00043   private:
00044     UString str; /* TODO: buffer */
00045     UString ind;
00046   };
00047 }
00048 
00049 using namespace KJS;
00050 
00051 SourceStream& SourceStream::operator<<(char c)
00052 {
00053   str += UString(c);
00054   return *this;
00055 }
00056 
00057 SourceStream& SourceStream::operator<<(const char *s)
00058 {
00059   str += UString(s);
00060   return *this;
00061 }
00062 
00063 SourceStream& SourceStream::operator<<(const UString &s)
00064 {
00065   str += s;
00066   return *this;
00067 }
00068 
00069 SourceStream& SourceStream::operator<<(const Identifier &s)
00070 {
00071   str += s.ustring();
00072   return *this;
00073 }
00074 
00075 SourceStream& SourceStream::operator<<(const Node *n)
00076 {
00077   if (n)
00078     n->streamTo(*this);
00079   return *this;
00080 }
00081 
00082 SourceStream& SourceStream::operator<<(Format f)
00083 {
00084   switch (f) {
00085     case Endl:
00086       str += "\n" + ind;
00087       break;
00088     case Indent:
00089       ind += "  ";
00090       break;
00091     case Unindent:
00092       ind = ind.substr(0, ind.size() - 2);
00093       break;
00094   }
00095 
00096   return *this;
00097 }
00098 
00099 UString unescapeStr(UString str)
00100 {
00101   UString unescaped = "";
00102   int i = 0;
00103   int copied = 0;
00104   for (i = 0; i <= str.size(); i++) {
00105     if (str[i] == '"') {
00106       if (copied < i)
00107     unescaped += str.substr(copied,i-copied);
00108       copied = i+1;
00109       unescaped += "\\\"";
00110     }
00111   }
00112   if (copied < i)
00113     unescaped += str.substr(copied,i-copied);
00114   return unescaped;
00115 }
00116 
00117 UString Node::toCode() const
00118 {
00119   SourceStream str;
00120   streamTo(str);
00121 
00122   return str.toString();
00123 }
00124 
00125 void NullNode::streamTo(SourceStream &s) const { s << "null"; }
00126 
00127 void BooleanNode::streamTo(SourceStream &s) const
00128 {
00129   s << (val ? "true" : "false");
00130 }
00131 
00132 void NumberNode::streamTo(SourceStream &s) const { s << UString::from(val); }
00133 
00134 void StringNode::streamTo(SourceStream &s) const
00135 {
00136   s << '"' << unescapeStr(val) << '"';
00137 }
00138 
00139 void RegExpNode::streamTo(SourceStream &s) const { s << "/" << pattern << "/" << flags; }
00140 
00141 void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
00142 
00143 void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
00144 
00145 void GroupNode::streamTo(SourceStream &s) const
00146 {
00147   s << "(" << group << ")";
00148 }
00149 
00150 void ElementNode::streamTo(SourceStream &s) const
00151 {
00152   for (const ElementNode *n = this; n; n = n->list) {
00153     for (int i = 0; i < n->elision; i++)
00154       s << ",";
00155     s << n->node;
00156     if ( n->list )
00157         s << ",";
00158   }
00159 }
00160 
00161 void ArrayNode::streamTo(SourceStream &s) const
00162 {
00163   s << "[" << element;
00164   for (int i = 0; i < elision; i++)
00165     s << ",";
00166   s << "]";
00167 }
00168 
00169 void ObjectLiteralNode::streamTo(SourceStream &s) const
00170 {
00171   if (list)
00172     s << "{ " << list << " }";
00173   else
00174     s << "{ }";
00175 }
00176 
00177 void PropertyValueNode::streamTo(SourceStream &s) const
00178 {
00179   for (const PropertyValueNode *n = this; n; n = n->list)
00180     s << n->name << ": " << n->assign;
00181 }
00182 
00183 void PropertyNode::streamTo(SourceStream &s) const
00184 {
00185   if (str.isNull())
00186     s << UString::from(numeric);
00187   else
00188     s << str;
00189 }
00190 
00191 void AccessorNode1::streamTo(SourceStream &s) const
00192 {
00193   s << expr1 << "[" << expr2 << "]";
00194 }
00195 
00196 void AccessorNode2::streamTo(SourceStream &s) const
00197 {
00198   s << expr << "." << ident;
00199 }
00200 
00201 void ArgumentListNode::streamTo(SourceStream &s) const
00202 {
00203   s << expr;
00204   for (ArgumentListNode *n = list; n; n = n->list)
00205     s << ", " << n->expr;
00206 }
00207 
00208 void ArgumentsNode::streamTo(SourceStream &s) const
00209 {
00210   s << "(" << list << ")";
00211 }
00212 
00213 void NewExprNode::streamTo(SourceStream &s) const
00214 {
00215   s << "new " << expr << args;
00216 }
00217 
00218 void FunctionCallNode::streamTo(SourceStream &s) const
00219 {
00220   s << expr << args;
00221 }
00222 
00223 void PostfixNode::streamTo(SourceStream &s) const
00224 {
00225   s << expr;
00226   if (oper == OpPlusPlus)
00227     s << "++";
00228   else
00229     s << "--";
00230 }
00231 
00232 void DeleteNode::streamTo(SourceStream &s) const
00233 {
00234   s << "delete " << expr;
00235 }
00236 
00237 void VoidNode::streamTo(SourceStream &s) const
00238 {
00239   s << "void " << expr;
00240 }
00241 
00242 void TypeOfNode::streamTo(SourceStream &s) const
00243 {
00244   s << "typeof " << expr;
00245 }
00246 
00247 void PrefixNode::streamTo(SourceStream &s) const
00248 {
00249   s << (oper == OpPlusPlus ? "++" : "--") << expr;
00250 }
00251 
00252 void UnaryPlusNode::streamTo(SourceStream &s) const
00253 {
00254   s << "+" << expr;
00255 }
00256 
00257 void NegateNode::streamTo(SourceStream &s) const
00258 {
00259   s << "-" << expr;
00260 }
00261 
00262 void BitwiseNotNode::streamTo(SourceStream &s) const
00263 {
00264   s << "~" << expr;
00265 }
00266 
00267 void LogicalNotNode::streamTo(SourceStream &s) const
00268 {
00269   s << "!" << expr;
00270 }
00271 
00272 void MultNode::streamTo(SourceStream &s) const
00273 {
00274   s << term1 << oper << term2;
00275 }
00276 
00277 void AddNode::streamTo(SourceStream &s) const
00278 {
00279   s << term1 << oper << term2;
00280 }
00281 
00282 void AppendStringNode::streamTo(SourceStream &s) const
00283 {
00284   s << term << "+" << '"' << unescapeStr(str) << '"';
00285 }
00286 
00287 void ShiftNode::streamTo(SourceStream &s) const
00288 {
00289   s << term1;
00290   if (oper == OpLShift)
00291     s << "<<";
00292   else if (oper == OpRShift)
00293     s << ">>";
00294   else
00295     s << ">>>";
00296   s << term2;
00297 }
00298 
00299 void RelationalNode::streamTo(SourceStream &s) const
00300 {
00301   s << expr1;
00302   switch (oper) {
00303   case OpLess:
00304     s << " < ";
00305     break;
00306   case OpGreater:
00307     s << " > ";
00308     break;
00309   case OpLessEq:
00310     s << " <= ";
00311     break;
00312   case OpGreaterEq:
00313     s << " >= ";
00314     break;
00315   case OpInstanceOf:
00316     s << " instanceof ";
00317     break;
00318   case OpIn:
00319     s << " in ";
00320     break;
00321   default:
00322     ;
00323   }
00324   s << expr2;
00325 }
00326 
00327 void EqualNode::streamTo(SourceStream &s) const
00328 {
00329   s << expr1;
00330  switch (oper) {
00331  case OpEqEq:
00332    s << " == ";
00333    break;
00334  case OpNotEq:
00335    s << " != ";
00336    break;
00337  case OpStrEq:
00338    s << " === ";
00339    break;
00340  case OpStrNEq:
00341    s << " !== ";
00342    break;
00343  default:
00344    ;
00345  }
00346   s << expr2;
00347 }
00348 
00349 void BitOperNode::streamTo(SourceStream &s) const
00350 {
00351   s << expr1;
00352   if (oper == OpBitAnd)
00353     s << " & ";
00354   else if (oper == OpBitXOr)
00355     s << " ^ ";
00356   else
00357     s << " | ";
00358   s << expr2;
00359 }
00360 
00361 void BinaryLogicalNode::streamTo(SourceStream &s) const
00362 {
00363   s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
00364 }
00365 
00366 void ConditionalNode::streamTo(SourceStream &s) const
00367 {
00368   s << logical << " ? " << expr1 << " : " << expr2;
00369 }
00370 
00371 void AssignNode::streamTo(SourceStream &s) const
00372 {
00373   s << left;
00374   const char *opStr;
00375   switch (oper) {
00376   case OpEqual:
00377     opStr = " = ";
00378     break;
00379   case OpMultEq:
00380     opStr = " *= ";
00381     break;
00382   case OpDivEq:
00383     opStr = " /= ";
00384     break;
00385   case OpPlusEq:
00386     opStr = " += ";
00387     break;
00388   case OpMinusEq:
00389     opStr = " -= ";
00390     break;
00391   case OpLShift:
00392     opStr = " <<= ";
00393     break;
00394   case OpRShift:
00395     opStr = " >>= ";
00396     break;
00397   case OpURShift:
00398     opStr = " >>= ";
00399     break;
00400   case OpAndEq:
00401     opStr = " &= ";
00402     break;
00403   case OpXOrEq:
00404     opStr = " ^= ";
00405     break;
00406   case OpOrEq:
00407     opStr = " |= ";
00408     break;
00409   case OpModEq:
00410     opStr = " %= ";
00411     break;
00412   default:
00413     opStr = " ?= ";
00414   }
00415   s << opStr << expr;
00416 }
00417 
00418 void CommaNode::streamTo(SourceStream &s) const
00419 {
00420   s << expr1 << ", " << expr2;
00421 }
00422 
00423 void StatListNode::streamTo(SourceStream &s) const
00424 {
00425   for (const StatListNode *n = this; n; n = n->list)
00426     s << n->statement;
00427 }
00428 
00429 void AssignExprNode::streamTo(SourceStream &s) const
00430 {
00431   s << " = " << expr;
00432 }
00433 
00434 void VarDeclNode::streamTo(SourceStream &s) const
00435 {
00436   s << ident << init;
00437 }
00438 
00439 void VarDeclListNode::streamTo(SourceStream &s) const
00440 {
00441   s << var;
00442   for (VarDeclListNode *n = list; n; n = n->list)
00443     s << ", " << n->var;
00444 }
00445 
00446 void VarStatementNode::streamTo(SourceStream &s) const
00447 {
00448   s << SourceStream::Endl << "var " << list << ";";
00449 }
00450 
00451 void BlockNode::streamTo(SourceStream &s) const
00452 {
00453   s << SourceStream::Endl << "{" << SourceStream::Indent
00454     << source << SourceStream::Unindent << SourceStream::Endl << "}";
00455 }
00456 
00457 void EmptyStatementNode::streamTo(SourceStream &s) const
00458 {
00459   s << SourceStream::Endl << ";";
00460 }
00461 
00462 void ExprStatementNode::streamTo(SourceStream &s) const
00463 {
00464   s << SourceStream::Endl << expr << ";";
00465 }
00466 
00467 void IfNode::streamTo(SourceStream &s) const
00468 {
00469   s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
00470     << statement1 << SourceStream::Unindent;
00471   if (statement2)
00472     s << SourceStream::Endl << "else" << SourceStream::Indent
00473       << statement2 << SourceStream::Unindent;
00474 }
00475 
00476 void DoWhileNode::streamTo(SourceStream &s) const
00477 {
00478   s << SourceStream::Endl << "do " << SourceStream::Indent
00479     << statement << SourceStream::Unindent << SourceStream::Endl
00480     << "while (" << expr << ");";
00481 }
00482 
00483 void WhileNode::streamTo(SourceStream &s) const
00484 {
00485   s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
00486     << statement << SourceStream::Unindent;
00487 }
00488 
00489 void ForNode::streamTo(SourceStream &s) const
00490 {
00491   s << SourceStream::Endl << "for ("
00492     << expr1  // TODO: doesn't properly do "var i = 0"
00493     << "; " << expr2
00494     << "; " << expr3
00495     << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
00496 }
00497 
00498 void ForInNode::streamTo(SourceStream &s) const
00499 {
00500   s << SourceStream::Endl << "for (";
00501   if (varDecl)
00502     s << "var " << varDecl;
00503   if (init)
00504     s << " = " << init;
00505   s << " in " << expr << ")" << SourceStream::Indent
00506     << statement << SourceStream::Unindent;
00507 }
00508 
00509 void ContinueNode::streamTo(SourceStream &s) const
00510 {
00511   s << SourceStream::Endl << "continue";
00512   if (!ident.isNull())
00513     s << " " << ident;
00514   s << ";";
00515 }
00516 
00517 void BreakNode::streamTo(SourceStream &s) const
00518 {
00519   s << SourceStream::Endl << "break";
00520   if (!ident.isNull())
00521     s << " " << ident;
00522   s << ";";
00523 }
00524 
00525 void ReturnNode::streamTo(SourceStream &s) const
00526 {
00527   s << SourceStream::Endl << "return";
00528   if (value)
00529     s << " " << value;
00530   s << ";";
00531 }
00532 
00533 void WithNode::streamTo(SourceStream &s) const
00534 {
00535   s << SourceStream::Endl << "with (" << expr << ") "
00536     << statement;
00537 }
00538 
00539 void CaseClauseNode::streamTo(SourceStream &s) const
00540 {
00541   s << SourceStream::Endl;
00542   if (expr)
00543     s << "case " << expr;
00544   else
00545     s << "default";
00546   s << ":" << SourceStream::Indent;
00547   if (list)
00548     s << list;
00549   s << SourceStream::Unindent;
00550 }
00551 
00552 void ClauseListNode::streamTo(SourceStream &s) const
00553 {
00554   for (const ClauseListNode *n = this; n; n = n->next())
00555     s << n->clause();
00556 }
00557 
00558 void CaseBlockNode::streamTo(SourceStream &s) const
00559 {
00560   for (const ClauseListNode *n = list1; n; n = n->next())
00561     s << n->clause();
00562   if (def)
00563     s << def;
00564   for (const ClauseListNode *n = list2; n; n = n->next())
00565     s << n->clause();
00566 }
00567 
00568 void SwitchNode::streamTo(SourceStream &s) const
00569 {
00570   s << SourceStream::Endl << "switch (" << expr << ") {"
00571     << SourceStream::Indent << block << SourceStream::Unindent
00572     << SourceStream::Endl << "}";
00573 }
00574 
00575 void LabelNode::streamTo(SourceStream &s) const
00576 {
00577   s << SourceStream::Endl << label << ":" << SourceStream::Indent
00578     << statement << SourceStream::Unindent;
00579 }
00580 
00581 void ThrowNode::streamTo(SourceStream &s) const
00582 {
00583   s << SourceStream::Endl << "throw " << expr << ";";
00584 }
00585 
00586 void CatchNode::streamTo(SourceStream &s) const
00587 {
00588   s << SourceStream::Endl << "catch (" << ident << ")" << block;
00589 }
00590 
00591 void FinallyNode::streamTo(SourceStream &s) const
00592 {
00593   s << SourceStream::Endl << "finally " << block;
00594 }
00595 
00596 void TryNode::streamTo(SourceStream &s) const
00597 {
00598   s << SourceStream::Endl << "try " << block
00599     << _catch
00600     << _final;
00601 }
00602 
00603 void ParameterNode::streamTo(SourceStream &s) const
00604 {
00605   s << id;
00606   for (ParameterNode *n = next; n; n = n->next)
00607     s << ", " << n->id;
00608 }
00609 
00610 void FuncDeclNode::streamTo(SourceStream &s) const {
00611   s << SourceStream::Endl << "function " << ident << "(";
00612   if (param)
00613     s << param;
00614   s << ")" << body;
00615 }
00616 
00617 void FuncExprNode::streamTo(SourceStream &s) const
00618 {
00619   s << "function " << "("
00620     << param
00621     << ")" << body;
00622 }
00623 
00624 void SourceElementsNode::streamTo(SourceStream &s) const
00625 {
00626   for (const SourceElementsNode *n = this; n; n = n->elements)
00627     s << n->element;
00628 }
00629 
KDE Home | KDE Accessibility Home | Description of Access Keys