From cac61857bcc00ddc1e354756e11b24e93b8edbf3 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Mon, 19 Oct 2009 18:58:08 +0000 Subject: [PATCH] Added CYNoLeader after 'case', implemented a pass-through LetStatement binding (temporary), turned on GLR parser in Bison, moved YYLTYPE #define to handle GLR, reorganized a few grammar statements to make clear what is or is not specification, and fixed the "for each (i in" and "switch" crashes reported by kennytm. --- Console.cpp | 28 +++++++++++++++++++++-- Cycript.l | 3 ++- Cycript.y | 61 +++++++++++++++++++++++++++++++++++++------------ Output.cpp | 52 ++++++++++++++++++++++++++++++------------ Parser.hpp | 65 +++++++++++++++++++++++++++++++++-------------------- 5 files changed, 154 insertions(+), 55 deletions(-) diff --git a/Console.cpp b/Console.cpp index b3702ca..f83c3a2 100644 --- a/Console.cpp +++ b/Console.cpp @@ -91,6 +91,17 @@ static void sigint(int) { } } +#if YYDEBUG +static bool bison_; +#endif + +void Setup(cy::parser &parser) { +#if YYDEBUG + if (bison_) + parser.set_debug_level(1); +#endif +} + void Run(int socket, const char *data, size_t size, FILE *fout = NULL, bool expand = false) { CYPool pool; @@ -218,7 +229,7 @@ static void Console(int socket) { else { CYDriver driver(""); cy::parser parser(driver); - //parser.set_debug_level(1); + Setup(parser); driver.data_ = command.c_str(); driver.size_ = command.size(); @@ -304,7 +315,7 @@ int main(int argc, char *argv[]) { pid_t pid(_not(pid_t)); bool compile(false); - for (;;) switch (getopt(argc, argv, "cp:")) { + for (;;) switch (getopt(argc, argv, "cg:p:")) { case -1: goto getopt; case '?': @@ -315,6 +326,18 @@ int main(int argc, char *argv[]) { compile = true; break; + case 'g': + if (false); +#if YYDEBUG + else if (strcmp(optarg, "bison") == 0) + bison_ = true; +#endif + else { + fprintf(stderr, "invalid name for -g\n"); + return 1; + } + break; + case 'p': { size_t size(strlen(optarg)); char *end; @@ -373,6 +396,7 @@ int main(int argc, char *argv[]) { else { CYDriver driver(script ?: ""); cy::parser parser(driver); + Setup(parser); char *start, *end; diff --git a/Cycript.l b/Cycript.l index dd6e204..063e900 100644 --- a/Cycript.l +++ b/Cycript.l @@ -1,9 +1,9 @@ %{ +#define YYLTYPE cy::location #include "Cycript.tab.hh" typedef cy::parser::token tk; #define YY_EXTRA_TYPE CYDriver * -#define YYLTYPE cy::location #define T yylval->newline_ = yyextra->state_ == CYNewLine; #define C T yyextra->state_ = CYClear; @@ -188,6 +188,7 @@ Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n "volatile" L C yylval->word_ = new CYWord("volatile"); return tk::Volatile; "each" L C yylval->word_ = new CYIdentifier("each"); return tk::Each; +"let" L C yylval->word_ = new CYIdentifier("let"); return tk::Let; [a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier_; diff --git a/Cycript.y b/Cycript.y index 6a35534..6a304b3 100644 --- a/Cycript.y +++ b/Cycript.y @@ -107,7 +107,11 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %defines -//%debug +%glr-parser +%expect 1 + +%debug + %error-verbose %parse-param { CYDriver &driver } @@ -236,6 +240,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %token Volatile "volatile" %token Each "each" +%token Let "let" %token Identifier_ %token NumericLiteral @@ -259,6 +264,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type BitwiseANDExpressionNoBF %type BitwiseANDExpressionNoIn %type Block +%type Block_ %type BooleanLiteral %type BitwiseORExpression %type BitwiseORExpressionNoBF @@ -329,6 +335,7 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %type LabelledStatement %type LeftHandSideExpression %type LeftHandSideExpressionNoBF +%type LetStatement %type Literal %type LogicalANDExpression %type LogicalANDExpressionNoBF @@ -435,10 +442,10 @@ Terminator | error { if (yychar != 0 && yychar != cy::parser::token::CloseBrace && !yylval.newline_) YYABORT; else { yyerrok; driver.errors_.pop_back(); } } ; -CommaOpt +/*CommaOpt : "," | - ; + ;*/ NewLineOpt : "\n" @@ -516,6 +523,7 @@ Word Identifier : Identifier_ { $$ = $1; } | "each" { $$ = $1; } + | "let" { $$ = $1; } ; IdentifierOpt @@ -588,7 +596,7 @@ ObjectLiteral PropertyNameAndValueList_ : "," PropertyNameAndValueList { $$ = $2; } - | CommaOpt { $$ = NULL; } + | { $$ = NULL; } ; PropertyNameAndValueListOpt @@ -1001,8 +1009,12 @@ Statement | TryStatement { $$ = $1; } ; +Block_ + : "{" StatementListOpt "}" { $$ = $2; } + ; + Block - : "{" StatementListOpt "}" { if ($2) $$ = new(driver.pool_) CYBlock($2); else $$ = new(driver.pool_) CYEmpty(); } + : Block_ { if ($1) $$ = new(driver.pool_) CYBlock($1); else $$ = new(driver.pool_) CYEmpty(); } ; StatementList @@ -1015,7 +1027,7 @@ StatementListOpt ; VariableStatement - : "var" VariableDeclarationList Terminator { $$ = $2; } + : "var" VariableDeclarationList Terminator { $$ = new(driver.pool_) CYVar($2); } ; VariableDeclarationList_ @@ -1105,7 +1117,6 @@ ForStatementInitialiser 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 @@ -1160,16 +1171,16 @@ ThrowStatement ; TryStatement - : "try" Block CatchOpt FinallyOpt { $$ = new(driver.pool_) CYTry($2, $3, $4); } + : "try" Block_ CatchOpt FinallyOpt { $$ = new(driver.pool_) CYTry($2, $3, $4); } ; CatchOpt - : "catch" "(" Identifier ")" Block { $$ = new(driver.pool_) CYCatch($3, $5); } + : "catch" "(" Identifier ")" Block_ { $$ = new(driver.pool_) CYCatch($3, $5); } | { $$ = NULL; } ; FinallyOpt - : "finally" Block { $$ = $2; } + : "finally" Block_ { $$ = $2; } | { $$ = NULL; } ; @@ -1209,7 +1220,7 @@ SourceElement | FunctionDeclaration { $$ = $1; } ; -/* Objective-C Extensions {{{ */ +/* Cycript: @class Declaration {{{ */ ClassSuperOpt : ":" MemberExpressionNoBF { $$ = $2; } | { $$ = NULL; } @@ -1282,7 +1293,8 @@ Statement : ClassDefinition { $$ = $1; } | CategoryStatement { $$ = $1; } ; - +/* }}} */ +/* Cycript: Send Message {{{ */ VariadicCall : "," AssignmentExpression VariadicCall { $$ = new(driver.pool_) CYArgument(NULL, $2, $3); } | { $$ = NULL; } @@ -1325,7 +1337,7 @@ PrimaryExpression_ | "@selector" "(" SelectorExpression ")" { $$ = new(driver.pool_) CYSelector($3); } ; /* }}} */ - +/* Cycript: Pointer Indirection/Addressing {{{ */ AssigneeExpression_ : "*" UnaryExpression { $$ = new(driver.pool_) CYIndirect($2); } ; @@ -1337,7 +1349,13 @@ UnaryExpression_ MemberAccess : "->" Identifier { $$ = new(driver.pool_) CYIndirectMember(NULL, new(driver.pool_) CYString($2)); } ; - +/* }}} */ +/* ECMAScript5: Object Literal Trailing Comma {{{ */ +PropertyNameAndValueList_ + : "," { $$ = NULL; } + ; +/* }}} */ +/* JavaScript 1.7: Array Comprehensions {{{ */ IfComprehension : "if" "(" Expression ")" { $$ = new(driver.pool_) CYIfComprehension($3); } ; @@ -1360,5 +1378,20 @@ ComprehensionList PrimaryExpression_ : "[" AssignmentExpression ComprehensionList "]" { $$ = new(driver.pool_) CYArrayComprehension($2, $3); } ; +/* }}} */ +/* JavaScript 1.7: for each {{{ */ +ForInStatement + : "for" "each" "(" ForInStatementInitialiser "in" Expression ")" Statement { $$ = new(driver.pool_) CYForEachIn($4, $6, $8); } + ; +/* }}} */ +/* JavaScript 1.7: Let Statements {{{ */ +LetStatement + : "let" "(" VariableDeclarationList ")" Block_ { $$ = new(driver.pool_) CYLet($3, $5); } + ; + +Statement + : LetStatement + ; +/* }}} */ %% diff --git a/Output.cpp b/Output.cpp index 100e25a..7580288 100644 --- a/Output.cpp +++ b/Output.cpp @@ -212,16 +212,21 @@ void CYContinue::Output(std::ostream &out) const { void CYClause::Output(std::ostream &out) const { if (case_ != NULL) { out << "case"; - case_->Output(out, CYNoFlags); + case_->Output(out, CYNoLeader); } else out << "default"; out << ':'; if (code_ != NULL) code_->Output(out, false); - out << *next_; + if (next_ != NULL) + out << *next_; +} + +const char *CYDeclaration::ForEachIn() const { + return identifier_->Value(); } -void CYDeclaration::Part(std::ostream &out, CYFlags flags) const { +void CYDeclaration::ForIn(std::ostream &out, CYFlags flags) const { if ((flags & CYNoLeader) != 0) out << ' '; out << "var "; @@ -241,11 +246,12 @@ void CYDeclaration::Output(std::ostream &out, CYFlags flags) const { out << ' '; } -void CYDeclarations::Part(std::ostream &out, CYFlags flags) const { - if ((flags & CYNoLeader) != 0) - out << ' '; +void CYDeclarations::For(std::ostream &out) const { out << "var "; + Output(out, CYNoIn); +} +void CYDeclarations::Output(std::ostream &out, CYFlags flags) const { const CYDeclarations *declaration(this); output: CYDeclarations *next(declaration->next_); @@ -259,11 +265,6 @@ void CYDeclarations::Part(std::ostream &out, CYFlags flags) const { } } -void CYDeclarations::Output(std::ostream &out) const { - Part(out, CYNoFlags); - out << ';'; -} - void CYDirectMember::Output(std::ostream &out, CYFlags flags) const { object_->Output(out, Precedence(), CYLeft(flags)); if (const char *word = property_->Word()) @@ -313,12 +314,20 @@ void CYExpression::ClassName(std::ostream &out, bool object) const { Output(out, CYPA, CYNoFlags); } +const char *CYExpression::ForEachIn() const { + return NULL; +} + +void CYExpression::For(std::ostream &out) const { + Output(out, CYNoIn); +} + void CYExpression::ForEachIn(std::ostream &out) const { // XXX: this should handle LeftHandSideExpression Output(out, CYPA, CYNoFlags); } -void CYExpression::Part(std::ostream &out, CYFlags flags) const { +void CYExpression::ForIn(std::ostream &out, CYFlags flags) const { // XXX: this should handle LeftHandSideExpression Output(out, flags); } @@ -339,7 +348,7 @@ void CYField::Output(std::ostream &out) const { void CYFor::Output(std::ostream &out) const { out << "for("; if (initialiser_ != NULL) - initialiser_->Part(out, CYNoFlags); + initialiser_->For(out); out << ';'; if (test_ != NULL) test_->Output(out, CYNoFlags); @@ -392,7 +401,7 @@ void CYForEachInComprehension::End_(std::ostream &out) const { void CYForIn::Output(std::ostream &out) const { out << "for("; - initialiser_->Part(out, CYNoIn | CYNoTrailer); + initialiser_->ForIn(out, CYNoIn | CYNoTrailer); out << "in"; set_->Output(out, CYNoLeader); out << ')'; @@ -492,6 +501,15 @@ void CYLambda::Output(std::ostream &out, CYFlags flags) const { out << ')'; } +void CYLet::Output(std::ostream &out) const { + out << "let("; + declarations_->Output(out, CYNoFlags); + out << "){"; + if (statements_ != NULL) + statements_->Show(out); + out << "}"; +} + void CYMessage::Output(std::ostream &out, bool replace) const { if (next_ != NULL) next_->Output(out, replace); @@ -743,6 +761,12 @@ void CYTry::Output(std::ostream &out) const { } } +void CYVar::Output(std::ostream &out) const { + out << "var "; + declarations_->Output(out, CYNoFlags); + out << ';'; +} + void CYVariable::Output(std::ostream &out, CYFlags flags) const { if ((flags & CYNoLeader) != 0) out << ' '; diff --git a/Parser.hpp b/Parser.hpp index ed4037e..66bd872 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -222,18 +222,12 @@ enum CYFlags { CYNoBF = (CYNoBrace | CYNoFunction), }; -struct CYPart { - virtual void Part(std::ostream &out, CYFlags flags) const = 0; +struct CYForInitialiser { + virtual void For(std::ostream &out) const = 0; }; -struct CYForInitialiser : - CYPart -{ -}; - -struct CYForInInitialiser : - CYPart -{ +struct CYForInInitialiser { + virtual void ForIn(std::ostream &out, CYFlags flags) const = 0; virtual const char *ForEachIn() const = 0; virtual void ForEachIn(std::ostream &out) const = 0; }; @@ -245,12 +239,11 @@ struct CYExpression : CYClassName { virtual unsigned Precedence() const = 0; - virtual void Part(std::ostream &out, CYFlags flags) const; - virtual const char *ForEachIn() const { - return NULL; - } + virtual void For(std::ostream &out) const; + virtual void ForIn(std::ostream &out, CYFlags flags) const; + virtual const char *ForEachIn() const; virtual void ForEachIn(std::ostream &out) const; virtual void Output(std::ostream &out, CYFlags flags) const = 0; @@ -735,31 +728,55 @@ struct CYDeclaration : { } - virtual void Part(std::ostream &out, CYFlags flags) const; - - virtual const char *ForEachIn() const { - return identifier_->Value(); - } + virtual void ForIn(std::ostream &out, CYFlags flags) const; + virtual const char *ForEachIn() const; virtual void ForEachIn(std::ostream &out) const; virtual void Output(std::ostream &out, CYFlags flags) const; }; struct CYDeclarations : - CYStatement, + CYNext, CYForInitialiser { CYDeclaration *declaration_; - CYDeclarations *next_; CYDeclarations(CYDeclaration *declaration, CYDeclarations *next) : - declaration_(declaration), - next_(next) + CYNext(next), + declaration_(declaration) + { + } + + virtual void For(std::ostream &out) const; + virtual void Output(std::ostream &out, CYFlags flags) const; +}; + +struct CYVar : + CYStatement +{ + CYDeclarations *declarations_; + + CYVar(CYDeclarations *declarations) : + declarations_(declarations) + { + } + + virtual void Output(std::ostream &out) const; +}; + +struct CYLet : + CYStatement +{ + CYDeclarations *declarations_; + CYStatement *statements_; + + CYLet(CYDeclarations *declarations, CYStatement *statements) : + declarations_(declarations), + statements_(statements) { } - virtual void Part(std::ostream &out, CYFlags flags) const; virtual void Output(std::ostream &out) const; }; -- 2.45.2