%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::NewLine:
+ driver.newline_ = CYDriver::NewLineHere;
+ if (!driver.next_)
+ goto lex;
+ 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; \
} while (false)
+#define CYEOK() do { \
+ yyerrok; \
+ driver.errors_.pop_back(); \
+} while (false)
+
#define CYNOT(location) \
CYERR(location, "unimplemented feature")
+#define CYMPT(location) do { \
+ if (!yyla.empty() && yyla.type_get() != yyeof_) \
+ CYERR(location, "unexpected lookahead"); \
+} while (false)
+
}
%name-prefix "cy"
%token OpenBrace "{"
%token OpenBrace_ "\n{"
%token OpenBrace__ ";{"
+%token OpenBrace_let "let {"
%token CloseBrace "}"
%token OpenBracket "["
+%token OpenBracket_let "let ["
%token CloseBracket "]"
%token At_error_ "@error"
%token _instanceof_ "instanceof"
%token _new_ "new"
%token _return_ "return"
-%token _return__ "!return"
%token _super_ "super"
%token _switch_ "switch"
%token _target_ "target"
%token _int_ "int"
%token _interface_ "interface"
%token _let_ "let"
+%token _let__ "!let"
%token _long_ "long"
%token _native_ "native"
%token _package_ "package"
%token _auto_ "auto"
%token _each_ "each"
%token _of_ "of"
+%token _of__ "!of"
@begin E4X
%token _namespace_ "namespace"
%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
@end
/* }}} */
/* Token Priorities {{{ */
-%nonassoc ""
-%left "++" "--" "{"
-
%nonassoc "if"
%nonassoc "else"
/* }}} */
LexPushYieldOff: { driver.yield_.push(false); };
LexPopYield: { driver.yield_.pop(); };
+LexOf
+ : { CYMAP(_of__, _of_); }
+ ;
+
LexSetRegExp
- : { CYLEX(); if (yyla.type == yytranslate_(token::Slash)) { yyla.clear(); driver.SetRegEx(false); } else if (yyla.type == yytranslate_(token::SlashEqual)) { yyla.clear(); driver.SetRegEx(true); } }
+ : { CYLEX(); if (yyla.type == yytranslate_(token::Slash)) { yyla.clear(); driver.SetRegEx(false); } else if (yyla.type == yytranslate_(token::SlashEqual)) { yyla.clear(); driver.SetRegEx(true); } } LexOf
;
LexNewLine
- : { if (!yyla.empty() && yyla.type_get() != yyeof_) CYERR(@$, "unexpected lookahead"); driver.next_ = true; }
+ : { CYMPT(@$); driver.next_ = true; }
;
LexNoStar
: 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"); }
| "switch" { $$ = CYNew CYWord("switch"); }
| "this" { $$ = CYNew CYWord("this"); }
| "yield" { $$ = CYNew CYIdentifier("yield"); }
| Yield LexSetRegExp NewLineOpt { $$ = CYNew CYIdentifier("yield"); }
-
- // XXX: should be Identifier
- | "let" { $$ = CYNew CYIdentifier("let"); }
;
@begin ObjectiveC
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 CYEOK(); } StrictSemi
;
TerminatorOpt
| "get" { $$ = CYNew CYIdentifier("get"); }
| "goto" { $$ = CYNew CYIdentifier("goto"); }
| "implements" { $$ = CYNew CYIdentifier("implements"); }
+ | "Infinity" { $$ = CYNew CYIdentifier("Infinity"); }
| "interface" { $$ = CYNew CYIdentifier("interface"); }
+ | "let" { $$ = CYNew CYIdentifier("let"); }
+ | "!let" LexBind { $$ = CYNew CYIdentifier("let"); }
| "native" { $$ = CYNew CYIdentifier("native"); }
- | "of" { $$ = CYNew CYIdentifier("of"); }
+ | "!of" { $$ = CYNew CYIdentifier("of"); }
| "package" { $$ = CYNew CYIdentifier("package"); }
| "private" { $$ = CYNew CYIdentifier("private"); }
| "protected" { $$ = CYNew CYIdentifier("protected"); }
: NullLiteral { $$ = $1; }
| BooleanLiteral { $$ = $1; }
| NumericLiteral { $$ = $1; }
- | "Infinity" { $$ = CYNew CYNumber(std::numeric_limits<double>::infinity()); }
| StringLiteral { $$ = $1; }
;
/* }}} */
| LexSetRegExp { $$ = NULL; }
;
-LeftHandSideExpression
+AccessExpression
: NewExpression { $$ = $1; }
| CallExpression { $$ = $1; }
;
+
+LeftHandSideExpression
+ : AccessExpression LexCrement { $$ = $1; }
+ | LexSetRegExp IndirectExpression { $$ = $2; }
+ ;
/* }}} */
/* 12.4 Postfix Expressions {{{ */
+LexCrement
+ : { CYLIN(PlusPlus); CYLIN(HyphenHyphen); }
+ ;
+
PostfixExpression
- : %prec "" LeftHandSideExpression { $$ = $1; }
- | LeftHandSideExpression "++" { $$ = CYNew CYPostIncrement($1); }
- | LeftHandSideExpression "--" { $$ = CYNew CYPostDecrement($1); }
+ : AccessExpression LexCrement { $$ = $1; }
+ | AccessExpression LexCrement "++" { $$ = CYNew CYPostIncrement($1); }
+ | AccessExpression LexCrement "--" { $$ = CYNew CYPostDecrement($1); }
;
/* }}} */
/* 12.5 Unary Operators {{{ */
;
UnaryExpression
- : %prec "" PostfixExpression { $$ = $1; }
+ : PostfixExpression LexOpenBrace { $$ = $1; }
| LexSetRegExp UnaryExpression_ { $$ = $2; }
;
/* }}} */
;
Statement
- : LexSetStatement Statement_ { $$ = $2; }
+ : LexSetStatement LexLet Statement_ { $$ = $3; }
;
Declaration__
: HoistableDeclaration { $$ = $1; }
| ClassDeclaration { $$ = $1; }
- | LexicalDeclaration { $$ = $1; }
;
Declaration_
- : LexSetRegExp Declaration__ { $$ = $2; }
+ : LexLet LexSetRegExp Declaration__ { $$ = $3; }
+ | LexicalDeclaration { $$ = $1; }
;
Declaration
StatementListOpt
: StatementList { $$ = $1; }
- | LexSetStatement LexSetRegExp { $$ = NULL; }
+ | LexSetStatement LexLet LexSetRegExp { $$ = NULL; }
;
StatementListItem
: LexicalDeclaration_ Terminator { $$ = $1; }
;
+LexLet
+ : { CYMAP(_let__, _let_); }
+ ;
+
+LexBind
+ : { CYMAP(OpenBrace_let, OpenBrace); CYMAP(OpenBracket_let, OpenBracket); } LexOf
+ ;
+
LetOrConst
- : "let" { $$ = false; }
- | "const" { $$ = true; }
+ : LexLet LexSetRegExp "!let" LexBind { $$ = false; }
+ | LexLet LexSetRegExp "const" { $$ = true; }
;
BindingList_
- : "," BindingList { $$ = $2; }
+ : "," LexBind BindingList { $$ = $3; }
| { $$ = NULL; }
;
;
VariableDeclarationList
- : VariableDeclaration VariableDeclarationList_ { $$ = CYNew CYDeclarations($1, $2); }
+ : LexBind VariableDeclaration VariableDeclarationList_ { $$ = CYNew CYDeclarations($2, $3); }
;
VariableDeclaration
;
ObjectBindingPattern
- : BRACE BindingPropertyListOpt "}"
+ : "let {" BindingPropertyListOpt "}"
;
ArrayBindingPattern
- : "[" { CYNOT(@$); }
+ : "let [" { CYNOT(@$); }
;
BindingPropertyList_
;
BindingElement
- : SingleNameBinding { $$ = $1; }
- | BindingPattern InitializerOpt { CYNOT(@$); }
+ : LexBind SingleNameBinding { $$ = $2; }
+ | LexBind BindingPattern InitializerOpt { CYNOT(@$); }
;
SingleNameBinding
: "do" Statement "while" "(" Expression ")" TerminatorOpt { $$ = CYNew CYDoWhile($5, $2); }
| "while" "(" Expression ")" Statement { $$ = CYNew CYWhile($3, $5); }
| "for" "(" LexPushInOn ForStatementInitializer LexPopIn ExpressionOpt ";" ExpressionOpt ")" Statement { $$ = CYNew CYFor($4, $6, $8, $10); }
- | "for" "(" LexPushInOn LexSetRegExp Var_ BindingIdentifier Initializer "!in" LexPopIn Expression ")" Statement { $$ = CYNew CYForInitialized(CYNew CYDeclaration($6, $7), $10, $12); }
+ | "for" "(" LexPushInOn LexLet LexSetRegExp Var_ LexBind BindingIdentifier Initializer "!in" LexPopIn Expression ")" Statement { $$ = CYNew CYForInitialized(CYNew CYDeclaration($8, $9), $12, $14); }
| "for" "(" LexPushInOn ForInStatementInitializer "!in" LexPopIn Expression ")" Statement { $$ = CYNew CYForIn($4, $7, $9); }
| "for" "(" LexPushInOn ForInStatementInitializer "of" LexPopIn AssignmentExpression ")" Statement { $$ = CYNew CYForOf($4, $7, $9); }
;
ForStatementInitializer
- : LexSetRegExp EmptyStatement { $$ = $2; }
- | ExpressionStatement_ ";" { $$ = $1; }
- | LexSetRegExp VariableStatement_ ";" { $$ = $2; }
- | LexSetRegExp LexicalDeclaration_ ";" { $$ = $2; }
+ : LexLet LexSetRegExp EmptyStatement { $$ = $3; }
+ | LexLet ExpressionStatement_ ";" { $$ = $2; }
+ | LexLet LexSetRegExp VariableStatement_ ";" { $$ = $3; }
+ | LexicalDeclaration_ ";" { $$ = $1; }
;
ForInStatementInitializer
- : LeftHandSideExpression { $$ = $1; }
- | LexSetRegExp Var_ ForBinding { $$ = CYNew CYForVariable($3); }
- | LexSetRegExp ForDeclaration { $$ = $2; }
+ : LexLet AccessExpression LexCrement { $$ = $2; }
+ | LexLet LexSetRegExp IndirectExpression { $$ = $3; }
+ | LexLet LexSetRegExp Var_ LexBind ForBinding { $$ = CYNew CYForVariable($5); }
+ | ForDeclaration { $$ = $1; }
;
ForDeclaration
/* }}} */
/* 13.10 The return Statement {{{ */
Return
- : "!return" LexNewLine
+ : "return" { if (!driver.return_.top()) CYERR(@1, "invalid return"); } LexNewLine
;
ReturnStatement
LabelledItem
: Statement { $$ = $1; }
- | LexSetStatement LexSetRegExp FunctionDeclaration { $$ = $3; }
+ | LexSetStatement LexLet LexSetRegExp FunctionDeclaration { $$ = $4; }
;
/* }}} */
/* 13.14 The throw Statement {{{ */
;
Catch
- : "catch" "(" CatchParameter ")" Block { $$ = CYNew cy::Syntax::Catch($3, $5); }
+ : "catch" "(" LexBind CatchParameter ")" Block { $$ = CYNew cy::Syntax::Catch($4, $6); }
;
Finally
;
FormalParameters
- : { $$ = NULL; }
+ : LexBind { $$ = NULL; }
| FormalParameterList
;
;
FormalParameterList
- : FunctionRestParameter { CYNOT(@$); }
+ : LexBind FunctionRestParameter { CYNOT(@$); }
| FormalParameter FormalParameterList_ { $$ = CYNew CYFunctionParameter($1, $2); }
;
;
/* }}} */
/* 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
;
ClassHeritage
- : "extends" LeftHandSideExpression { $$ = CYNew CYClassTail($2); }
+ : "extends" AccessExpression { $$ = CYNew CYClassTail($2); }
;
ClassHeritageOpt
ScriptBodyOpt
: ScriptBody { $$ = $1; }
- | LexSetStatement LexSetRegExp { $$ = NULL; }
+ | LexSetStatement LexLet LexSetRegExp { $$ = NULL; }
;
/* }}} */
/* 15.2 Modules {{{ */
;
ModuleItem
- : LexSetStatement LexSetRegExp ImportDeclaration
- | LexSetStatement LexSetRegExp ExportDeclaration
+ : LexSetStatement LexLet LexSetRegExp ImportDeclaration
+ | LexSetStatement LexLet LexSetRegExp ExportDeclaration
| StatementListItem
;
/* }}} */
;
ExportDeclaration
- : "export" LexSetStatement LexSetRegExp ExportDeclaration_
+ : "export" LexSetStatement LexLet LexSetRegExp ExportDeclaration_
| "export" Declaration
;
;
ImplementationFieldListOpt
- : TypedIdentifier ";" ImplementationFieldListOpt { $$ = CYNew CYImplementationField($1, $3); }
+ : LexSetRegExp TypedIdentifier ";" ImplementationFieldListOpt { $$ = CYNew CYImplementationField($2, $4); }
| LexSetRegExp { $$ = NULL; }
;
@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 LexBind ForBinding "!in" LexPopIn Expression ")" { $$ = CYNew CYForOfComprehension($6, $9); }
;
/* }}} */
/* JavaScript FTL: for each {{{ */
;
ComprehensionFor
- : "for" "(" LexPushInOn ForBinding "!in" LexPopIn Expression ")" { $$ = CYNew CYForInComprehension($4, $7); }
- | "for" "(" LexPushInOn ForBinding "of" LexPopIn Expression ")" { $$ = CYNew CYForOfComprehension($4, $7); }
+ : "for" "(" LexPushInOn LexBind ForBinding "!in" LexPopIn Expression ")" { $$ = CYNew CYForInComprehension($5, $8); }
+ | "for" "(" LexPushInOn LexBind ForBinding "of" LexPopIn Expression ")" { $$ = CYNew CYForOfComprehension($5, $8); }
;
ComprehensionIf
RubyProcParametersOpt
: RubyProcParameters { $$ = $1; }
- | { $$ = NULL; }
+ | LexSetRegExp { $$ = NULL; }
+ ;
+
+LexOpenBrace
+ : { CYLIN(OpenBrace); }
;
RubyProcExpression
;
PostfixExpression
- : PostfixExpression RubyProcExpression { $$ = CYNew CYRubyBlock($1, $2); }
+ : PostfixExpression LexOpenBrace RubyProcExpression { $$ = CYNew CYRubyBlock($1, $3); }
;
/* }}} */