]> git.saurik.com Git - cycript.git/commitdiff
Made drastic changes to the serializer in order to support correctly serializing...
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 20 Oct 2009 10:22:24 +0000 (10:22 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 20 Oct 2009 10:22:24 +0000 (10:22 +0000)
Console.cpp
Cycript.l
Cycript.y
Library.mm
Output.cpp
Parser.hpp

index 77ee9f9c40f2171119669fb7cc53a4b19e2f78f2..e09ea01fc764214a0ad541b5d475a3571878f022 100644 (file)
@@ -280,7 +280,7 @@ static void Console(int socket) {
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.program_->Show(out);
+                driver.program_->Multiple(out);
                 code = str.str();
             }
         }
@@ -440,7 +440,7 @@ int main(int argc, char *argv[]) {
             else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.program_->Show(out);
+                driver.program_->Multiple(out);
                 std::string code(str.str());
                 if (compile)
                     std::cout << code;
index d62a14b09f3413553c69293d337db5d43a1482ba..516c8133b992c6bc50f669716e6a11268610e61e 100644 (file)
--- a/Cycript.l
+++ b/Cycript.l
@@ -114,6 +114,8 @@ RegularExpressionStart_ {RegularExpressionBody}{RegularExpressionEnd_}
         yylloc->end.lines(lines);
         yylloc->end.columns(left);
         yylloc->step();
+
+        N
     } else L
 }
 
index 42402f3935fa9f83a849a4224815eaae68e8babb..70022e7d12b5e3ef0d5bf198a7e978e5a3871834 100644 (file)
--- a/Cycript.y
+++ b/Cycript.y
@@ -59,7 +59,6 @@ typedef struct {
         CYBoolean *boolean_;
         CYClause *clause_;
         CYCatch *catch_;
-        CYClass *class_;
         CYClassName *className_;
         CYComprehension *comprehension_;
         CYCompound *compound_;
@@ -296,11 +295,12 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <clause_> CaseClausesOpt
 %type <catch_> CatchOpt
 %type <statement_> CategoryStatement
-%type <class_> ClassDefinition
+%type <expression_> ClassExpression
 %type <message_> ClassMessageDeclaration
 %type <message_> ClassMessageDeclarationListOpt
 %type <className_> ClassName
 %type <className_> ClassNameOpt
+%type <statement_> ClassStatement
 %type <expression_> ClassSuperOpt
 %type <field_> ClassFieldList
 %type <comprehension_> ComprehensionList
@@ -1268,11 +1268,11 @@ FinallyOpt
 
 /* 13 Function Definition {{{ */
 FunctionDeclaration
-    : "function" Identifier "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYFunction($2, $4, $7); }
+    : "function" Identifier "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYFunctionStatement($2, $4, $7); }
     ;
 
 FunctionExpression
-    : "function" IdentifierOpt "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYLambda($2, $4, $7); }
+    : "function" IdentifierOpt "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYFunctionExpression($2, $4, $7); }
     ;
 
 FormalParameterList_
@@ -1362,8 +1362,12 @@ ClassNameOpt
     | { $$ = NULL; }
     ;
 
-ClassDefinition
-    : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClass($2, $3, $4, $5); }
+ClassExpression
+    : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassExpression($2, $3, $4, $5); }
+    ;
+
+ClassStatement
+    : "@class" ClassName ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassStatement($2, $3, $4, $5); }
     ;
 
 CategoryStatement
@@ -1371,11 +1375,11 @@ CategoryStatement
     ;
 
 PrimaryExpression
-    : ClassDefinition { $$ = $1; }
+    : ClassExpression { $$ = $1; }
     ;
 
 Statement_
-    : ClassDefinition { $$ = $1; }
+    : ClassStatement { $$ = $1; }
     | CategoryStatement { $$ = $1; }
     ;
 /* }}} */
index e4bf70b8580f2ad3a07f334560296514153827e7..faed79e0d273da98d24d6034de558d08adc3e89e 100644 (file)
@@ -3469,7 +3469,7 @@ struct CYClient :
             } else {
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.program_->Show(out);
+                driver.program_->Multiple(out);
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
                 [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
index 09ee163a739f138b964081d9a9d0aab5e4afdefd..be38f058810a777740663362d0fe01ffac3aae38 100644 (file)
@@ -31,7 +31,7 @@ _finline CYFlags CYCenter(CYFlags flags) {
 }
 
 _finline CYFlags CYRight(CYFlags flags) {
-    return flags & (CYNoIn | CYNoTrailer);
+    return flags & (CYNoIn | CYNoTrailer | CYNoTerminator);
 }
 
 bool CYFalse::Value() const {
@@ -92,14 +92,13 @@ void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
-    lhs_->Output(out, Precedence() - 1, CYLeft(flags));
+    lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
     out << Operator();
     rhs_->Output(out, Precedence(), CYRight(flags));
 }
 
-void CYBlock::Output(CYOutput &out) const {
-    for (CYStatement *statement(statements_); statement != NULL; statement = statement->next_)
-        statement->Output(out);
+void CYBlock::Output(CYOutput &out, CYFlags flags) const {
+    statements_->Single(out, flags);
 }
 
 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
@@ -110,29 +109,39 @@ void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
         out << ' ';
 }
 
-void CYBreak::Output(CYOutput &out) const {
+void CYBreak::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "break";
     if (label_ != NULL)
         out << ' ' << *label_;
-    out << ';';
+    if ((flags & CYNoTerminator) == 0)
+        out << ';';
+    else if ((flags & CYNoTrailer) != 0)
+        out << ' ';
 }
 
 void CYCall::Output(CYOutput &out, CYFlags flags) const {
-    function_->Output(out, Precedence(), CYLeft(flags));
+    bool protect((flags & CYNoCall) != 0);
+    if (protect)
+        out << '(';
+    function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
     out << '(';
     if (arguments_ != NULL)
         arguments_->Output(out);
     out << ')';
+    if (protect)
+        out << ')';
 }
 
 void CYCatch::Output(CYOutput &out) const {
     out << "catch(" << *name_ << "){";
     if (code_ != NULL)
-        code_->Show(out);
+        code_->Multiple(out);
     out << "}";
 }
 
-void CYCategory::Output(CYOutput &out) const {
+void CYCategory::Output(CYOutput &out, CYFlags flags) const {
     out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
     out << "$cyp=object_getClass($cys);";
     out << "$cyc=$cys;";
@@ -140,12 +149,9 @@ void CYCategory::Output(CYOutput &out) const {
         messages_->Output(out, true);
     out << "})(";
     name_->ClassName(out, true);
-    out << ");";
-}
-
-void CYClass::Output(CYOutput &out) const {
-    Output(out, CYNoBF);
-    out << ";";
+    out << ')';
+    if ((flags & CYNoTerminator) == 0)
+        out << ';';
 }
 
 void CYClass::Output(CYOutput &out, CYFlags flags) const {
@@ -173,6 +179,14 @@ void CYClass::Output(CYOutput &out, CYFlags flags) const {
     out << "))";
 }
 
+void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
+    CYClass::Output(out, flags);
+}
+
+void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
+    CYClass::Output(out, flags);
+}
+
 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
     if (CYExpression *expression = expressions_)
         if (CYExpression *next = expression->next_) {
@@ -204,11 +218,16 @@ void CYCondition::Output(CYOutput &out, CYFlags flags) const {
     false_->Output(out, CYPA, CYRight(flags));
 }
 
-void CYContinue::Output(CYOutput &out) const {
+void CYContinue::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "continue";
     if (label_ != NULL)
         out << ' ' << *label_;
-    out << ';';
+    if ((flags & CYNoTerminator) == 0)
+        out << ';';
+    else if ((flags & CYNoTrailer) != 0)
+        out << ' ';
 }
 
 void CYClause::Output(CYOutput &out) const {
@@ -219,7 +238,7 @@ void CYClause::Output(CYOutput &out) const {
         out << "default";
     out << ':';
     if (code_ != NULL)
-        code_->Output(out, false);
+        code_->Multiple(out, next_ == NULL ? CYNoFlags : CYNoTrailer);
     if (next_ != NULL)
         out << *next_;
 }
@@ -231,8 +250,8 @@ const char *CYDeclaration::ForEachIn() const {
 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
     if ((flags & CYNoLeader) != 0)
         out << ' ';
-    out << "var ";
-    Output(out, CYRight(flags));
+    out << "var";
+    Output(out, CYRight(flags) | CYNoLeader);
 }
 
 void CYDeclaration::ForEachIn(CYOutput &out) const {
@@ -240,6 +259,8 @@ void CYDeclaration::ForEachIn(CYOutput &out) const {
 }
 
 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << *identifier_;
     if (initialiser_ != NULL) {
         out << '=';
@@ -249,16 +270,18 @@ void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYDeclarations::For(CYOutput &out) const {
-    out << "var ";
-    Output(out, CYNoIn);
+    out << "var";
+    Output(out, CYNoIn | CYNoLeader);
 }
 
 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
     const CYDeclarations *declaration(this);
+    bool first(true);
   output:
     CYDeclarations *next(declaration->next_);
-    CYFlags right(next == NULL ? CYRight(flags) : CYCenter(flags));
-    declaration->declaration_->Output(out, right);
+    CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
+    first = false;
+    declaration->declaration_->Output(out, jacks);
 
     if (next != NULL) {
         out << ',';
@@ -278,10 +301,11 @@ void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
     }
 }
 
-void CYDoWhile::Output(CYOutput &out) const {
-    // XXX: extra space character!
-    out << "do ";
-    code_->Output(out, false);
+void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
+    out << "do";
+    code_->Single(out, CYNoLeader | CYNoTrailer);
     out << "while(";
     test_->Output(out, CYNoFlags);
     out << ')';
@@ -296,20 +320,15 @@ void CYElement::Output(CYOutput &out) const {
         next_->Output(out);
 }
 
-void CYEmpty::Output(CYOutput &out) const {
+void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
     out << ';';
 }
 
-void CYEmpty::Output(CYOutput &out, bool block) const {
-    if (next_ != NULL)
-        CYStatement::Output(out, block);
-    else
-        out << "{}";
-}
-
-void CYExpress::Output(CYOutput &out) const {
-    expression_->Output(out, CYNoBF);
-    out << ';';
+void CYExpress::Output(CYOutput &out, CYFlags flags) const {
+    bool terminator((flags & CYNoTerminator) == 0);
+    expression_->Output(out, (terminator ? CYLeft(flags) : flags) | CYNoBF);
+    if (terminator)
+        out << ';';
 }
 
 void CYExpression::ClassName(CYOutput &out, bool object) const {
@@ -325,17 +344,15 @@ void CYExpression::For(CYOutput &out) const {
 }
 
 void CYExpression::ForEachIn(CYOutput &out) const {
-    // XXX: this should handle LeftHandSideExpression
-    Output(out, CYPA, CYNoFlags);
+    Output(out, CYPA, CYNoRightHand);
 }
 
 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
-    // XXX: this should handle LeftHandSideExpression
-    Output(out, flags);
+    Output(out, flags | CYNoRightHand);
 }
 
 void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
-    if (precedence < Precedence()) {
+    if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand()) {
         out << '(';
         Output(out, CYNoFlags);
         out << ')';
@@ -350,11 +367,13 @@ void CYField::Output(CYOutput &out) const {
 void CYFinally::Output(CYOutput &out) const {
     out << "finally{";
     if (code_ != NULL)
-        code_->Show(out);
+        code_->Multiple(out);
     out << "}";
 }
 
-void CYFor::Output(CYOutput &out) const {
+void CYFor::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "for(";
     if (initialiser_ != NULL)
         initialiser_->For(out);
@@ -365,10 +384,13 @@ void CYFor::Output(CYOutput &out) const {
     if (increment_ != NULL)
         increment_->Output(out, CYNoFlags);
     out << ')';
-    code_->Output(out, false);
+    code_->Single(out, CYNoFlags);
 }
 
-void CYForEachIn::Output(CYOutput &out) const {
+void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
+
     out << "with({$cys:0,$cyt:0}){";
 
     out << "$cys=";
@@ -380,7 +402,7 @@ void CYForEachIn::Output(CYOutput &out) const {
     initialiser_->ForEachIn(out);
     out << "=$cys[$cyt];";
 
-    code_->Show(out);
+    code_->Multiple(out);
 
     out << '}';
 
@@ -401,13 +423,15 @@ void CYForEachInComprehension::End_(CYOutput &out) const {
     out << "}}());";
 }
 
-void CYForIn::Output(CYOutput &out) const {
+void CYForIn::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "for(";
     initialiser_->ForIn(out, CYNoIn | CYNoTrailer);
     out << "in";
     set_->Output(out, CYNoLeader);
     out << ')';
-    code_->Output(out, false);
+    code_->Single(out, CYRight(flags));
 }
 
 void CYForInComprehension::Begin_(CYOutput &out) const {
@@ -416,8 +440,32 @@ void CYForInComprehension::Begin_(CYOutput &out) const {
     out << ')';
 }
 
-void CYFunction::Output(CYOutput &out) const {
-    CYLambda::Output(out, CYNoFlags);
+void CYFunction::Output(CYOutput &out, CYFlags flags) const {
+    bool protect((flags & CYNoFunction) != 0);
+    if (protect)
+        out << '(';
+    else if ((flags & CYNoLeader) != 0)
+        out << ' ';
+    out << "function";
+    if (name_ != NULL)
+        out << ' ' << *name_;
+    out << '(';
+    if (parameters_ != NULL)
+        out << *parameters_;
+    out << "){";
+    if (body_ != NULL)
+        body_->Multiple(out);
+    out << '}';
+    if (protect)
+        out << ')';
+}
+
+void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
+    CYFunction::Output(out, flags);
+}
+
+void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
+    CYFunction::Output(out, flags);
 }
 
 void CYFunctionParameter::Output(CYOutput &out) const {
@@ -428,15 +476,28 @@ void CYFunctionParameter::Output(CYOutput &out) const {
     }
 }
 
-void CYIf::Output(CYOutput &out) const {
+void CYIf::Output(CYOutput &out, CYFlags flags) const {
+    bool protect(false);
+    if (false_ == NULL && (flags & CYNoDangle) != 0) {
+        protect = true;
+        out << '{';
+    } else if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "if(";
     test_->Output(out, CYNoFlags);
     out << ')';
-    true_->Output(out, true);
+    CYFlags right(protect ? CYNoFlags : CYRight(flags));
+    CYFlags jacks(CYNoDangle);
+    jacks |= false_ == NULL ? right : CYNoTrailer;
+    true_->Single(out, jacks);
     if (false_ != NULL) {
-        out << "else ";
-        false_->Output(out, false);
+        out << "else";
+        if (protect)
+            right |= CYNoTerminator;
+        false_->Single(out, CYNoLeader | right);
     }
+    if (protect)
+        out << '}';
 }
 
 void CYIfComprehension::Begin_(CYOutput &out) const {
@@ -448,6 +509,8 @@ void CYIfComprehension::Begin_(CYOutput &out) const {
 void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
     rhs_->Output(out, 1, CYLeft(flags));
     out << ".$cyi";
+    if ((flags & CYNoTrailer) != 0)
+        out << ' ';
 }
 
 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
@@ -483,32 +546,14 @@ void CYInfix::Output(CYOutput &out, CYFlags flags) const {
         out << ')';
 }
 
-void CYLambda::Output(CYOutput &out, CYFlags flags) const {
-    bool protect((flags & CYNoFunction) != 0);
-    if (protect)
-        out << '(';
-    else if ((flags & CYNoLeader) != 0)
+void CYLet::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
         out << ' ';
-    out << "function";
-    if (name_ != NULL)
-        out << ' ' << *name_;
-    out << '(';
-    if (parameters_ != NULL)
-        out << *parameters_;
-    out << "){";
-    if (body_ != NULL)
-        body_->Show(out);
-    out << '}';
-    if (protect)
-        out << ')';
-}
-
-void CYLet::Output(CYOutput &out) const {
     out << "let(";
     declarations_->Output(out, CYNoFlags);
     out << "){";
     if (statements_ != NULL)
-        statements_->Show(out);
+        statements_->Multiple(out);
     out << "}";
 }
 
@@ -531,7 +576,7 @@ void CYMessage::Output(CYOutput &out, bool replace) const {
             out << ',' << *parameter->name_;
     out << "){return function(){";
     if (body_ != NULL)
-        body_->Show(out);
+        body_->Multiple(out);
     out << "}.call(self);},$cyt),$cyt);";
 }
 
@@ -539,11 +584,12 @@ void CYNew::Output(CYOutput &out, CYFlags flags) const {
     if ((flags & CYNoLeader) != 0)
         out << ' ';
     out << "new";
-    constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader);
-    out << '(';
-    if (arguments_ != NULL)
+    constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader | CYNoCall);
+    if (arguments_ != NULL) {
+        out << '(';
         arguments_->Output(out);
-    out << ')';
+        out << ')';
+    }
 }
 
 void CYNull::Output(CYOutput &out, CYFlags flags) const {
@@ -565,7 +611,7 @@ void CYNumber::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYNumber::PropertyName(CYOutput &out) const {
-    Output(out);
+    Output(out, CYNoFlags);
 }
 
 void CYObject::Output(CYOutput &out, CYFlags flags) const {
@@ -613,11 +659,15 @@ void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
         out << ' ';
 }
 
-void CYReturn::Output(CYOutput &out) const {
+void CYReturn::Output(CYOutput &out, CYFlags flags) const {
+    bool terminator((flags & CYNoTerminator) == 0);
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "return";
     if (value_ != NULL)
-        value_->Output(out, CYNoLeader);
-    out << ';';
+        value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
+    if (terminator)
+        out << ';';
 }
 
 void CYSelector::Output(CYOutput &out, CYFlags flags) const {
@@ -660,27 +710,35 @@ void CYSend::Output(CYOutput &out, CYFlags flags) const {
     out << ')';
 }
 
-void CYStatement::Show(CYOutput &out) const {
-    for (const CYStatement *next(this); next != NULL; next = next->next_)
-        next->Output_(out);
+void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
+    bool first(true);
+    for (const CYStatement *next(this); next != NULL; next = next->next_) {
+        bool last(next->next_ == NULL);
+        CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
+        if (last)
+            jacks |= CYNoTerminator;
+        first = false;
+        next->Output(out, jacks);
+    }
 }
 
-void CYStatement::Output(CYOutput &out, bool block) const {
-    if (!block && !IsBlock())
-        Output(out);
-    else {
+void CYStatement::Single(CYOutput &out, CYFlags flags) const {
+    if (next_ != NULL) {
         out << '{';
-        Show(out);
+        Multiple(out);
         out << '}';
+    } else {
+        bool protect(false);
+        if (labels_ != NULL && (flags & CYNoLeader) != 0)
+            protect = true;
+        if (protect)
+            out << ' ';
+        for (CYLabel *label(labels_); label != NULL; label = label->next_)
+            out << *label->name_ << ':';
+        Output(out, protect ? CYRight(flags) : flags);
     }
 }
 
-void CYStatement::Output_(CYOutput &out) const {
-    for (CYLabel *label(labels_); label != NULL; label = label->next_)
-        out << *label->name_ << ':';
-    Output(out);
-}
-
 void CYString::Output(CYOutput &out, CYFlags flags) const {
     unsigned quot(0), apos(0);
     for (const char *value(value_), *end(value_ + size_); value != end; ++value)
@@ -727,10 +785,12 @@ void CYString::PropertyName(CYOutput &out) const {
     if (const char *word = Word())
         out << word;
     else
-        Output(out);
+        Output(out, CYNoFlags);
 }
 
-void CYSwitch::Output(CYOutput &out) const {
+void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "switch(";
     value_->Output(out, CYNoFlags);
     out << "){";
@@ -747,17 +807,23 @@ void CYThis::Output(CYOutput &out, CYFlags flags) const {
         out << ' ';
 }
 
-void CYThrow::Output(CYOutput &out) const {
+void CYThrow::Output(CYOutput &out, CYFlags flags) const {
+    bool terminator((flags & CYNoTerminator) == 0);
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "throw";
     if (value_ != NULL)
-        value_->Output(out, CYNoLeader);
-    out << ';';
+        value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
+    if (terminator)
+        out << ';';
 }
 
-void CYTry::Output(CYOutput &out) const {
+void CYTry::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "try{";
     if (code_ != NULL)
-        code_->Show(out);
+        code_->Multiple(out);
     out << "}";
     if (catch_ != NULL)
         catch_->Output(out);
@@ -765,10 +831,14 @@ void CYTry::Output(CYOutput &out) const {
         finally_->Output(out);
 }
 
-void CYVar::Output(CYOutput &out) const {
-    out << "var ";
-    declarations_->Output(out, CYNoFlags);
-    out << ';';
+void CYVar::Output(CYOutput &out, CYFlags flags) const {
+    bool terminator((flags & CYNoTerminator) == 0);
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
+    out << "var";
+    declarations_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
+    if (terminator)
+        out << ';';
 }
 
 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
@@ -779,18 +849,22 @@ void CYVariable::Output(CYOutput &out, CYFlags flags) const {
         out << ' ';
 }
 
-void CYWhile::Output(CYOutput &out) const {
+void CYWhile::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "while(";
     test_->Output(out, CYNoFlags);
     out << ')';
-    code_->Output(out, false);
+    code_->Single(out, CYRight(flags));
 }
 
-void CYWith::Output(CYOutput &out) const {
+void CYWith::Output(CYOutput &out, CYFlags flags) const {
+    if ((flags & CYNoLeader) != 0)
+        out << ' ';
     out << "with(";
     scope_->Output(out, CYNoFlags);
     out << ')';
-    code_->Output(out, false);
+    code_->Single(out, CYRight(flags));
 }
 
 void CYWord::ClassName(CYOutput &out, bool object) const {
index 6fde458b31cc43b6504550ca050d8377b66b8070..bf73389cf415fb3edfe6cf0d9f2061fdd8fcbf49 100644 (file)
@@ -149,6 +149,27 @@ struct CYLabel :
     }
 };
 
+enum CYNeeded {
+    CYNever     = -1,
+    CYSometimes =  0,
+    CYAlways    =  1,
+};
+
+enum CYFlags {
+    CYNoFlags =      0,
+    CYNoBrace =      (1 << 0),
+    CYNoFunction =   (1 << 1),
+    CYNoLeader =     (1 << 2),
+    CYNoTrailer =    (1 << 3),
+    CYNoIn =         (1 << 4),
+    CYNoHyphen =     (1 << 5),
+    CYNoCall =       (1 << 6),
+    CYNoRightHand =  (1 << 7),
+    CYNoDangle =     (1 << 8),
+    CYNoTerminator = (1 << 9),
+    CYNoBF =         (CYNoBrace | CYNoFunction),
+};
+
 struct CYStatement :
     CYNext<CYStatement>
 {
@@ -167,10 +188,11 @@ struct CYStatement :
         return next_ != NULL;
     }
 
-    virtual void Show(CYOutput &out) const;
-    virtual void Output(CYOutput &out) const = 0;
-    virtual void Output(CYOutput &out, bool block) const;
-    virtual void Output_(CYOutput &out) const;
+    virtual void Single(CYOutput &out, CYFlags flags) const;
+    virtual void Multiple(CYOutput &out, CYFlags flags = CYNoFlags) const;
+
+  private:
+    virtual void Output(CYOutput &out, CYFlags flags) const = 0;
 };
 
 struct CYBlock :
@@ -187,7 +209,7 @@ struct CYBlock :
         return true;
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 enum CYState {
@@ -240,17 +262,6 @@ class CYDriver {
     void Warning(const cy::location &location, const char *message);
 };
 
-enum CYFlags {
-    CYNoFlags =    0,
-    CYNoBrace =    (1 << 0),
-    CYNoFunction = (1 << 1),
-    CYNoLeader =   (1 << 2),
-    CYNoTrailer =  (1 << 3),
-    CYNoIn =       (1 << 4),
-    CYNoHyphen =   (1 << 5),
-    CYNoBF =       (CYNoBrace | CYNoFunction),
-};
-
 struct CYForInitialiser {
     virtual void For(CYOutput &out) const = 0;
 };
@@ -269,6 +280,10 @@ struct CYExpression :
 {
     virtual unsigned Precedence() const = 0;
 
+    virtual bool RightHand() const {
+        return true;
+    }
+
     virtual void For(CYOutput &out) const;
     virtual void ForIn(CYOutput &out, CYFlags flags) const;
 
@@ -295,6 +310,11 @@ struct CYExpression :
         return value; \
     }
 
+#define CYRightHand(value) \
+    virtual bool RightHand() const { \
+        return value; \
+    }
+
 struct CYCompound :
     CYExpression
 {
@@ -407,12 +427,14 @@ struct CYLiteral :
     CYExpression
 {
     CYPrecedence(0)
+    CYRightHand(false)
 };
 
 struct CYMagic :
     CYExpression
 {
     CYPrecedence(0)
+    CYRightHand(false)
 };
 
 struct CYSelectorPart :
@@ -502,10 +524,6 @@ struct CYString :
         return Value();
     }
 
-    virtual void Output(CYOutput &out) const {
-        return Output(out, CYNoFlags);
-    }
-
     virtual void Output(CYOutput &out, CYFlags flags) const;
     virtual void PropertyName(CYOutput &out) const;
 };
@@ -525,10 +543,6 @@ struct CYNumber :
         return value_;
     }
 
-    virtual void Output(CYOutput &out) const {
-        return Output(out, CYNoFlags);
-    }
-
     virtual void Output(CYOutput &out, CYFlags flags) const;
     virtual void PropertyName(CYOutput &out) const;
 };
@@ -616,6 +630,7 @@ struct CYVariable :
     }
 
     CYPrecedence(0)
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -808,7 +823,7 @@ struct CYVar :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYLet :
@@ -823,7 +838,7 @@ struct CYLet :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYField :
@@ -866,10 +881,7 @@ struct CYMessage :
     virtual void Output(CYOutput &out, bool replace) const;
 };
 
-struct CYClass :
-    CYExpression,
-    CYStatement
-{
+struct CYClass {
     CYClassName *name_;
     CYExpression *super_;
     CYField *fields_;
@@ -883,9 +895,32 @@ struct CYClass :
     {
     }
 
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYClassExpression :
+    CYClass,
+    CYExpression
+{
+    CYClassExpression(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) :
+        CYClass(name, super, fields, messages)
+    {
+    }
+
     CYPrecedence(0)
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYClassStatement :
+    CYClass,
+    CYStatement
+{
+    CYClassStatement(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) :
+        CYClass(name, super, fields, messages)
+    {
+    }
+
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
@@ -901,7 +936,7 @@ struct CYCategory :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYFunctionParameter :
@@ -935,7 +970,7 @@ struct CYFor :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYForIn :
@@ -952,7 +987,7 @@ struct CYForIn :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYForEachIn :
@@ -969,7 +1004,7 @@ struct CYForEachIn :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYProperty :
@@ -1059,6 +1094,7 @@ struct CYDirectMember :
     }
 
     CYPrecedence(1)
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -1072,6 +1108,7 @@ struct CYIndirectMember :
     }
 
     CYPrecedence(1)
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -1088,7 +1125,11 @@ struct CYNew :
     {
     }
 
-    CYPrecedence(1)
+    virtual unsigned Precedence() const {
+        return arguments_ == NULL ? 2 : 1;
+    }
+
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -1105,7 +1146,8 @@ struct CYCall :
     {
     }
 
-    CYPrecedence(2)
+    CYPrecedence(1)
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -1124,7 +1166,7 @@ struct CYIf :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYDoWhile :
@@ -1139,7 +1181,7 @@ struct CYDoWhile :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYWhile :
@@ -1154,38 +1196,49 @@ struct CYWhile :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYLambda :
-    CYExpression
-{
+struct CYFunction {
     CYIdentifier *name_;
     CYFunctionParameter *parameters_;
     CYStatement *body_;
 
-    CYLambda(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
+    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
         name_(name),
         parameters_(parameters),
         body_(body)
     {
     }
 
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYFunctionExpression :
+    CYFunction,
+    CYExpression
+{
+    CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
+        CYFunction(name, parameters, body)
+    {
+    }
+
     CYPrecedence(0)
+    CYRightHand(false)
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYFunction :
-    CYLambda,
+struct CYFunctionStatement :
+    CYFunction,
     CYStatement
 {
-    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
-        CYLambda(name, parameters, body)
+    CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *body) :
+        CYFunction(name, parameters, body)
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYExpress :
@@ -1198,7 +1251,7 @@ struct CYExpress :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYContinue :
@@ -1211,7 +1264,7 @@ struct CYContinue :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYBreak :
@@ -1224,7 +1277,7 @@ struct CYBreak :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYReturn :
@@ -1237,14 +1290,13 @@ struct CYReturn :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYEmpty :
     CYStatement
 {
-    virtual void Output(CYOutput &out) const;
-    virtual void Output(CYOutput &out, bool block) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYFinally {
@@ -1272,7 +1324,7 @@ struct CYTry :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYThrow :
@@ -1285,7 +1337,7 @@ struct CYThrow :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYWith :
@@ -1300,7 +1352,7 @@ struct CYWith :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYSwitch :
@@ -1315,7 +1367,7 @@ struct CYSwitch :
     {
     }
 
-    virtual void Output(CYOutput &out) const;
+    virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
 struct CYCondition :