"(" L C return tk::OpenParen;
")" L C return tk::CloseParen;
-"{" L C return tk::OpenBrace;
+"{" L C return yylval->newline_ ? tk::OpenBrace_ : tk::OpenBrace;
"}" L C return tk::CloseBrace;
"[" L C return tk::OpenBracket;
CYProgram *program_;
CYProperty *property_;
CYPropertyName *propertyName_;
+ CYRubyProc *rubyProc_;
CYStatement *statement_;
CYString *string_;
CYThis *this_;
%token CloseParen ")"
%token OpenBrace "{"
+%token OpenBrace_ "\n{"
%token CloseBrace "}"
%token OpenBracket "["
%type <expression_> RelationalExpressionNoIn
%type <infix_> RelationalExpressionNoIn_
%type <statement_> ReturnStatement
+%type <rubyProc_> RubyProcExpression
+%type <functionParameter_> RubyProcParameterList
+%type <functionParameter_> RubyProcParameterList_
+%type <functionParameter_> RubyProcParametersOpt
%type <expression_> ShiftExpression
%type <expression_> ShiftExpressionNoBF
%type <statement_> SourceElement
;
/* }}} */
+Brace
+ : "{"
+ | "\n{"
+ ;
+
StrictSemi
: { driver.Warning(yylloc, "warning, automatic semi-colon insertion required"); }
;
/* }}} */
/* 11.1.5 Object Initialiser {{{ */
ObjectLiteral
- : "{" PropertyNameAndValueListOpt "}" { $$ = new(driver.pool_) CYObject($2); }
+ : OpenBrace PropertyNameAndValueListOpt "}" { $$ = new(driver.pool_) CYObject($2); }
;
PropertyNameAndValueList_
/* }}} */
/* 12.1 Block {{{ */
Block_
- : "{" StatementListOpt "}" { $$ = $2; }
+ : Brace StatementListOpt "}" { $$ = $2; }
;
Block
;
CaseBlock
- : "{" CaseClausesOpt "}" { $$ = $2; }
+ : Brace CaseClausesOpt "}" { $$ = $2; }
;
CaseClausesOpt
/* 13 Function Definition {{{ */
FunctionDeclaration
- : "function" Identifier "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYFunctionStatement($2, $4, $7); }
+ : "function" Identifier "(" FormalParameterList ")" Brace FunctionBody "}" { $$ = new(driver.pool_) CYFunctionStatement($2, $4, $7); }
;
FunctionExpression
- : "function" IdentifierOpt "(" FormalParameterList ")" "{" FunctionBody "}" { $$ = new(driver.pool_) CYFunctionExpression($2, $4, $7); }
+ : "function" IdentifierOpt "(" FormalParameterList ")" Brace FunctionBody "}" { $$ = new(driver.pool_) CYFunctionExpression($2, $4, $7); }
;
FormalParameterList_
;
ClassFieldList
- : "{" "}" { $$ = NULL; }
+ : Brace "}" { $$ = NULL; }
;
MessageScope
;
ClassMessageDeclaration
- : MessageScope TypeOpt MessageParameters "{" FunctionBody "}" { $$ = new(driver.pool_) CYMessage($1, $2, $3, $5); }
+ : MessageScope TypeOpt MessageParameters Brace FunctionBody "}" { $$ = new(driver.pool_) CYMessage($1, $2, $3, $5); }
;
ClassMessageDeclarationListOpt
;
XMLExpression
- : "{" LexPushRegExp Expression "}" LexPop
+ : Brace LexPushRegExp Expression "}" LexPop
;
XMLTagName
: Identifier "=" AssignmentExpression FormalParameterList_ { $$ = new(driver.pool_) CYOptionalFunctionParameter($1, $3, $4); }
;
/* }}} */
+/* JavaScript FTW: Ruby Blocks {{{ */
+RubyProcParameterList_
+ : "," RubyProcParameterList { $$ = $2; }
+ | { $$ = NULL; }
+ ;
+
+RubyProcParameterList
+ : Identifier RubyProcParameterList_ { $$ = new(driver.pool_) CYFunctionParameter($1, $2); }
+ | { $$ = NULL; }
+ ;
+
+RubyProcParametersOpt
+ : "|" RubyProcParameterList "|" { $$ = $2; }
+ | { $$ = NULL; }
+ ;
+
+RubyProcExpression
+ : "{" RubyProcParametersOpt StatementListOpt "}" { $$ = new(driver.pool_) CYRubyProc($2, $3); }
+ ;
+
+LeftHandSideExpression
+ : LeftHandSideExpression RubyProcExpression { $$ = new(driver.pool_) CYRubyBlock($1, $2); }
+ ;
+
+LeftHandSideExpressionNoBF
+ : LeftHandSideExpressionNoBF RubyProcExpression { $$ = new(driver.pool_) CYRubyBlock($1, $2); }
+ ;
+
+@begin C
+LeftHandSideExpressionNoRE
+ : LeftHandSideExpressionNoRE RubyProcExpression { $$ = new(driver.pool_) CYRubyBlock($1, $2); }
+ ;
+@end
+/* }}} */
%%
}
void CYOptionalFunctionParameter::Output(CYOutput &out) const {
- out << *name_ << ' ' << '=' << ' ';
+ out << *name_ << '=';
initializer_->Output(out, CYPA, CYNoFlags);
if (next_ != NULL)
out << ',' << ' ' << *next_;
out << ';';
}
+void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
+ call_->Output(out, CYLeft(flags));
+ out << ' ';
+ proc_->Output(out, CYRight(flags));
+}
+
+void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
+ // XXX: this is not outputting the parameters
+ out << code_;
+}
+
void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
bool first(true);
for (const CYStatement *next(this); next != NULL; next = next->next_) {
virtual const char *ForEachIn() const;
virtual CYExpression *ForEachIn(CYContext &out);
+ virtual CYExpression *AddArgument(CYContext &context, CYExpression *value);
+
virtual void Output(CYOutput &out) const;
virtual void Output(CYOutput &out, CYFlags flags) const = 0;
void Output(CYOutput &out, unsigned precedence, CYFlags flags) const;
virtual CYExpression *Replace(CYContext &context);
virtual void Output(CYOutput &out, CYFlags flags) const;
+
+ virtual CYExpression *AddArgument(CYContext &context, CYExpression *value);
};
struct CYCall :
virtual CYExpression *Replace(CYContext &context);
virtual void Output(CYOutput &out, CYFlags flags) const;
+
+ virtual CYExpression *AddArgument(CYContext &context, CYExpression *value);
+};
+
+struct CYRubyProc;
+
+struct CYRubyBlock :
+ CYExpression
+{
+ CYExpression *call_;
+ CYRubyProc *proc_;
+
+ CYRubyBlock(CYExpression *call, CYRubyProc *proc) :
+ call_(call),
+ proc_(proc)
+ {
+ }
+
+ CYPrecedence(1)
+ CYRightHand(false)
+
+ virtual CYExpression *Replace(CYContext &context);
+ virtual void Output(CYOutput &out, CYFlags flags) const;
};
struct CYIf :
virtual void Output(CYOutput &out, CYFlags flags) const;
};
+// XXX: this should be split up into CYAnonymousFunction and CYNamedFunction (subclass)
struct CYFunction {
CYIdentifier *name_;
CYFunctionParameter *parameters_;
virtual void Output(CYOutput &out, CYFlags flags) const;
};
+// XXX: this should be split up into CYAnonymousFunctionExpression and CYNamedFunctionExpression
struct CYFunctionExpression :
CYFunction,
CYExpression
virtual void Output(CYOutput &out, CYFlags flags) const;
};
+// XXX: this should derive from CYAnonymousFunctionExpression
+struct CYRubyProc :
+ CYFunctionExpression
+{
+ CYRubyProc(CYFunctionParameter *parameters, CYStatement *statements) :
+ CYFunctionExpression(NULL, parameters, statements)
+ {
+ }
+
+ virtual CYExpression *Replace(CYContext &context);
+ virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+// XXX: this should derive from CYNamedFunction
struct CYFunctionStatement :
CYFunction,
CYStatement
return this;
}
+CYExpression *CYCall::AddArgument(CYContext &context, CYExpression *value) {
+ CYArgument **argument(&arguments_);
+ while (*argument != NULL)
+ argument = &(*argument)->next_;
+ *argument = $ CYArgument(value);
+ return this;
+}
+
CYExpression *CYCall::Replace(CYContext &context) {
context.Replace(function_);
arguments_->Replace(context);
return this;
}
+CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value) {
+ return $C1(this, value);
+}
+
CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
return this;
}
if (!outer && name_ != NULL)
Inject(context);
- parameters_ = parameters_->Replace(context, code_);
+ if (parameters_ != NULL)
+ parameters_ = parameters_->Replace(context, code_);
code_.Replace(context);
context.scope_ = scope.parent_;
context.Replace(property_);
}
+CYExpression *CYNew::AddArgument(CYContext &context, CYExpression *value) {
+ CYArgument **argument(&arguments_);
+ while (*argument != NULL)
+ argument = &(*argument)->next_;
+ *argument = $ CYArgument(value);
+ return this;
+}
+
CYExpression *CYNew::Replace(CYContext &context) {
context.Replace(constructor_);
arguments_->Replace(context);
return this;
}
+CYExpression *CYRubyBlock::Replace(CYContext &context) {
+ // XXX: this needs to do something much more epic to handle return
+ return call_->AddArgument(context, proc_->Replace(context));
+}
+
+CYExpression *CYRubyProc::Replace(CYContext &context) {
+ return $ CYFunctionExpression(NULL, parameters_, code_);
+}
+
void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags));
}