else {
CYDriver driver("");
cy::parser parser(driver);
+ //parser.set_debug_level(1);
driver.data_ = command.c_str();
driver.size_ = command.size();
int main(int argc, char *argv[]) {
bool tty(isatty(STDIN_FILENO));
pid_t pid(_not(pid_t));
+ bool compile(false);
- for (;;) switch (getopt(argc, argv, "p:")) {
+ for (;;) switch (getopt(argc, argv, "cp:")) {
case -1:
goto getopt;
case '?':
- fprintf(stderr, "usage: cycript [-p <pid>] [<script> [<arg>...]]\n");
+ fprintf(stderr, "usage: cycript [-c] [-p <pid>] [<script> [<arg>...]]\n");
return 1;
+ case 'c':
+ compile = true;
+ break;
+
case 'p': {
size_t size(strlen(optarg));
char *end;
const char *script;
- if (optind < argc - 1 && pid != _not(pid_t)) {
+ if (pid != _not(pid_t) && optind < argc - 1) {
fprintf(stderr, "-p cannot set argv\n");
return 1;
}
+ if (pid != _not(pid_t) && compile) {
+ fprintf(stderr, "-p conflicts with -c\n");
+ return 1;
+ }
+
if (optind == argc)
script = NULL;
else {
std::ostringstream str;
driver.source_->Show(str);
std::string code(str.str());
- Run(socket, code);
+ if (compile)
+ std::cout << code;
+ else
+ Run(socket, code);
}
}
"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;
+"each" L C yylval->word_ = new CYIdentifier("each"); return tk::Each;
+
+[a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier_;
(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? yylval->number_ = new CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral;
CYCatch *catch_;
CYClass *class_;
CYClassName *className_;
+ CYComprehension *comprehension_;
CYCompound *compound_;
CYDeclaration *declaration_;
CYDeclarations *declarations_;
%defines
-%debug
+//%debug
%error-verbose
%parse-param { CYDriver &driver }
%token <word_> Transient "transient"
%token <word_> Volatile "volatile"
-%token <identifier_> Identifier
+%token <identifier_> Each "each"
+
+%token <identifier_> Identifier_
%token <number_> NumericLiteral
%token <string_> StringLiteral
%type <className_> ClassNameOpt
%type <expression_> ClassSuperOpt
%type <field_> ClassFieldList
+%type <comprehension_> ComprehensionList
+%type <comprehension_> ComprehensionListOpt
%type <expression_> ConditionalExpression
%type <expression_> ConditionalExpressionNoBF
%type <expression_> ConditionalExpressionNoIn
%type <expression_> ExpressionNoInOpt
%type <statement_> ExpressionStatement
%type <statement_> FinallyOpt
+%type <comprehension_> ForComprehension
%type <statement_> ForStatement
%type <for_> ForStatementInitialiser
%type <statement_> ForInStatement
%type <source_> FunctionBody
%type <source_> FunctionDeclaration
%type <expression_> FunctionExpression
+%type <identifier_> Identifier
%type <identifier_> IdentifierOpt
+%type <comprehension_> IfComprehension
%type <statement_> IfStatement
%type <expression_> Initialiser
%type <expression_> InitialiserOpt
| "with" { $$ = $1; }
;
+Identifier
+ : Identifier_ { $$ = $1; }
+ | "each" { $$ = $1; }
+ ;
+
IdentifierOpt
: Identifier { $$ = $1; }
| { $$ = NULL; }
ForInStatement
: "for" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForIn($3, $5, $7); }
+ | "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); }
;
ForInStatementInitialiser
;
MessageParameter
- : Word ":" TypeOpt Identifier { $$ = new CYMessageParameter($1, $3, $4); }
+ : Word ":" TypeOpt Identifier { $$ = new(driver.pool_) CYMessageParameter($1, $3, $4); }
;
MessageParameterListOpt
MessageParameters
: MessageParameterList { $$ = $1; }
- | Word { $$ = new CYMessageParameter($1, NULL, NULL); }
+ | Word { $$ = new(driver.pool_) CYMessageParameter($1, NULL, NULL); }
;
ClassMessageDeclaration
- : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new CYMessage($1, $2, $3, $5); }
+ : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new(driver.pool_) CYMessage($1, $2, $3, $5); }
;
ClassMessageDeclarationListOpt
;
ClassDefinition
- : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new CYClass($2, $3, $4, $5); }
+ : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClass($2, $3, $4, $5); }
;
CategoryStatement
- : "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new CYCategory($2, $3); }
+ : "@class" ClassName ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYCategory($2, $3); }
;
PrimaryExpression
PrimaryExpression_
: MessageExpression { $$ = $1; }
- | "@selector" "(" SelectorExpression ")" { $$ = new CYSelector($3); }
+ | "@selector" "(" SelectorExpression ")" { $$ = new(driver.pool_) CYSelector($3); }
;
/* }}} */
: "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); }
;
-/*
-
IfComprehension
- : "if" "(" Expression ")"
+ : "if" "(" Expression ")" { $$ = new(driver.pool_) CYIfComprehension($3); }
;
ForComprehension
- : "for" "(" ForInStatementInitialiser "in" Expression ")"
+ : "for" "(" Identifier "in" Expression ")" { $$ = new(driver.pool_) CYForInComprehension($3, $5); }
+ | "for" "each" "(" Identifier "in" Expression ")" { $$ = new(driver.pool_) CYForEachInComprehension($4, $6); }
;
ComprehensionListOpt
- : ComprehensionList
- | IfComprehension
- |
+ : ComprehensionList { $$ = $1; }
+ | IfComprehension { $$ = $1; }
+ | { $$ = NULL; }
;
ComprehensionList
- : ForComprehension ComprehensionListOpt
+ : ForComprehension ComprehensionListOpt { $1->SetNext($2); $$ = $1; }
;
PrimaryExpression_
- : "[" AssignmentExpression ComprehensionList "]"
+ : "[" AssignmentExpression ComprehensionList "]" { $$ = new(driver.pool_) CYArrayComprehension($2, $3); }
;
-*/
-
%%
if ((self = [super init]) != nil) {
object_ = object;
context_ = context;
+ JSValueProtect(context_, object_);
} return self;
}
+- (void) dealloc {
+ JSValueUnprotect(context_, object_);
+ [super dealloc];
+}
+
- (NSObject *) cy$toJSON:(NSString *)key {
JSValueRef toJSON(CYGetProperty(context_, object_, toJSON_));
if (!CYIsCallable(context_, toJSON))
if ((self = [super init]) != nil) {
object_ = object;
context_ = context;
+ JSValueProtect(context_, object_);
} return self;
}
+- (void) dealloc {
+ JSValueUnprotect(context_, object_);
+ [super dealloc];
+}
+
- (NSUInteger) count {
return CYCastDouble(context_, CYGetProperty(context_, object_, length_));
}
out << ']';
}
+void CYArrayComprehension::Output(std::ostream &out, CYFlags flags) const {
+ // XXX: I don't necc. need the ()s
+ out << "(function($cyv";
+ for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
+ if (const char *name = comprehension->Name())
+ out << ',' << name;
+ out << "){";
+ out << "$cyt=[];";
+ comprehensions_->Output(out);
+ out << "$cyt.push(";
+ expression_->Output(out, CYPA, CYNoFlags);
+ out << ");";
+ for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
+ comprehension->End_(out);
+ out << "return $cyt;";
+ out << "}())";
+}
+
void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
lhs_->Output(out, Precedence() - 1, CYLeft(flags));
out << Operator();
expression->Output(out, flags);
}
+void CYComprehension::Output(std::ostream &out) const {
+ Begin_(out);
+ if (next_ != NULL)
+ next_->Output(out);
+}
+
void CYCondition::Output(std::ostream &out, CYFlags flags) const {
test_->Output(out, Precedence() - 1, CYLeft(flags));
out << '?';
out << *next_;
}
-// XXX: deal with NoIn
-void CYDeclaration::Part(std::ostream &out) const {
+void CYDeclaration::Part(std::ostream &out, CYFlags flags) const {
+ if ((flags & CYNoLeader) != 0)
+ out << ' ';
out << "var ";
- Output(out);
+ Output(out, CYRight(flags));
+}
+
+void CYDeclaration::ForEachIn(std::ostream &out) const {
+ out << *identifier_;
}
-void CYDeclaration::Output(std::ostream &out) const {
+void CYDeclaration::Output(std::ostream &out, CYFlags flags) const {
out << *identifier_;
if (initialiser_ != NULL) {
out << '=';
- initialiser_->Output(out, CYPA, CYNoFlags);
- }
+ initialiser_->Output(out, CYPA, CYRight(flags));
+ } else if ((flags & CYNoTrailer) != 0)
+ out << ' ';
}
-// XXX: deal with NoIn
-void CYDeclarations::Part(std::ostream &out) const {
+void CYDeclarations::Part(std::ostream &out, CYFlags flags) const {
+ if ((flags & CYNoLeader) != 0)
+ out << ' ';
out << "var ";
const CYDeclarations *declaration(this);
output:
- out << *declaration->declaration_;
- declaration = declaration->next_;
+ CYDeclarations *next(declaration->next_);
+ CYFlags right(next == NULL ? CYRight(flags) : CYCenter(flags));
+ declaration->declaration_->Output(out, right);
- if (declaration != NULL) {
+ if (next != NULL) {
out << ',';
+ declaration = next;
goto output;
}
}
void CYDeclarations::Output(std::ostream &out) const {
- Part(out);
+ Part(out, CYNoFlags);
out << ';';
}
Output(out, CYPA, CYNoFlags);
}
-void CYExpression::Part(std::ostream &out) const {
+void CYExpression::ForEachIn(std::ostream &out) const {
// XXX: this should handle LeftHandSideExpression
- Output(out, CYNoIn);
+ Output(out, CYPA, CYNoFlags);
+}
+
+void CYExpression::Part(std::ostream &out, CYFlags flags) const {
+ // XXX: this should handle LeftHandSideExpression
+ Output(out, flags);
}
void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
void CYFor::Output(std::ostream &out) const {
out << "for(";
if (initialiser_ != NULL)
- initialiser_->Part(out);
+ initialiser_->Part(out, CYNoFlags);
out << ';';
if (test_ != NULL)
test_->Output(out, CYNoFlags);
code_->Output(out, false);
}
+void CYForEachIn::Output(std::ostream &out) const {
+ const char *name(initialiser_->ForEachIn());
+
+ if (name != NULL) {
+ out << '{';
+ out << "var " << name << ';';
+ }
+
+ out << "(function($cys,$cyt){";
+ out << "$cys=";
+ set_->Output(out, CYPA, CYNoFlags);
+ out << ";";
+
+ out << "for($cyt in $cys){";
+
+ initialiser_->ForEachIn(out);
+ out << "=$cys[$cyt];";
+
+ code_->Show(out);
+
+ out << "}}());";
+
+ if (name != NULL)
+ out << '}';
+}
+
+void CYForEachInComprehension::Begin_(std::ostream &out) const {
+ out << "(function($cys){";
+ out << "$cys=";
+ set_->Output(out, CYPA, CYNoFlags);
+ out << ";";
+
+ out << "for(" << *name_ << " in $cys){";
+ out << *name_ << "=$cys[" << *name_ << "];";
+}
+
+void CYForEachInComprehension::End_(std::ostream &out) const {
+ out << "}}());";
+}
+
void CYForIn::Output(std::ostream &out) const {
out << "for(";
- initialiser_->Part(out);
- // XXX: deal with this space character!
- out << ' ';
+ initialiser_->Part(out, CYNoIn | CYNoTrailer);
out << "in";
set_->Output(out, CYNoLeader);
out << ')';
code_->Output(out, false);
}
+void CYForInComprehension::Begin_(std::ostream &out) const {
+ out << "for(" << *name_ << " in";
+ set_->Output(out, CYNoLeader);
+ out << ')';
+}
+
void CYFunction::Output(std::ostream &out) const {
CYLambda::Output(out, CYNoFlags);
}
}
}
+void CYIfComprehension::Begin_(std::ostream &out) const {
+ out << "if(";
+ test_->Output(out, CYNoFlags);
+ out << ')';
+}
+
void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
rhs_->Output(out, 1, CYLeft(flags));
out << ".$cyi";
~CYDriver();
};
+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 CYPart {
- virtual void Part(std::ostream &out) const = 0;
+ virtual void Part(std::ostream &out, CYFlags flags) const = 0;
};
struct CYForInitialiser :
struct CYForInInitialiser :
CYPart
{
-};
-
-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),
+ virtual const char *ForEachIn() const = 0;
+ virtual void ForEachIn(std::ostream &out) const = 0;
};
struct CYExpression :
CYClassName
{
virtual unsigned Precedence() const = 0;
- virtual void Part(std::ostream &out) const;
+ virtual void Part(std::ostream &out, CYFlags flags) const;
+
+ virtual const char *ForEachIn() const {
+ return NULL;
+ }
+
+ virtual void ForEachIn(std::ostream &out) const;
+
virtual void Output(std::ostream &out, CYFlags flags) const = 0;
void Output(std::ostream &out, unsigned precedence, CYFlags flags) const;
void Output(std::ostream &out, CYFlags flags) const;
};
+struct CYComprehension :
+ CYNext<CYComprehension>
+{
+ void Output(std::ostream &out) const;
+ virtual const char *Name() const = 0;
+
+ virtual void Begin_(std::ostream &out) const = 0;
+
+ virtual void End_(std::ostream &out) const {
+ }
+};
+
+struct CYForInComprehension :
+ CYComprehension
+{
+ CYIdentifier *name_;
+ CYExpression *set_;
+
+ CYForInComprehension(CYIdentifier *name, CYExpression *set) :
+ name_(name),
+ set_(set)
+ {
+ }
+
+ virtual const char *Name() const {
+ return name_->Value();
+ }
+
+ virtual void Begin_(std::ostream &out) const;
+};
+
+struct CYForEachInComprehension :
+ CYComprehension
+{
+ CYIdentifier *name_;
+ CYExpression *set_;
+
+ CYForEachInComprehension(CYIdentifier *name, CYExpression *set) :
+ name_(name),
+ set_(set)
+ {
+ }
+
+ virtual const char *Name() const {
+ return name_->Value();
+ }
+
+ virtual void Begin_(std::ostream &out) const;
+ virtual void End_(std::ostream &out) const;
+};
+
+struct CYIfComprehension :
+ CYComprehension
+{
+ CYExpression *test_;
+
+ CYIfComprehension(CYExpression *test) :
+ test_(test)
+ {
+ }
+
+ virtual const char *Name() const {
+ return NULL;
+ }
+
+ virtual void Begin_(std::ostream &out) const;
+};
+
+struct CYArrayComprehension :
+ CYExpression
+{
+ CYExpression *expression_;
+ CYComprehension *comprehensions_;
+
+ CYArrayComprehension(CYExpression *expression, CYComprehension *comprehensions) :
+ expression_(expression),
+ comprehensions_(comprehensions)
+ {
+ }
+
+ CYPrecedence(0)
+
+ virtual void Output(std::ostream &out, CYFlags flags) const;
+};
+
struct CYLiteral :
CYExpression
{
};
struct CYDeclaration :
- CYThing,
CYForInInitialiser
{
CYIdentifier *identifier_;
{
}
- virtual void Part(std::ostream &out) const;
- virtual void Output(std::ostream &out) const;
+ virtual void Part(std::ostream &out, CYFlags flags) const;
+
+ virtual const char *ForEachIn() const {
+ return identifier_->Value();
+ }
+
+ virtual void ForEachIn(std::ostream &out) const;
+
+ virtual void Output(std::ostream &out, CYFlags flags) const;
};
struct CYDeclarations :
{
}
- virtual void Part(std::ostream &out) const;
+ virtual void Part(std::ostream &out, CYFlags flags) const;
virtual void Output(std::ostream &out) const;
};
virtual void Output(std::ostream &out) const;
};
+struct CYForEachIn :
+ CYStatement
+{
+ CYForInInitialiser *initialiser_;
+ CYExpression *set_;
+ CYStatement *code_;
+
+ CYForEachIn(CYForInInitialiser *initialiser, CYExpression *set, CYStatement *code) :
+ initialiser_(initialiser),
+ set_(set),
+ code_(code)
+ {
+ }
+
+ virtual void Output(std::ostream &out) const;
+};
+
struct CYProperty :
CYNext<CYProperty>
{
all: $(all)
clean:
- rm -f *.o libcycript.dylib cycript libcycript.plist Struct.hpp lex.cy.c Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh
+ rm -f *.o libcycript.dylib cycript libcycript.plist Struct.hpp lex.cy.c Cycript.tab.cc Cycript.tab.hh location.hh position.hh stack.hh cyrver
libcycript.plist: Bridge.def
{ \