rhs_->Output(out, Precedence(), CYRight(flags));
 }
 
+void CYAttemptMember::Output(CYOutput &out, CYFlags flags) const {
+    object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
+    if (const char *word = property_->Word())
+        out << "?." << word;
+    else
+        _assert(false);
+}
+
 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
     out << '{' << '\n';
     ++out.indent_;
 
 %token Plus "+"
 %token PlusEqual "+="
 %token PlusPlus "++"
+%token QuestionPeriod "?."
 %token Right ">"
 %token RightEqual ">="
 %token RightRight ">>"
     : "." "[" AssignmentExpression[property] "]" { $$ = CYNew CYSubscriptMember(NULL, $property); }
     ;
 /* }}} */
+/* JavaScript FTW: Undefined Monad {{{ */
+MemberAccess
+    : "?." IdentifierName[property] { $$ = CYNew CYAttemptMember(NULL, CYNew CYString($property)); }
+    | "?." AutoComplete { driver.mode_ = CYDriver::AutoDirect; YYACCEPT; }
+    ;
+/* }}} */
 
 /* JavaScript FTW: Java "Anonymous Inner Classes" {{{ */
 BracedParameter
 
     return this;
 }
 
+CYTarget *CYAttemptMember::Replace(CYContext &context) {
+    CYIdentifier *value(context.Unique());
+
+    return $C1($F(NULL, $P1($B(value)), $$
+        ->* $ CYReturn($ CYCondition($V(value), $M($V(value), property_), $V(value)))
+    ), object_);
+}
+
 CYStatement *CYBlock::Return() {
     CYImplicitReturn(code_);
     return this;
 }
 
 CYTarget *CYCall::Replace(CYContext &context) {
+    // XXX: this also is a horrible hack but I'm still a month over schedule :(
+    if (CYAttemptMember *member = dynamic_cast<CYAttemptMember *>(function_)) {
+        CYIdentifier *value(context.Unique());
+
+        return $C1($F(NULL, $P1($B(value)), $$
+            ->* $ CYReturn($ CYCondition($V(value), $C($M($V(value), member->property_), arguments_), $V(value)))
+        ), member->object_);
+    }
+
     context.Replace(function_);
     arguments_->Replace(context);
     return this;
 
 "%"    L F(tk::Percent, hi::Operator);
 "%="   L F(tk::PercentEqual, hi::Operator);
 "."    L F(tk::Period, hi::Operator);
+"?."   L F(tk::QuestionPeriod, hi::Operator);
 "|"    L F(tk::Pipe, hi::Operator);
 "|="   L F(tk::PipeEqual, hi::Operator);
 "||"   L F(tk::PipePipe, hi::Operator);
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYAttemptMember :
+    CYMember
+{
+    CYAttemptMember(CYExpression *object, CYExpression *property) :
+        CYMember(object, property)
+    {
+    }
+
+    CYPrecedence(1)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 struct CYIndirectMember :
     CYMember
 {