%code {
+typedef cy::parser::token tk;
+
#undef yylex
_finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CYDriver &driver) {
if (driver.mark_ == CYMarkIgnore);
return cy::parser::token::MarkModule;
}
+ lex:
+ if (driver.newline_ == CYDriver::NewLineHere)
+ driver.newline_ = CYDriver::NewLineLast;
+ else if (driver.newline_ == CYDriver::NewLineLast)
+ driver.newline_ = CYDriver::NewLineNone;
+
YYSTYPE data;
int token(cylex(&data, location, driver.scanner_));
*semantic = data.semantic_;
+
+ switch (token) {
+ case tk::_in_:
+ if (driver.in_.top())
+ token = tk::_in__;
+ break;
+
+ case tk::_yield_:
+ if (driver.yield_.top())
+ token = tk::_yield__;
+ break;
+
+ case tk::HyphenHyphen:
+ if (driver.newline_ == CYDriver::NewLineLast)
+ token = tk::HyphenHyphen_;
+ break;
+
+ case tk::NewLine:
+ driver.newline_ = CYDriver::NewLineHere;
+ if (!driver.next_)
+ goto lex;
+ break;
+
+ case tk::PlusPlus:
+ if (driver.newline_ == CYDriver::NewLineLast)
+ token = tk::PlusPlus_;
+ break;
+ }
+
+ driver.next_ = false;
return token;
}
yyla.type = yytranslate_(token::to); \
} while (false)
+#define CYLIN(from) do { \
+ CYLEX(); \
+ if (yyla.type == yytranslate_(token::from) && driver.newline_ == CYDriver::NewLineLast) \
+ yyla.type = yytranslate_(token::from ## _); \
+} while (false)
+
#define CYERR(location, message) do { \
error(location, message); \
YYABORT; \
%token _instanceof_ "instanceof"
%token _new_ "new"
%token _return_ "return"
-%token _return__ "!return"
%token _super_ "super"
-%token _super__ "!super"
%token _switch_ "switch"
+%token _target_ "target"
%token _this_ "this"
%token _throw_ "throw"
%token _try_ "try"
%token <string_> TemplateMiddle
%token <string_> TemplateTail
+%type <target_> AccessExpression
%type <expression_> AdditiveExpression
%type <argument_> ArgumentList_
%type <argument_> ArgumentList
%type <word_> IdentifierName
%type <variable_> IdentifierReference
%type <statement_> IfStatement
+%type <target_> IndirectExpression
%type <expression_> Initializer
%type <expression_> InitializerOpt
%type <statement_> IterationStatement
/* }}} */
/* Token Priorities {{{ */
%nonassoc ""
-%left "++" "--" "{"
+%left "{"
%nonassoc "if"
%nonassoc "else"
: Word { $$ = $1; }
| "for" { $$ = CYNew CYWord("for"); }
| "in" { $$ = CYNew CYWord("in"); }
- | "Infinity" { $$ = CYNew CYIdentifier("Infinity"); }
| "instanceof" { $$ = CYNew CYWord("instanceof"); }
;
| "new" LexSetRegExp { $$ = CYNew CYWord("new"); }
| "null" { $$ = CYNew CYWord("null"); }
| "return" { $$ = CYNew CYWord("return"); }
- | "!return" { $$ = CYNew CYWord("return"); }
| "super" { $$ = CYNew CYWord("super"); }
- | "!super" { $$ = CYNew CYWord("super"); }
| "switch" { $$ = CYNew CYWord("switch"); }
| "this" { $$ = CYNew CYWord("this"); }
| "throw" { $$ = CYNew CYWord("throw"); }
Terminator
: ";"
- | error { if (yyla.type_get() != yyeof_ && yyla.type != yytranslate_(token::CloseBrace) && !driver.newline_) { CYERR(@1, "required semi-colon"); } else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
+ | error { if (yyla.type_get() != yyeof_ && yyla.type != yytranslate_(token::CloseBrace) && driver.newline_ == CYDriver::NewLineNone) { CYERR(@1, "required semi-colon"); } else { yyerrok; driver.errors_.pop_back(); } } StrictSemi
;
TerminatorOpt
| "get" { $$ = CYNew CYIdentifier("get"); }
| "goto" { $$ = CYNew CYIdentifier("goto"); }
| "implements" { $$ = CYNew CYIdentifier("implements"); }
+ | "Infinity" { $$ = CYNew CYIdentifier("Infinity"); }
| "interface" { $$ = CYNew CYIdentifier("interface"); }
| "native" { $$ = CYNew CYIdentifier("native"); }
| "of" { $$ = CYNew CYIdentifier("of"); }
| "public" { $$ = CYNew CYIdentifier("public"); }
| "set" { $$ = CYNew CYIdentifier("set"); }
| "synchronized" { $$ = CYNew CYIdentifier("synchronized"); }
+ | "target" { $$ = CYNew CYIdentifier("target"); }
| "throws" { $$ = CYNew CYIdentifier("throws"); }
| "transient" { $$ = CYNew CYIdentifier("transient"); }
| "undefined" { $$ = CYNew CYIdentifier("undefined"); }
: NullLiteral { $$ = $1; }
| BooleanLiteral { $$ = $1; }
| NumericLiteral { $$ = $1; }
- | "Infinity" { $$ = CYNew CYNumber(std::numeric_limits<double>::infinity()); }
| StringLiteral { $$ = $1; }
;
/* }}} */
;
SuperProperty
- : LexSetRegExp "!super" "[" Expression "]" { $$ = CYNew CYSuperAccess($4); }
- | LexSetRegExp "!super" "." IdentifierName { $$ = CYNew CYSuperAccess(CYNew CYString($4)); }
+ : LexSetRegExp "super" { if (!driver.super_.top()) CYERR(@2, "invalid super"); } "[" Expression "]" { $$ = CYNew CYSuperAccess($5); }
+ | LexSetRegExp "super" { if (!driver.super_.top()) CYERR(@2, "invalid super"); } "." IdentifierName { $$ = CYNew CYSuperAccess(CYNew CYString($5)); }
;
MetaProperty
;
SuperCall
- : LexSetRegExp "!super" Arguments { $$ = CYNew CYSuperCall($3); }
+ : LexSetRegExp "super" { if (!driver.super_.top()) CYERR(@2, "invalid super"); } Arguments { $$ = CYNew CYSuperCall($4); }
;
Arguments
| LexSetRegExp { $$ = NULL; }
;
-LeftHandSideExpression
+AccessExpression
: NewExpression { $$ = $1; }
| CallExpression { $$ = $1; }
;
+
+LeftHandSideExpression
+ : AccessExpression { $$ = $1; }
+ | LexSetRegExp IndirectExpression { $$ = $2; }
+ ;
/* }}} */
/* 12.4 Postfix Expressions {{{ */
PostfixExpression
- : %prec "" LeftHandSideExpression { $$ = $1; }
- | LeftHandSideExpression "++" { $$ = CYNew CYPostIncrement($1); }
- | LeftHandSideExpression "--" { $$ = CYNew CYPostDecrement($1); }
+ : AccessExpression { $$ = $1; }
+ | AccessExpression "++" { $$ = CYNew CYPostIncrement($1); }
+ | AccessExpression "--" { $$ = CYNew CYPostDecrement($1); }
;
/* }}} */
/* 12.5 Unary Operators {{{ */
;
UnaryExpression
- : %prec "" PostfixExpression { $$ = $1; }
+ : %prec "" PostfixExpression LexOpenBrace { $$ = $1; }
| LexSetRegExp UnaryExpression_ { $$ = $2; }
;
/* }}} */
;
ForInStatementInitializer
- : LeftHandSideExpression { $$ = $1; }
+ : AccessExpression { $$ = $1; }
+ | LexSetRegExp IndirectExpression { $$ = $2; }
| LexSetRegExp Var_ ForBinding { $$ = CYNew CYForVariable($3); }
| LexSetRegExp ForDeclaration { $$ = $2; }
;
/* }}} */
/* 13.10 The return Statement {{{ */
Return
- : "!return" LexNewLine
+ : "return" { if (!driver.return_.top()) CYERR(@1, "invalid return"); } LexNewLine
;
ReturnStatement
;
/* }}} */
/* 14.2 Arrow Function Definitions {{{ */
+LexEqualRight
+ : { CYLIN(EqualRight); }
+ ;
+
ArrowFunction
- : LexSetRegExp ArrowParameters "=>" LexNoBrace ConciseBody { $$ = CYNew CYFatArrow($2, $5); }
+ : LexSetRegExp ArrowParameters LexEqualRight "=>" LexNoBrace ConciseBody { $$ = CYNew CYFatArrow($2, $6); }
;
ArrowParameters
;
ImplementationFieldListOpt
- : TypedIdentifier ";" ImplementationFieldListOpt { $$ = CYNew CYImplementationField($1, $3); }
+ : LexSetRegExp TypedIdentifier ";" ImplementationFieldListOpt { $$ = CYNew CYImplementationField($2, $4); }
| LexSetRegExp { $$ = NULL; }
;
MessageExpression
: "[" LexPushInOff AssignmentExpressionClassic { driver.contexts_.push_back($3); } SelectorList "]" LexPopIn { driver.contexts_.pop_back(); } { $$ = CYNew CYSendDirect($3, $5); }
- | "[" LexPushInOff LexSetRegExp "!super" { driver.context_ = NULL; } SelectorList "]" LexPopIn { $$ = CYNew CYSendSuper($6); }
+ | "[" LexPushInOff LexSetRegExp "super" { driver.context_ = NULL; } SelectorList "]" LexPopIn { $$ = CYNew CYSendSuper($6); }
;
SelectorExpression_
@begin C
/* Cycript (C): Pointer Indirection/Addressing {{{ */
-LeftHandSideExpression
- : LexSetRegExp "*" UnaryExpression { $$ = CYNew CYIndirect($3); }
+UnaryExpression_
+ : IndirectExpression { $$ = $1; }
+ ;
+
+IndirectExpression
+ : "*" UnaryExpression { $$ = CYNew CYIndirect($2); }
;
UnaryExpression_
;
ComprehensionFor
- : "for" "each" "(" LexPushInOn LexicalBinding "!in" LexPopIn Expression ")" { $$ = CYNew CYForOfComprehension($5, $8); }
+ : "for" "each" "(" LexPushInOn ForBinding "!in" LexPopIn Expression ")" { $$ = CYNew CYForOfComprehension($5, $8); }
;
/* }}} */
/* JavaScript FTL: for each {{{ */
RubyProcParametersOpt
: RubyProcParameters { $$ = $1; }
- | { $$ = NULL; }
+ | LexSetRegExp { $$ = NULL; }
+ ;
+
+LexOpenBrace
+ : { CYLIN(OpenBrace); }
;
RubyProcExpression
;
PostfixExpression
- : PostfixExpression RubyProcExpression { $$ = CYNew CYRubyBlock($1, $2); }
+ : PostfixExpression LexOpenBrace RubyProcExpression { $$ = CYNew CYRubyBlock($1, $3); }
;
/* }}} */