int CYConsole(FILE *in, FILE *out, FILE *err);
 
+@ /**/protocol a
+- (void) a:(int)m;
+@end
+
 int main() {
     return CYConsole(stdin, stdout, stderr);
 }
 
 #define C T yyextra->state_ = CYClear;
 #define R T yyextra->state_ = CYRestricted;
 #define N if (yyextra->state_ != CYNewLine) { bool restricted(yyextra->state_ == CYRestricted); if (restricted) { yyextra->state_ = CYClear; return tk::NewLine; } else yyextra->state_ = CYNewLine; }
+
+#define YY_INPUT(data, value, size) { \
+    if (yyextra->size_ == 0) \
+        value = YY_NULL; \
+    else { \
+        size_t copy(std::min(size, yyextra->size_)); \
+        memcpy(data, yyextra->data_, copy); \
+        yyextra->data_ += copy; \
+        yyextra->size_ -= copy; \
+        value = copy; \
+    } \
+}
+
 %}
 
 %option prefix="cy"
 "["    C return tk::OpenBracket;
 "]"    C return tk::CloseBracket;
 
+"@selector"  C return tk::AtSelector;
+
 "break"      R yylval->word_ = new CYWord("break"); return tk::Break;
 "case"       C yylval->word_ = new CYWord("case"); return tk::Case;
 "catch"      C yylval->word_ = new CYWord("catch"); return tk::Catch;
 
         CYNumber *number_;
         CYParameter *parameter_;
         CYProperty *property_;
+        CYSelector *selector_;
         CYSource *source_;
         CYStatement *statement_;
         CYString *string_;
 %token OpenBracket "["
 %token CloseBracket "]"
 
+%token AtSelector "@selector"
+
 %token <word_> Break "break"
 %token <word_> Case "case"
 %token <word_> Catch "catch"
 %type <expression_> RelationalExpressionNoBF
 %type <expression_> RelationalExpressionNoIn
 %type <statement_> ReturnStatement
+%type <selector_> SelectorExpression
+%type <selector_> SelectorExpression_
+%type <selector_> SelectorExpressionOpt
 %type <expression_> ShiftExpression
 %type <expression_> ShiftExpressionNoBF
 %type <source_> SourceElement
     : "[" AssignmentExpression SelectorList "]" { $$ = new(driver.pool_) CYMessage($2, $3); }
     ;
 
+SelectorExpressionOpt
+    : SelectorExpression_ { $$ = $1; }
+    | { $$ = NULL; }
+    ;
+
+SelectorExpression_
+    : WordOpt ":" SelectorExpressionOpt { $$ = new CYSelector($1, true, $3); }
+    ;
+
+SelectorExpression
+    : SelectorExpression_ { $$ = $1; }
+    | Word { $$ = new CYSelector($1, false, NULL); }
+    ;
+
 PrimaryExpression_
     : MessageExpression { $$ = $1; }
+    | "@selector" "(" SelectorExpression ")" { $$ = $3; }
     ;
 /* }}} */
 
 
 
 CYDriver::CYDriver(const std::string &filename) :
     state_(CYClear),
+    data_(NULL),
+    size_(0),
     filename_(filename),
     source_(NULL)
 {
 }
 
 void CYDriver::Clear() {
+    pool_.Clear();
     state_ = CYClear;
+    data_ = NULL;
+    size_ = 0;
     source_.clear();
-    pool_.Clear();
 }
 
 void cy::parser::error(const cy::parser::location_type &loc, const std::string &msg) {
 }
 
 void CYConsole(FILE *fin, FILE *fout, FILE *ferr) {
+    std::string line;
+
+    __gnu_cxx::stdio_filebuf<char> bin(fin, std::ios::in);
+    std::istream sin(&bin);
+
     CYDriver driver("");
 
     while (!feof(fin)) { _pooled
         driver.Clear();
 
+        fputs("cy# ", fout);
+        fflush(fout);
+
         cy::parser parser(driver);
-        if (parser.parse() != 0)
-            continue;
+        std::string command;
+
+        for (;;) {
+            if (!std::getline(sin, line))
+                return;
+            command += line;
+            driver.data_ = command.c_str();
+            driver.size_ = command.size();
+            if (parser.parse() == 0)
+                break;
+            fputs("cy> ", fout);
+            fflush(fout);
+        }
 
         for (std::vector<CYSource *>::const_iterator i(driver.source_.begin()); i != driver.source_.end(); ++i) {
             CYSource *source(*i);
 
     out << ';';
 }
 
+void CYSelector::Output(std::ostream &out) const {
+    out << '"';
+    out << "<unimplemented>";
+    out << '"';
+}
+
 void CYSource::Show(std::ostream &out) const {
     for (const CYSource *next(this); next != NULL; next = next->next_)
         next->Output(out);
 
 class CYDriver {
   public:
     CYPool pool_;
+
     CYState state_;
+    void *scanner_;
+
+    const char *data_;
+    size_t size_;
+
     std::string filename_;
+
     std::vector<CYSource *> source_;
-    void *scanner_;
 
   private:
     void ScannerInit();
 {
 };
 
+struct CYSelector :
+    CYLiteral
+{
+    CYWord *name_;
+    bool value_;
+    CYSelector *after_;
+
+    CYSelector(CYWord *name, bool value, CYSelector *after) :
+        name_(name),
+        value_(value),
+        after_(after)
+    {
+    }
+
+    virtual void Output(std::ostream &out) const;
+};
+
 struct CYString :
     CYLiteral,
     CYName
 
 
 package:
 
-flags := -mthumb -g0 -O3 -Wall -Werror -I.
+flags := -mthumb -g3 -O0 -Wall -Werror -I.
 
 all: cycript libcycript.dylib libcycript.plist
 
        done >$@
 
 Cycript.tab.cc Cycript.tab.hh location.hh position.hh: Cycript.y
-       bison --report=state $<
+       bison -v --report=state $<
 
 lex.cy.c: Cycript.l
        flex $<