]> git.saurik.com Git - cycript.git/commitdiff
Parse scope and symbol colon operators, from Ruby.
authorJay Freeman (saurik) <saurik@saurik.com>
Wed, 30 Dec 2015 17:51:01 +0000 (09:51 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Wed, 30 Dec 2015 17:51:01 +0000 (09:51 -0800)
Complete.cpp
Driver.hpp
Output.cpp
Parser.ypp.in
Replace.cpp
Scanner.lpp.in
Syntax.hpp

index 276ccaf5e2111827ef28693137df42074f74cfc5..0cde80c193e6fdbdde64f8f32f7c5c6c487ca42b 100644 (file)
@@ -89,6 +89,10 @@ _visible char **CYComplete(const char *word, const std::string &line, CYUTF8Stri
                 prefix << (*part)->word_ << ':';
         } break;
 
+        case CYDriver::AutoResolve:
+            expression = $M(driver.context_, $S("$cyr"));
+        break;
+
         default:
             _assert(false);
     }
index adb03f20f612c9e864e3a677fbb9d78fed1ac4c2..9625ed852948e882b3969ac170433a92bd308b8d 100644 (file)
@@ -112,7 +112,8 @@ class _visible CYDriver {
         AutoPrimary,
         AutoDirect,
         AutoIndirect,
-        AutoMessage
+        AutoMessage,
+        AutoResolve,
     } mode_;
 
   private:
index a6174087c8ddfbe67130c2e0ef3b8fc548d1bedf..c436b3ca1e184a7b93df08b84b4159347137cf6f 100644 (file)
@@ -326,7 +326,7 @@ void CYCondition::Output(CYOutput &out, CYFlags flags) const {
     test_->Output(out, Precedence() - 1, CYLeft(flags));
     out << ' ' << '?' << ' ';
     if (true_ != NULL)
-        true_->Output(out, CYAssign::Precedence_, CYNoFlags);
+        true_->Output(out, CYAssign::Precedence_, CYNoColon);
     out << ' ' << ':' << ' ';
     false_->Output(out, CYAssign::Precedence_, CYRight(flags));
 }
@@ -340,10 +340,12 @@ void CYContinue::Output(CYOutput &out, CYFlags flags) const {
 
 void CYClause::Output(CYOutput &out) const {
     out << '\t';
-    if (value_ != NULL)
-        out << "case" << ' ' << *value_;
-    else
+    if (value_ == NULL)
         out << "default";
+    else {
+        out << "case" << ' ';
+        value_->Output(out, CYNoColon);
+    }
     out << ':' << '\n';
     ++out.indent_;
     out << code_;
@@ -854,6 +856,14 @@ void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
     out << Value();
 }
 
+void CYResolveMember::Output(CYOutput &out, CYFlags flags) const {
+    object_->Output(out, Precedence(), CYLeft(flags));
+    if (const char *word = property_->Word())
+        out << "::" << word;
+    else
+        out << "::" << '[' << *property_ << ']';
+}
+
 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
     out << "return";
     if (value_ != NULL)
@@ -993,6 +1003,15 @@ void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
     out << '\t' << '}';
 }
 
+void CYSymbol::Output(CYOutput &out, CYFlags flags) const {
+    bool protect((flags & CYNoColon) != 0);
+    if (protect)
+        out << '(';
+    out << ':' << name_;
+    if (protect)
+        out << ')';
+}
+
 void CYThis::Output(CYOutput &out, CYFlags flags) const {
     out << "this";
 }
index ec17e71153350d4d0c8d036e998636dff55920c4..5efee0522f222f397927d0812aa156fb9a10697d 100644 (file)
@@ -253,7 +253,6 @@ type; })
 %token SlashRight "/>"
 %token LeftSlash "</"
 
-%token ColonColon "::"
 %token PeriodPeriod ".."
 @end
 
@@ -305,6 +304,7 @@ type; })
 %token Tilde "~"
 
 %token Colon ":"
+%token ColonColon "::"
 %token Comma ","
 %token Question "?"
 %token SemiColon ";"
@@ -652,6 +652,7 @@ type; })
 %type <statement_> VariableStatement
 %type <statement_> WithStatement
 %type <word_> Word
+%type <word_> WordNoUnary
 @begin ObjectiveC
 %type <word_> WordOpt
 @end
@@ -742,6 +743,9 @@ type; })
 /* Token Priorities {{{ */
 %nonassoc "if"
 %nonassoc "else"
+
+%nonassoc ":"
+%nonassoc "!yield"
 /* }}} */
 
 %start Program
@@ -815,7 +819,7 @@ IdentifierName
     | "instanceof" { $$ = CYNew CYWord("instanceof"); }
     ;
 
-Word
+WordNoUnary
     : IdentifierNoOf[pass] { $$ = $pass; }
     | "break" { $$ = CYNew CYWord("break"); }
     | "case" { $$ = CYNew CYWord("case"); }
@@ -826,7 +830,6 @@ Word
     | "continue" { $$ = CYNew CYWord("continue"); }
     | "debugger" { $$ = CYNew CYWord("debugger"); }
     | "default" { $$ = CYNew CYWord("default"); }
-    | "delete" { $$ = CYNew CYWord("delete"); }
     | "do" { $$ = CYNew CYWord("do"); }
     | "else" { $$ = CYNew CYWord("else"); }
     | "enum" { $$ = CYNew CYWord("enum"); }
@@ -839,7 +842,6 @@ Word
     | "import" { $$ = CYNew CYWord("import"); }
     | "!in" { $$ = CYNew CYWord("in"); }
     | "!of" { $$ = CYNew CYWord("of"); }
-    | "new" { $$ = CYNew CYWord("new"); }
     | "null" { $$ = CYNew CYWord("null"); }
     | "return" { $$ = CYNew CYWord("return"); }
     | "super" { $$ = CYNew CYWord("super"); }
@@ -848,11 +850,16 @@ Word
     | "throw" { $$ = CYNew CYWord("throw"); }
     | "true" { $$ = CYNew CYWord("true"); }
     | "try" { $$ = CYNew CYWord("try"); }
-    | "typeof" { $$ = CYNew CYWord("typeof"); }
     | "var" { $$ = CYNew CYWord("var"); }
-    | "void" { $$ = CYNew CYWord("void"); }
     | "while" { $$ = CYNew CYWord("while"); }
     | "with" { $$ = CYNew CYWord("with"); }
+    ;
+
+Word
+    : WordNoUnary[pass] { $$ = $pass; }
+    | "delete" { $$ = CYNew CYWord("delete"); }
+    | "typeof" { $$ = CYNew CYWord("typeof"); }
+    | "void" { $$ = CYNew CYWord("void"); }
     | "yield" { $$ = CYNew CYIdentifier("yield"); }
     ;
 
@@ -1802,7 +1809,7 @@ GeneratorBody
 
 YieldExpression
     : "!yield" LexNewLineOrNot "\n" LexOf { CYNOT(@$); /* $$ = CYNew CYYieldValue(NULL); */ }
-    | "!yield" LexNewLineOrNot "" LexNoStar LexOf { CYNOT(@$); /* $$ = CYNew CYYieldValue(NULL); */ }
+    | "!yield" LexNewLineOrNot "" LexNoStar LexOf { CYNOT(@$); /* $$ = CYNew CYYieldValue(NULL); */ } %prec "!yield"
     | "!yield" LexNewLineOrNot "" LexNoStar AssignmentExpression[value] { CYNOT(@$); /* $$ = CYNew CYYieldValue($value); */ }
     | "!yield" LexNewLineOrNot "" LexNoStar LexOf "yield *" AssignmentExpression[generator] { CYNOT(@$); /* $$ = CYNew CYYieldGenerator($generator); */ }
     ;
@@ -2645,16 +2652,12 @@ ComprehensionIf
     : "if" "(" AssignmentExpression[test] ")" { $$ = CYNew CYIfComprehension($test); }
     ;
 /* }}} */
-/* JavaScript FTW: Coalesce Operator {{{ */
-ConditionalExpression
-    : LogicalORExpression[test] "?" LexPushInOff LexOf ":" LexPopIn AssignmentExpression[false] { $$ = CYNew CYCondition($test, $test, $false); }
-    ;
-/* }}} */
 /* JavaScript FTW: Named Arguments {{{ */
 ArgumentList
-    : LexOf Word[tag] ":" AssignmentExpression[value] ArgumentList_[next] { $$ = CYNew CYArgument($tag, $value, $next); }
+    : LexOf WordNoUnary[tag] ":" AssignmentExpression[value] ArgumentList_[next] { $$ = CYNew CYArgument($tag, $value, $next); }
     ;
 /* }}} */
+
 /* JavaScript FTW: Ruby Blocks {{{ */
 RubyProcParameterList_
     : "," RubyProcParameterList[parameters] { $$ = $parameters; }
@@ -2694,6 +2697,18 @@ RubyBlockExpression
     | RubyBlockExpression_[pass] { $$ = $pass; }
     ;
 /* }}} */
+/* JavaScript FTW: Ruby Scopes {{{ */
+MemberAccess
+    : "::" "[" Expression[property] "]" { $$ = CYNew CYResolveMember(NULL, $property); }
+    | "::" IdentifierName[property] { $$ = CYNew CYResolveMember(NULL, CYNew CYString($property)); }
+    | "::" AutoComplete { driver.mode_ = CYDriver::AutoResolve; YYACCEPT; }
+    ;
+/* }}} */
+/* JavaScript FTW: Ruby Symbols {{{ */
+PrimaryExpression
+    : ":" Word[name] { $$ = CYNew CYSymbol($name->Word()); }
+    ;
+/* }}} */
 
 %%
 
index 719b3a57eeca3a67f7663d976cadf874d802fec0..ed486f7d96e6794d08b8dff80fa2c7643e90b459 100644 (file)
@@ -878,6 +878,10 @@ void CYScript::Replace(CYContext &context) {
     }
 }
 
+CYTarget *CYResolveMember::Replace(CYContext &context) {
+    return $M($M(object_, $S("$cyr")), property_);
+}
+
 CYStatement *CYReturn::Replace(CYContext &context) {
     if (context.nonlocal_ != NULL) {
         CYProperty *value(value_ == NULL ? NULL : $ CYPropertyValue($S("$cyv"), value_));
@@ -1122,6 +1126,10 @@ CYTarget *CYSuperCall::Replace(CYContext &context) {
     return $C($C1($M($V(context.super_), $S("bind")), $ CYThis()), arguments_);
 }
 
+CYTarget *CYSymbol::Replace(CYContext &context) {
+    return $C1($M($V("Symbol"), $S("for")), $S(name_));
+}
+
 CYStatement *CYSwitch::Replace(CYContext &context) {
     context.Replace(value_);
     clauses_->Replace(context);
index edadb8f9a6f640292a4932223461d0bcb419551a..b0def8d6ecce637441d0ca8030a37f2d9c14d581 100644 (file)
@@ -340,7 +340,6 @@ XMLName {XMLNameStart}{XMLNamePart}*
 ".."   L E("invalid operator")
 
 @begin E4X
-"::"   L F(tk::ColonColon, hi::Operator);
 ".."   L F(tk::PeriodPeriod, hi::Operator);
 @end
 
@@ -392,6 +391,7 @@ XMLName {XMLNameStart}{XMLNamePart}*
 "/=" L F(tk::SlashEqual, hi::Operator);
 
 ":"    L F(tk::Colon, hi::Structure);
+"::"   L F(tk::ColonColon, hi::Structure);
 ","    L F(tk::Comma, hi::Structure);
 "?"    L F(tk::Question, hi::Structure);
 ";"    L F(tk::SemiColon, hi::Structure);
index abf05bcc31933717419330ba8917b1acb8caa912..a3f03fab47eaca021196368cdc7cd29e965986ed 100644 (file)
@@ -150,6 +150,7 @@ enum CYFlags {
     CYNoRightHand =  (1 << 5),
     CYNoDangle =     (1 << 6),
     CYNoInteger =    (1 << 7),
+    CYNoColon =      (1 << 8),
     CYNoBFC =        (CYNoBrace | CYNoFunction | CYNoClass),
 };
 
@@ -962,6 +963,22 @@ struct CYVariable :
     virtual CYFunctionParameter *Parameter() const;
 };
 
+struct CYSymbol :
+    CYTarget
+{
+    const char *name_;
+
+    CYSymbol(const char *name) :
+        name_(name)
+    {
+    }
+
+    CYPrecedence(0)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 struct CYPrefix :
     CYExpression
 {
@@ -1448,6 +1465,20 @@ struct CYIndirectMember :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYResolveMember :
+    CYMember
+{
+    CYResolveMember(CYExpression *object, CYExpression *property) :
+        CYMember(object, property)
+    {
+    }
+
+    CYPrecedence(1)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 namespace cy {
 namespace Syntax {