From d35a3b07965ee394c89615d9648c45face9f7f07 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 2 Oct 2009 04:29:06 +0000 Subject: [PATCH] Drastically improved serializer. --- Application.mm | 2 + Cycript.l | 92 ++++++++++++++++--------- Cycript.y | 82 +++++++++++++++++++--- Library.mm | 3 +- Output.cpp | 180 ++++++++++++++++++++++++++++++++----------------- Parser.hpp | 123 ++++++++++++++++++++++++--------- cycript.hpp | 6 +- 7 files changed, 350 insertions(+), 138 deletions(-) diff --git a/Application.mm b/Application.mm index c5c6936..d5478a3 100644 --- a/Application.mm +++ b/Application.mm @@ -51,6 +51,7 @@ int main(int argc, const char *argv[]) { if (!extra) { extra = true; if (line[0] == '\\') { + add_history(line); goto restart; } } @@ -70,6 +71,7 @@ int main(int argc, const char *argv[]) { cy::position begin(i->location_.begin); if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) { std::cerr << i->message_ << std::endl; + add_history(command.c_str()); goto restart; } } diff --git a/Cycript.l b/Cycript.l index 4a54403..b1ff59a 100644 --- a/Cycript.l +++ b/Cycript.l @@ -119,36 +119,68 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} "[" L C return tk::OpenBracket; "]" L C return tk::CloseBracket; -"@selector" L C return tk::AtSelector; - -"break" L R yylval->word_ = new CYWord("break"); return tk::Break; -"case" L C yylval->word_ = new CYWord("case"); return tk::Case; -"catch" L C yylval->word_ = new CYWord("catch"); return tk::Catch; -"continue" L R yylval->word_ = new CYWord("continue"); return tk::Continue; -"default" L C yylval->word_ = new CYWord("default"); return tk::Default; -"delete" L C yylval->word_ = new CYWord("delete"); return tk::Delete; -"do" L C yylval->word_ = new CYWord("do"); return tk::Do; -"else" L C yylval->word_ = new CYWord("else"); return tk::Else; -"false" L C yylval->false_ = new CYFalse(); return tk::False; -"finally" L C yylval->word_ = new CYWord("finally"); return tk::Finally; -"for" L C yylval->word_ = new CYWord("for"); return tk::For; -"function" L C yylval->word_ = new CYWord("function"); return tk::Function; -"if" L C yylval->word_ = new CYWord("if"); return tk::If; -"in" L C yylval->word_ = new CYWord("in"); return tk::In; -"instanceof" L C yylval->word_ = new CYWord("instanceof"); return tk::InstanceOf; -"new" L C yylval->word_ = new CYWord("new"); return tk::New; -"null" L C yylval->null_ = new CYNull(); return tk::Null; -"return" L R yylval->word_ = new CYWord("return"); return tk::Return; -"switch" L C yylval->word_ = new CYWord("switch"); return tk::Switch; -"this" L C yylval->this_ = new CYThis(); return tk::This; -"throw" L R yylval->word_ = new CYWord("throw"); return tk::Throw; -"true" L C yylval->true_ = new CYTrue(); return tk::True; -"try" L C yylval->word_ = new CYWord("try"); return tk::Try; -"typeof" L C yylval->word_ = new CYWord("typeof"); return tk::TypeOf; -"var" L C yylval->word_ = new CYWord("var"); return tk::Var; -"void" L C yylval->word_ = new CYWord("void"); return tk::Void; -"while" L C yylval->word_ = new CYWord("while"); return tk::While; -"with" L C yylval->word_ = new CYWord("with"); return tk::With; +"@selector" L C return tk::AtSelector; + +"break" L R yylval->word_ = new CYWord("break"); return tk::Break; +"case" L C yylval->word_ = new CYWord("case"); return tk::Case; +"catch" L C yylval->word_ = new CYWord("catch"); return tk::Catch; +"continue" L R yylval->word_ = new CYWord("continue"); return tk::Continue; +"default" L C yylval->word_ = new CYWord("default"); return tk::Default; +"delete" L C yylval->word_ = new CYWord("delete"); return tk::Delete; +"do" L C yylval->word_ = new CYWord("do"); return tk::Do; +"else" L C yylval->word_ = new CYWord("else"); return tk::Else; +"false" L C yylval->false_ = new CYFalse(); return tk::False; +"finally" L C yylval->word_ = new CYWord("finally"); return tk::Finally; +"for" L C yylval->word_ = new CYWord("for"); return tk::For; +"function" L C yylval->word_ = new CYWord("function"); return tk::Function; +"if" L C yylval->word_ = new CYWord("if"); return tk::If; +"in" L C yylval->word_ = new CYWord("in"); return tk::In; +"instanceof" L C yylval->word_ = new CYWord("instanceof"); return tk::InstanceOf; +"new" L C yylval->word_ = new CYWord("new"); return tk::New; +"null" L C yylval->null_ = new CYNull(); return tk::Null; +"return" L R yylval->word_ = new CYWord("return"); return tk::Return; +"switch" L C yylval->word_ = new CYWord("switch"); return tk::Switch; +"this" L C yylval->this_ = new CYThis(); return tk::This; +"throw" L R yylval->word_ = new CYWord("throw"); return tk::Throw; +"true" L C yylval->true_ = new CYTrue(); return tk::True; +"try" L C yylval->word_ = new CYWord("try"); return tk::Try; +"typeof" L C yylval->word_ = new CYWord("typeof"); return tk::TypeOf; +"var" L C yylval->word_ = new CYWord("var"); return tk::Var; +"void" L C yylval->word_ = new CYWord("void"); return tk::Void; +"while" L C yylval->word_ = new CYWord("while"); return tk::While; +"with" L C yylval->word_ = new CYWord("with"); return tk::With; + +"abstract" L C yylval->word_ = new CYWord("abstract"); return tk::Abstract; +"boolean" L C yylval->word_ = new CYWord("boolean"); return tk::Boolean; +"byte" L C yylval->word_ = new CYWord("byte"); return tk::Byte; +"char" L C yylval->word_ = new CYWord("char"); return tk::Char; +"class" L C yylval->word_ = new CYWord("class"); return tk::Class; +"const" L C yylval->word_ = new CYWord("const"); return tk::Const; +"debugger" L C yylval->word_ = new CYWord("debugger"); return tk::Debugger; +"double" L C yylval->word_ = new CYWord("double"); return tk::Double; +"enum" L C yylval->word_ = new CYWord("enum"); return tk::Enum; +"export" L C yylval->word_ = new CYWord("export"); return tk::Export; +"extends" L C yylval->word_ = new CYWord("extends"); return tk::Extends; +"final" L C yylval->word_ = new CYWord("final"); return tk::Final; +"float" L C yylval->word_ = new CYWord("float"); return tk::Float; +"goto" L C yylval->word_ = new CYWord("goto"); return tk::Goto; +"implements" L C yylval->word_ = new CYWord("implements"); return tk::Implements; +"import" L C yylval->word_ = new CYWord("import"); return tk::Import; +"int" L C yylval->word_ = new CYWord("int"); return tk::Int; +"interface" L C yylval->word_ = new CYWord("interface"); return tk::Interface; +"long" L C yylval->word_ = new CYWord("long"); return tk::Long; +"native" L C yylval->word_ = new CYWord("native"); return tk::Native; +"package" L C yylval->word_ = new CYWord("package"); return tk::Package; +"private" L C yylval->word_ = new CYWord("private"); return tk::Private; +"protected" L C yylval->word_ = new CYWord("protected"); return tk::Protected; +"public" L C yylval->word_ = new CYWord("public"); return tk::Public; +"short" L C yylval->word_ = new CYWord("short"); return tk::Short; +"static" L C yylval->word_ = new CYWord("static"); return tk::Static; +"super" L C yylval->word_ = new CYWord("super"); return tk::Super; +"synchronized" L C yylval->word_ = new CYWord("synchronized"); return tk::Synchronized; +"throws" L C yylval->word_ = new CYWord("throws"); return tk::Throws; +"transient" L C yylval->word_ = new CYWord("transient"); return tk::Transient; +"volatile" L C yylval->word_ = new CYWord("volatile"); return tk::Volatile; [a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier; diff --git a/Cycript.y b/Cycript.y index 31fd1bc..b1d2230 100644 --- a/Cycript.y +++ b/Cycript.y @@ -15,6 +15,7 @@ typedef struct { CYBoolean *boolean_; CYClause *clause_; CYCatch *catch_; + CYCompound *compound_; CYDeclaration *declaration_; CYDeclarations *declarations_; CYElement *element_; @@ -120,6 +121,8 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token CloseBracket "]" %token AtSelector "@selector" +%token AtImplementation "@implementation" +%token AtEnd "@end" %token Break "break" %token Case "case" @@ -150,6 +153,38 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token While "while" %token With "with" +%token Abstract "abstract" +%token Boolean "boolean" +%token Byte "byte" +%token Char "char" +%token Class "class" +%token Const "const" +%token Debugger "debugger" +%token Double "double" +%token Enum "enum" +%token Export "export" +%token Extends "extends" +%token Final "final" +%token Float "float" +%token Goto "goto" +%token Implements "implements" +%token Import "import" +%token Int "int" +%token Interface "interface" +%token Long "long" +%token Native "native" +%token Package "package" +%token Private "private" +%token Protected "protected" +%token Public "public" +%token Short "short" +%token Static "static" +%token Super "super" +%token Synchronized "synchronized" +%token Throws "throws" +%token Transient "transient" +%token Volatile "volatile" + %token Identifier %token NumericLiteral %token StringLiteral @@ -199,10 +234,10 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type EqualityExpressionNoIn %type Expression %type ExpressionOpt -%type Expression_ +%type Expression_ %type ExpressionNoBF %type ExpressionNoIn -%type ExpressionNoIn_ +%type ExpressionNoIn_ %type ExpressionNoInOpt %type ExpressionStatement %type FinallyOpt @@ -327,32 +362,63 @@ WordOpt Word : Identifier { $$ = $1; } + | "abstract" { $$ = $1; } + | "boolean" { $$ = $1; } | "break" NewLineOpt { $$ = $1; } + | "byte" { $$ = $1; } | "case" { $$ = $1; } | "catch" { $$ = $1; } + | "char" { $$ = $1; } + | "class" { $$ = $1; } + | "const" { $$ = $1; } | "continue" NewLineOpt { $$ = $1; } + | "debugger" { $$ = $1; } | "default" { $$ = $1; } | "delete" { $$ = $1; } | "do" { $$ = $1; } + | "double" { $$ = $1; } | "else" { $$ = $1; } + | "enum" { $$ = $1; } + | "export" { $$ = $1; } + | "extends" { $$ = $1; } | "false" { $$ = $1; } + | "final" { $$ = $1; } | "finally" { $$ = $1; } + | "float" { $$ = $1; } | "for" { $$ = $1; } | "function" { $$ = $1; } + | "goto" { $$ = $1; } | "if" { $$ = $1; } + | "implements" { $$ = $1; } + | "import" { $$ = $1; } /* XXX: | "in" { $$ = $1; } */ /* XXX: | "instanceof" { $$ = $1; } */ + | "int" { $$ = $1; } + | "interface" { $$ = $1; } + | "long" { $$ = $1; } + | "native" { $$ = $1; } | "new" { $$ = $1; } | "null" { $$ = $1; } + | "package" { $$ = $1; } + | "private" { $$ = $1; } + | "protected" { $$ = $1; } + | "public" { $$ = $1; } | "return" NewLineOpt { $$ = $1; } + | "short" { $$ = $1; } + | "static" { $$ = $1; } + | "super" { $$ = $1; } | "switch" { $$ = $1; } + | "synchronized" { $$ = $1; } | "this" { $$ = $1; } | "throw" NewLineOpt { $$ = $1; } + | "throws" { $$ = $1; } + | "transient" { $$ = $1; } | "true" { $$ = $1; } | "try" { $$ = $1; } | "typeof" { $$ = $1; } | "var" { $$ = $1; } | "void" { $$ = $1; } + | "volatile" { $$ = $1; } | "while" { $$ = $1; } | "with" { $$ = $1; } ; @@ -398,7 +464,7 @@ PrimaryExpressionNoBF /* }}} */ /* 11.1.4 Array Initialiser {{{ */ ArrayLiteral - : "[" ElementList "]" { $$ = new(driver.pool_) CYArray($2); } + : "[" ElementListOpt "]" { $$ = new(driver.pool_) CYArray($2); } ; Element @@ -791,12 +857,12 @@ AssignmentExpressionNoBF ; Expression_ - : "," Expression { $$ = $2; } + : "," Expression { $$ = new(driver.pool_) CYCompound($2); } | { $$ = NULL; } ; ExpressionNoIn_ - : "," ExpressionNoIn { $$ = $2; } + : "," ExpressionNoIn { $$ = new(driver.pool_) CYCompound($2); } | { $$ = NULL; } ; @@ -811,15 +877,15 @@ ExpressionNoInOpt ; Expression - : AssignmentExpression Expression_ { if ($1) { $1->SetNext($2); $$ = $1; } else $$ = $2; } + : AssignmentExpression Expression_ { if ($2) { $2->AddPrev($1); $$ = $2; } else $$ = $1; } ; ExpressionNoIn - : AssignmentExpressionNoIn ExpressionNoIn_ { if ($1) { $1->SetNext($2); $$ = $1; } else $$ = $2; } + : AssignmentExpressionNoIn ExpressionNoIn_ { if ($2) { $2->AddPrev($1); $$ = $2; } else $$ = $1; } ; ExpressionNoBF - : AssignmentExpressionNoBF Expression_ { if ($1) { $1->SetNext($2); $$ = $1; } else $$ = $2; } + : AssignmentExpressionNoBF Expression_ { if ($2) { $2->AddPrev($1); $$ = $2; } else $$ = $1; } ; Statement diff --git a/Library.mm b/Library.mm index 61edf63..b4eb9f5 100644 --- a/Library.mm +++ b/Library.mm @@ -188,8 +188,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { - (NSString *) cy$toJSON { NSMutableString *json([[[NSMutableString alloc] init] autorelease]); - [json appendString:@"("]; - [json appendString:@"{"]; + [json appendString:@"({"]; bool comma(false); for (id key in self) { diff --git a/Output.cpp b/Output.cpp index 647f47e..27b07b0 100644 --- a/Output.cpp +++ b/Output.cpp @@ -3,28 +3,27 @@ #include #include +#define CYPA 16 + void CYAddressOf::Output(std::ostream &out) const { - out << *rhs_ << ".$()"; + rhs_->Output(out, 1); + out << ".$()"; } -void CYArgument::Output(std::ostream &out, bool send) const { - if (!send && name_ != NULL) { +void CYArgument::Output(std::ostream &out) const { + if (name_ != NULL) { out << *name_; if (value_ != NULL) out << ":"; } - if (value_ != NULL) { - if (send) - out << ','; - value_->Output(out, true); - } + if (value_ != NULL) + value_->Output(out, false); if (next_ != NULL) { - if (!send) - if (next_->name_ == NULL) - out << ','; - else - out << ' '; - next_->Output(out, send); + if (next_->name_ == NULL) + out << ','; + else + out << ' '; + next_->Output(out); } } @@ -35,6 +34,12 @@ void CYArray::Output(std::ostream &out) const { out << ']'; } +void CYAssignment::Output(std::ostream &out) const { + lhs_->Output(out, Precedence() - 1); + out << Operator(); + rhs_->Output(out, Precedence()); +} + void CYBoolean::Output(std::ostream &out) const { out << (Value() ? "true" : "false"); } @@ -47,9 +52,10 @@ void CYBreak::Output(std::ostream &out) const { } void CYCall::Output(std::ostream &out) const { - out << *function_ << '('; + function_->Output(out, 2); + out << '('; if (arguments_ != NULL) - arguments_->Output(out, false); + arguments_->Output(out); out << ')'; } @@ -59,10 +65,12 @@ void CYCatch::Output(std::ostream &out) const { } void CYCondition::Output(std::ostream &out) const { - out << *test_ << '?'; + test_->Output(out, Precedence() - 1); + out << '?'; if (true_ != NULL) - out << *true_; - out << ':' << *false_; + true_->Output(out, CYPA); + out << ':'; + false_->Output(out, CYPA); } void CYContinue::Output(std::ostream &out) const { @@ -73,9 +81,10 @@ void CYContinue::Output(std::ostream &out) const { } void CYClause::Output(std::ostream &out) const { - if (case_ != NULL) - out << "case" << *case_; - else + if (case_ != NULL) { + out << "case"; + case_->Output(out); + } else out << "default"; out << ':'; if (code_ != NULL) @@ -90,17 +99,24 @@ void CYDeclaration::Part(std::ostream &out) const { void CYDeclaration::Output(std::ostream &out) const { out << *identifier_; - if (initialiser_ != NULL) - out << '=' << *initialiser_; + if (initialiser_ != NULL) { + out << '='; + initialiser_->Output(out, CYPA); + } } void CYDeclarations::Part(std::ostream &out) const { out << "var "; + const CYDeclarations *declaration(this); - do { - out << *declaration->declaration_; - declaration = declaration->next_; - } while (declaration != NULL); + output: + out << *declaration->declaration_; + declaration = declaration->next_; + + if (declaration != NULL) { + out << ','; + goto output; + } } void CYDeclarations::Output(std::ostream &out) const { @@ -111,12 +127,14 @@ void CYDeclarations::Output(std::ostream &out) const { void CYDoWhile::Output(std::ostream &out) const { out << "do "; code_->Output(out, false); - out << "while" << *test_ << ';'; + out << "while("; + test_->Output(out); + out << ';'; } void CYElement::Output(std::ostream &out) const { if (value_ != NULL) - value_->Output(out, true); + value_->Output(out, CYPA); if (next_ != NULL || value_ == NULL) out << ','; if (next_ != NULL) @@ -135,23 +153,33 @@ void CYEmpty::Output(std::ostream &out, bool block) const { } void CYExpress::Output(std::ostream &out) const { - expression_->Output(out, true); + expression_->Output(out); out << ';'; } void CYExpression::Part(std::ostream &out) const { - Output(out, true); + // XXX: this should notice "in" expressions + // XXX: this should handle LeftHandSideExpression + Output(out); +} + +void CYCompound::Output(std::ostream &out) const { + if (CYExpression *expression = expressions_) + for (;;) { + expression->Output(out); + expression = expression->next_; + if (expression == NULL) + break; + out << ','; + } } -void CYExpression::Output(std::ostream &out, bool raw) const { - if (!raw) +void CYExpression::Output(std::ostream &out, unsigned precedence) const { + bool protect(precedence < Precedence()); + if (protect) out << '('; Output(out); - if (next_ != NULL) { - out << ','; - next_->Output(out, true); - } - if (!raw) + if (protect) out << ')'; } @@ -161,10 +189,10 @@ void CYFor::Output(std::ostream &out) const { initialiser_->Part(out); out << ';'; if (test_ != NULL) - test_->Output(out, true); + test_->Output(out); out << ';'; if (increment_ != NULL) - increment_->Output(out, true); + increment_->Output(out); out << ')'; code_->Output(out, false); } @@ -173,7 +201,7 @@ void CYForIn::Output(std::ostream &out) const { out << "for("; initialiser_->Part(out); out << " in "; - set_->Output(out, true); + set_->Output(out); out << ')'; code_->Output(out, false); } @@ -183,7 +211,9 @@ void CYFunction::Output(std::ostream &out) const { } void CYIf::Output(std::ostream &out) const { - out << "if" << *test_; + out << "if("; + test_->Output(out); + out << ')'; true_->Output(out, true); if (false_ != NULL) { out << "else "; @@ -192,11 +222,14 @@ void CYIf::Output(std::ostream &out) const { } void CYIndirect::Output(std::ostream &out) const { - out << *rhs_ << "[0]"; + rhs_->Output(out, 1); + out << "[0]"; } void CYInfix::Output(std::ostream &out) const { - out << *lhs_ << Operator() << *rhs_; + lhs_->Output(out, Precedence()); + out << Operator(); + rhs_->Output(out, Precedence() - 1); } void CYLambda::Output(std::ostream &out) const { @@ -211,14 +244,15 @@ void CYLambda::Output(std::ostream &out) const { } void CYMember::Output(std::ostream &out) const { - out << *object_ << '['; - property_->Output(out, true); + object_->Output(out, Precedence()); + out << '['; + property_->Output(out); out << ']'; } void CYMessage::Output(std::ostream &out) const { out << "objc_msgSend("; - self_->Output(out, true); + self_->Output(out, CYPA); out << ",\""; for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) if (argument->name_ != NULL) { @@ -227,15 +261,22 @@ void CYMessage::Output(std::ostream &out) const { out << ':'; } out << "\""; - if (arguments_ != NULL) - arguments_->Output(out, true); + for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) + if (argument->value_ != NULL) { + out << ","; + argument->value_->Output(out, CYPA); + } out << ')'; } void CYNew::Output(std::ostream &out) const { - out << "new " << *constructor_ << '('; + out << "new"; + // XXX: I don't /always/ need this character + out << ' '; + constructor_->Output(out, Precedence()); + out << '('; if (arguments_ != NULL) - arguments_->Output(out, false); + arguments_->Output(out); out << ')'; } @@ -264,15 +305,18 @@ void CYParameter::Output(std::ostream &out) const { } void CYPostfix::Output(std::ostream &out) const { - out << *lhs_ << Operator(); + lhs_->Output(out, Precedence()); + out << Operator(); } void CYPrefix::Output(std::ostream &out) const { - out << Operator() << *rhs_; + out << Operator(); + rhs_->Output(out, Precedence()); } void CYProperty::Output(std::ostream &out) const { - out << *name_ << ':' << *value_; + out << *name_ << ':'; + value_->Output(out, CYPA); if (next_ != NULL) { out << ','; next_->Output(out); @@ -281,8 +325,10 @@ void CYProperty::Output(std::ostream &out) const { void CYReturn::Output(std::ostream &out) const { out << "return"; - if (value_ != NULL) - out << ' ' << *value_; + if (value_ != NULL) { + out << ' '; + value_->Output(out); + } out << ';'; } @@ -340,7 +386,9 @@ void CYString::Output(std::ostream &out) const { } void CYSwitch::Output(std::ostream &out) const { - out << "switch" << *value_ << '{'; + out << "switch("; + value_->Output(out); + out << "){"; if (clauses_ != NULL) out << *clauses_; out << '}'; @@ -351,9 +399,11 @@ void CYThis::Output(std::ostream &out) const { } void CYThrow::Output(std::ostream &out) const { - out << "return"; - if (value_ != NULL) - out << ' ' << *value_; + out << "throw"; + if (value_ != NULL) { + out << ' '; + value_->Output(out); + } out << ';'; } @@ -373,12 +423,16 @@ void CYVariable::Output(std::ostream &out) const { } void CYWhile::Output(std::ostream &out) const { - out << "while" << *test_; + out << "while("; + test_->Output(out); + out << ')'; code_->Output(out, false); } void CYWith::Output(std::ostream &out) const { - out << "with" << *scope_; + out << "with("; + scope_->Output(out); + out << ')'; code_->Output(out, false); } diff --git a/Parser.hpp b/Parser.hpp index b848c7b..7de6b02 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -158,19 +158,44 @@ struct CYExpression : CYForInitialiser, CYForInInitialiser { + virtual unsigned Precedence() const = 0; virtual void Part(std::ostream &out) const; virtual void Output(std::ostream &out) const = 0; - void Output(std::ostream &out, bool raw) const; + void Output(std::ostream &out, unsigned precedence) const; }; -_finline std::ostream &operator <<(std::ostream &out, const CYExpression &rhs) { - rhs.Output(out, false); - return out; -} +#define CYPrecedence(value) \ + virtual unsigned Precedence() const { \ + return value; \ + } + +struct CYCompound : + CYExpression +{ + CYExpression *expressions_; + + CYCompound(CYExpression *expressions) : + expressions_(expressions) + { + } + + void AddPrev(CYExpression *expression) { + CYExpression *last(expression); + while (last->next_ != NULL) + last = last->next_; + last->SetNext(expressions_); + expressions_ = expression; + } + + CYPrecedence(17) + + void Output(std::ostream &out) const; +}; struct CYLiteral : CYExpression { + CYPrecedence(0) }; struct CYSelectorPart : @@ -275,6 +300,8 @@ struct CYThis : { } + CYPrecedence(0) + virtual void Output(std::ostream &out) const; }; @@ -323,6 +350,8 @@ struct CYVariable : { } + CYPrecedence(0) + virtual void Output(std::ostream &out) const; }; @@ -374,14 +403,20 @@ struct CYPostfix : }; struct CYAssignment : - CYInfix + CYExpression { + CYExpression *lhs_; + CYExpression *rhs_; + CYAssignment(CYExpression *lhs, CYExpression *rhs) : - CYInfix(lhs, rhs) + lhs_(lhs), + rhs_(rhs) { } virtual const char *Operator() const = 0; + + virtual void Output(std::ostream &out) const; }; struct CYArgument : @@ -397,7 +432,7 @@ struct CYArgument : { } - void Output(std::ostream &out, bool send) const; + void Output(std::ostream &out) const; }; struct CYBlank : @@ -593,6 +628,8 @@ struct CYMessage : { } + CYPrecedence(0) + virtual void Output(std::ostream &out) const; }; @@ -608,6 +645,8 @@ struct CYMember : { } + CYPrecedence(1) + virtual void Output(std::ostream &out) const; }; @@ -623,6 +662,8 @@ struct CYNew : { } + CYPrecedence(1) + virtual void Output(std::ostream &out) const; }; @@ -638,6 +679,8 @@ struct CYCall : { } + CYPrecedence(2) + virtual void Output(std::ostream &out) const; }; @@ -702,6 +745,8 @@ struct CYLambda : { } + CYPrecedence(0) + virtual void Output(std::ostream &out) const; }; @@ -849,6 +894,8 @@ struct CYCondition : { } + CYPrecedence(15) + virtual void Output(std::ostream &out) const; }; @@ -864,6 +911,8 @@ struct CYAddressOf : return "&"; } + CYPrecedence(2) + virtual void Output(std::ostream &out) const; }; @@ -879,6 +928,8 @@ struct CYIndirect : return "*"; } + CYPrecedence(1) + virtual void Output(std::ostream &out) const; }; @@ -890,6 +941,8 @@ struct CYIndirect : CYPostfix(lhs) \ { \ } \ + \ + CYPrecedence(3) \ \ virtual const char *Operator() const { \ return op; \ @@ -904,13 +957,15 @@ struct CYIndirect : CYPrefix(rhs) \ { \ } \ + \ + CYPrecedence(4) \ \ virtual const char *Operator() const { \ return op; \ } \ }; -#define CYInfix_(op, name) \ +#define CYInfix_(precedence, op, name) \ struct CY ## name : \ CYInfix \ { \ @@ -918,6 +973,8 @@ struct CYIndirect : CYInfix(lhs, rhs) \ { \ } \ + \ + CYPrecedence(precedence) \ \ virtual const char *Operator() const { \ return op; \ @@ -932,6 +989,8 @@ struct CYIndirect : CYAssignment(lhs, rhs) \ { \ } \ + \ + CYPrecedence(16) \ \ virtual const char *Operator() const { \ return op; \ @@ -950,29 +1009,29 @@ CYPrefix_("-", Negate) CYPrefix_("~", BitwiseNot) CYPrefix_("!", LogicalNot) -CYInfix_("*", Multiply) -CYInfix_("/", Divide) -CYInfix_("%", Modulus) -CYInfix_("+", Add) -CYInfix_("-", Subtract) -CYInfix_("<<", ShiftLeft) -CYInfix_(">>", ShiftRightSigned) -CYInfix_(">>>", ShiftRightUnsigned) -CYInfix_("<", Less) -CYInfix_(">", Greater) -CYInfix_("<=", LessOrEqual) -CYInfix_(">=", GreaterOrEqual) -CYInfix_("instanceof", InstanceOf) -CYInfix_("in", In) -CYInfix_("==", Equal) -CYInfix_("!=", NotEqual) -CYInfix_("===", Identical) -CYInfix_("!==", NotIdentical) -CYInfix_("&", BitwiseAnd) -CYInfix_("^", BitwiseXOr) -CYInfix_("|", BitwiseOr) -CYInfix_("&&", LogicalAnd) -CYInfix_("||", LogicalOr) +CYInfix_(5, "*", Multiply) +CYInfix_(5, "/", Divide) +CYInfix_(5, "%", Modulus) +CYInfix_(6, "+", Add) +CYInfix_(6, "-", Subtract) +CYInfix_(7, "<<", ShiftLeft) +CYInfix_(7, ">>", ShiftRightSigned) +CYInfix_(7, ">>>", ShiftRightUnsigned) +CYInfix_(8, "<", Less) +CYInfix_(8, ">", Greater) +CYInfix_(8, "<=", LessOrEqual) +CYInfix_(8, ">=", GreaterOrEqual) +CYInfix_(8, "instanceof", InstanceOf) +CYInfix_(8, "in", In) +CYInfix_(9, "==", Equal) +CYInfix_(9, "!=", NotEqual) +CYInfix_(9, "===", Identical) +CYInfix_(9, "!==", NotIdentical) +CYInfix_(10, "&", BitwiseAnd) +CYInfix_(11, "^", BitwiseXOr) +CYInfix_(12, "|", BitwiseOr) +CYInfix_(13, "&&", LogicalAnd) +CYInfix_(14, "||", LogicalOr) CYAssignment_("=", ) CYAssignment_("*=", Multiply) diff --git a/cycript.hpp b/cycript.hpp index c1e6751..7fd159c 100644 --- a/cycript.hpp +++ b/cycript.hpp @@ -1,5 +1,5 @@ -#ifndef CYCRIPT_H -#define CYCRIPT_H +#ifndef CYCRIPT_HPP +#define CYCRIPT_HPP #ifdef __OBJC__ #include @@ -19,4 +19,4 @@ CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value); void CYThrow(JSContextRef context, id error, JSValueRef *exception); #endif -#endif/*CYCRIPT_H*/ +#endif/*CYCRIPT_HPP*/ -- 2.45.2