]> git.saurik.com Git - cycript.git/blobdiff - Parser.ypp.in
Use implicit properties on older, broken runtimes.
[cycript.git] / Parser.ypp.in
index 3d5aa6d4a31802054043032cdfd85891280e1080..0d8e87d50109910107dd4d3b02bff9953f3e0516 100644 (file)
@@ -1,5 +1,5 @@
-/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2015  Jay Freeman (saurik)
+/* Cycript - The Truly Universal Scripting Language
+ * Copyright (C) 2009-2016  Jay Freeman (saurik)
 */
 
 /* GNU Affero General Public License, Version 3 {{{ */
@@ -27,6 +27,7 @@
 #include "Driver.hpp"
 #include "Parser.hpp"
 #include "Stack.hpp"
+#include "Syntax.hpp"
 #define CYNew new(driver.pool_)
 
 @begin ObjectiveC
 %union { CYBinding *binding_; }
 %union { CYBindings *bindings_; }
 %union { CYBoolean *boolean_; }
+%union { CYBraced *braced_; }
 %union { CYClause *clause_; }
 %union { cy::Syntax::Catch *catch_; }
 %union { CYClassTail *classTail_; }
 %union { CYComprehension *comprehension_; }
 %union { CYElement *element_; }
+%union { CYEnumConstant *constant_; }
 %union { CYExpression *expression_; }
 %union { CYFalse *false_; }
 %union { CYVariable *variable_; }
@@ -71,7 +74,7 @@
 %union { CYParenthetical *parenthetical_; }
 %union { CYProperty *property_; }
 %union { CYPropertyName *propertyName_; }
-%union { CYRubyProc *rubyProc_; }
+%union { CYTypeSigning signing_; }
 %union { CYSpan *span_; }
 %union { CYStatement *statement_; }
 %union { CYString *string_; }
 %union { CYWord *word_; }
 
 @begin C
+%union { CYTypeIntegral *integral_; }
 %union { CYTypeStructField *structField_; }
 %union { CYTypeModifier *modifier_; }
 %union { CYTypeSpecifier *specifier_; }
-%union { CYTypedIdentifier *typedIdentifier_; }
+%union { CYTypedFormal *typedFormal_; }
+%union { CYTypedLocation *typedLocation_; }
+%union { CYTypedName *typedName_; }
 %union { CYTypedParameter *typedParameter_; }
+%union { CYType *typedThing_; }
 @end
 
 @begin ObjectiveC
+%union { CYObjCKeyValue *keyValue_; }
 %union { CYImplementationField *implementationField_; }
 %union { CYMessage *message_; }
 %union { CYMessageParameter *messageParameter_; }
@@ -181,6 +189,13 @@ type; })
         yyla.type = yytranslate_(token::to); \
 } while (false)
 
+#define CYHLD(location, token) do { \
+    if (driver.hold_ != empty_symbol) \
+        CYERR(location, "unexpected hold"); \
+    driver.hold_ = yyla.type; \
+    yyla.type = yytranslate_(token); \
+} while (false)
+
 #define CYERR(location, message) do { \
     error(location, message); \
     YYABORT; \
@@ -215,6 +230,9 @@ type; })
         case CYMarkModule:
             driver.hold_ = yytranslate_(token::MarkModule);
             break;
+        case CYMarkExpression:
+            driver.hold_ = yytranslate_(token::MarkExpression);
+            break;
     }
 };
 
@@ -250,13 +268,11 @@ type; })
 %token SlashRight "/>"
 %token LeftSlash "</"
 
-%token ColonColon "::"
 %token PeriodPeriod ".."
 @end
 
 @begin E4X ObjectiveC
 %token At "@"
-%token Pound "#"
 @end
 
 %token Ampersand "&"
@@ -302,9 +318,11 @@ type; })
 %token Tilde "~"
 
 %token Colon ":"
+%token ColonColon "::"
 %token Comma ","
 %token Question "?"
 %token SemiColon ";"
+%token Pound "#"
 %token NewLine "\n"
 %token __ ""
 
@@ -413,6 +431,7 @@ type; })
 %token _goto_ "goto"
 %token _implements_ "implements"
 %token _int_ "int"
+%token ___int128_ "__int128"
 %token _interface_ "interface"
 %token _let_ "let"
 %token _let__ "!let"
@@ -424,12 +443,15 @@ type; })
 %token ___proto___ "__proto__"
 %token _prototype_ "prototype"
 %token _public_ "public"
+%token ___restrict_ "__restrict"
+%token _restrict_ "restrict"
 %token _set_ "set"
 %token _short_ "short"
 %token _static_ "static"
 %token _synchronized_ "synchronized"
 %token _throws_ "throws"
 %token _transient_ "transient"
+%token _typeid_ "typeid"
 %token _volatile_ "volatile"
 %token _yield_ "yield"
 %token _yield__ "!yield"
@@ -474,11 +496,11 @@ type; })
 %type <argument_> ArgumentListOpt
 %type <argument_> Arguments
 %type <target_> ArrayComprehension
+%type <element_> ArrayElement
 %type <literal_> ArrayLiteral
 %type <expression_> ArrowFunction
 %type <functionParameter_> ArrowParameters
 %type <expression_> AssignmentExpression
-%type <expression_> AssignmentExpressionOpt
 %type <identifier_> BindingIdentifier
 %type <identifier_> BindingIdentifierOpt
 %type <bindings_> BindingList_
@@ -490,6 +512,8 @@ type; })
 %type <binding_> BindingElement
 %type <expression_> BitwiseORExpression
 %type <expression_> BitwiseXORExpression
+%type <target_> BracedExpression_
+%type <target_> BracedExpression
 %type <statement_> BreakStatement
 %type <statement_> BreakableStatement
 %type <expression_> CallExpression_
@@ -517,6 +541,7 @@ type; })
 %type <statement_> Declaration_
 %type <statement_> Declaration
 %type <clause_> DefaultClause
+%type <element_> ElementList_
 %type <element_> ElementList
 %type <element_> ElementListOpt
 %type <statement_> ElseStatementOpt
@@ -609,9 +634,7 @@ type; })
 %type <bool_> RegularExpressionSlash
 %type <expression_> RelationalExpression
 %type <statement_> ReturnStatement
-%type <target_> RubyBlockExpression_
-%type <target_> RubyBlockExpression
-%type <rubyProc_> RubyProcExpression
+%type <braced_> BracedParameter
 %type <functionParameter_> RubyProcParameterList_
 %type <functionParameter_> RubyProcParameterList
 %type <functionParameter_> RubyProcParameters
@@ -645,31 +668,44 @@ type; })
 %type <statement_> VariableStatement
 %type <statement_> WithStatement
 %type <word_> Word
+%type <word_> WordNoUnary
 @begin ObjectiveC
 %type <word_> WordOpt
 @end
 %type <expression_> YieldExpression
 
 @begin C
-%type <specifier_> IntegerType
-%type <specifier_> IntegerTypeOpt
-%type <typedIdentifier_> PrefixedType
+%type <constant_> EnumConstantListOpt_
+%type <constant_> EnumConstantListOpt
+%type <number_> IntegerNumber
+%type <integral_> IntegerType
+%type <integral_> IntegerTypeOpt
+%type <typedName_> PrefixedType
+%type <specifier_> PrimitiveReference
 %type <specifier_> PrimitiveType
 %type <structField_> StructFieldListOpt
-%type <typedIdentifier_> SuffixedType
-%type <typedIdentifier_> SuffixedTypeOpt
-%type <typedIdentifier_> TypeSignifier
-%type <typedIdentifier_> TypeSignifierOpt
+%type <typedName_> SuffixedType
+%type <typedName_> SuffixedTypeOpt
+%type <typedName_> TypeSignifier
+%type <typedName_> TypeSignifierNone
+%type <typedName_> TypeSignifierOpt
+%type <signing_> TypeSigning
+%type <modifier_> ParameterTail
 %type <modifier_> TypeQualifierLeft
 %type <modifier_> TypeQualifierLeftOpt
-%type <typedIdentifier_> TypeQualifierRight
-%type <typedIdentifier_> TypeQualifierRightOpt
-%type <typedIdentifier_> TypedIdentifierMaybe
-%type <typedIdentifier_> TypedIdentifierNo
-%type <typedIdentifier_> TypedIdentifierYes
-%type <typedParameter_> TypedParameterList_
-%type <typedParameter_> TypedParameterList
-%type <typedParameter_> TypedParameterListOpt
+%type <typedName_> TypeQualifierRight
+%type <typedName_> TypeQualifierRightOpt
+%type <typedName_> TypedIdentifierDefinition
+%type <typedThing_> TypedIdentifierEncoding
+%type <typedName_> TypedIdentifierField
+%type <typedName_> TypedIdentifierMaybe
+%type <typedLocation_> TypedIdentifierNo
+%type <typedName_> TypedIdentifierTagged
+%type <typedName_> TypedIdentifierYes
+%type <typedFormal_> TypedParameterList_
+%type <typedFormal_> TypedParameterList
+%type <typedFormal_> TypedParameterListOpt
+%type <typedParameter_> TypedParameters
 @end
 
 @begin ObjectiveC
@@ -685,6 +721,9 @@ type; })
 %type <protocol_> ClassProtocolsOpt
 %type <implementationField_> ImplementationFieldListOpt
 %type <statement_> ImplementationStatement
+%type <keyValue_> KeyValuePairList_
+%type <keyValue_> KeyValuePairList
+%type <keyValue_> KeyValuePairListOpt
 %type <target_> MessageExpression
 %type <messageParameter_> MessageParameter
 %type <messageParameter_> MessageParameters
@@ -698,7 +737,7 @@ type; })
 %type <selector_> SelectorExpressionOpt
 %type <argument_> SelectorList
 %type <word_> SelectorWordOpt
-%type <typedIdentifier_> TypeOpt
+%type <typedThing_> TypeOpt
 %type <argument_> VariadicCall
 @end
 
@@ -726,17 +765,22 @@ type; })
 /* Token Priorities {{{ */
 %nonassoc "if"
 %nonassoc "else"
+
+%nonassoc ":"
+%nonassoc "!yield"
 /* }}} */
 
 %start Program
 %token MarkModule
 %token MarkScript
+%token MarkExpression
 
 %%
 
 Program
     : MarkScript Script
     | MarkModule Module
+    | MarkExpression Expression[expression] { driver.context_ = $expression; }
     ;
 
 /* Lexer State {{{ */
@@ -758,11 +802,11 @@ LexPushYieldOff: { driver.yield_.push(false); };
 LexPopYield: { driver.yield_.pop(); };
 
 LexNewLineOrOpt
-    : { CYLEX(); if (driver.hold_ != empty_symbol) CYERR(@$, "unexpected hold"); if (driver.newline_) { driver.hold_ = yyla.type; yyla.type = yytranslate_(cy::parser::token::NewLine); } }
+    : { CYLEX(); if (driver.newline_) { CYHLD(@$, tk::NewLine); } }
     ;
 
 LexNewLineOrNot
-    : { CYLEX(); if (driver.hold_ != empty_symbol) CYERR(@$, "unexpected hold"); driver.hold_ = yyla.type; yyla.type = yytranslate_(driver.newline_ ? cy::parser::token::NewLine : cy::parser::token::__); }
+    : { CYLEX(); CYHLD(@$, driver.newline_ ? tk::NewLine : tk::__); }
     ;
 
 LexNoStar
@@ -799,7 +843,7 @@ IdentifierName
     | "instanceof" { $$ = CYNew CYWord("instanceof"); }
     ;
 
-Word
+WordNoUnary
     : IdentifierNoOf[pass] { $$ = $pass; }
     | "break" { $$ = CYNew CYWord("break"); }
     | "case" { $$ = CYNew CYWord("case"); }
@@ -810,7 +854,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"); }
@@ -823,7 +866,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"); }
@@ -832,11 +874,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"); }
     ;
 
@@ -959,6 +1006,7 @@ IdentifierTypeNoOf
     | "target" { $$ = CYNew CYIdentifier("target"); }
     | "throws" { $$ = CYNew CYIdentifier("throws"); }
     | "transient" { $$ = CYNew CYIdentifier("transient"); }
+    | "typeid" { $$ = CYNew CYIdentifier("typeid"); }
     | "undefined" { $$ = CYNew CYIdentifier("undefined"); }
 @begin ObjectiveC
     | "bool" { $$ = CYNew CYIdentifier("bool"); }
@@ -982,13 +1030,15 @@ IdentifierNoOf
     : IdentifierTypeNoOf
     | "char" { $$ = CYNew CYIdentifier("char"); }
     | "int" { $$ = CYNew CYIdentifier("int"); }
+    | "__int128" { $$ = CYNew CYIdentifier("__int128"); }
     | "long" { $$ = CYNew CYIdentifier("long"); }
+    | "__restrict" { $$ = CYNew CYIdentifier("__restrict"); }
+    | "restrict" { $$ = CYNew CYIdentifier("restrict"); }
     | "short" { $$ = CYNew CYIdentifier("short"); }
     | "static" { $$ = CYNew CYIdentifier("static"); }
     | "volatile" { $$ = CYNew CYIdentifier("volatile"); }
 @begin C
     | "signed" { $$ = CYNew CYIdentifier("signed"); }
-    | "struct" { $$ = CYNew CYIdentifier("struct"); }
     | "unsigned" { $$ = CYNew CYIdentifier("unsigned"); }
 @end
 @begin ObjectiveC
@@ -1041,10 +1091,19 @@ ArrayLiteral
     : "[" ElementListOpt[elements] "]" { $$ = CYNew CYArray($elements); }
     ;
 
-ElementList
-    : AssignmentExpressionOpt[value] "," ElementListOpt[next] { $$ = CYNew CYElementValue($value, $next); }
+ArrayElement
+    : AssignmentExpression[value] { $$ = CYNew CYElementValue($value); }
     | LexOf "..." AssignmentExpression[values] { $$ = CYNew CYElementSpread($values); }
-    | AssignmentExpression[value] { $$ = CYNew CYElementValue($value, NULL); }
+    ;
+
+ElementList_
+    : "," ElementListOpt[elements] { $$ = $elements; } 
+    | { $$ = NULL; }
+    ;
+
+ElementList
+    : ArrayElement[element] ElementList_[next] { $$ = $element; $$->SetNext($next); }
+    | LexOf "," ElementListOpt[next] { $$ = CYNew CYElementValue(NULL, $next); }
     ;
 
 ElementListOpt
@@ -1192,13 +1251,13 @@ AccessExpression
     ;
 
 LeftHandSideExpression
-    : RubyBlockExpression[pass] { $$ = $pass; }
+    : BracedExpression[pass] { $$ = $pass; }
     | IndirectExpression[pass] { $$ = $pass; }
     ;
 /* }}} */
 /* 12.4 Postfix Expressions {{{ */
 PostfixExpression
-    : RubyBlockExpression[pass] { $$ = $pass; }
+    : BracedExpression[pass] { $$ = $pass; }
     | AccessExpression[lhs] LexNewLineOrOpt "++" { $$ = CYNew CYPostIncrement($lhs); }
     | AccessExpression[lhs] LexNewLineOrOpt "--" { $$ = CYNew CYPostDecrement($lhs); }
     ;
@@ -1333,11 +1392,6 @@ AssignmentExpression
     | ArrowFunction[pass] { $$ = $pass; }
     | LexOf LeftHandSideAssignment[assignment] AssignmentExpression[rhs] { $assignment->SetRight($rhs); $$ = $assignment; }
     ;
-
-AssignmentExpressionOpt
-    : AssignmentExpression[pass] { $$ = $pass; }
-    | LexOf { $$ = NULL; }
-    ;
 /* }}} */
 /* 12.15 Comma Operator ( , ) {{{ */
 Expression
@@ -1586,7 +1640,7 @@ ForStatementInitializer
     ;
 
 ForInStatementInitializer
-    : LexLet LexOf RubyBlockExpression[pass] { $$ = $pass; }
+    : LexLet LexOf BracedExpression[pass] { $$ = $pass; }
     | LexLet LexOf IndirectExpression[pass] { $$ = $pass; }
     | LexLet LexOf Var_ LexBind ForBinding[binding] { $$ = CYNew CYForVariable($binding); }
     | ForDeclaration[pass] { $$ = $pass; }
@@ -1780,7 +1834,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); */ }
     ;
@@ -1975,20 +2029,49 @@ ExportSpecifier
 @begin C
 /* Cycript (C): Type Encoding {{{ */
 TypeSignifier
-    : IdentifierType[identifier] { $$ = CYNew CYTypedIdentifier(@identifier, $identifier); }
+    : IdentifierType[name] { $$ = CYNew CYTypedName(@name, $name); }
+    | StringLiteral[name] { $$ = CYNew CYTypedName(@name, $name); }
+    | NumericLiteral[name] { $$ = CYNew CYTypedName(@name, $name); }
     | "(" "*" TypeQualifierRightOpt[typed] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypePointerTo($$->modifier_); }
     ;
 
+TypeSignifierNone
+    : { $$ = CYNew CYTypedName(@$); }
+    ;
+
 TypeSignifierOpt
     : TypeSignifier[pass] { $$ = $pass; }
-    | { $$ = CYNew CYTypedIdentifier(@$); }
+    | TypeSignifierNone[pass] { $$ = $pass; }
+    ;
+
+Restrict
+    : "__restrict"
+    | "restrict"
+    ;
+
+RestrictOpt
+    : Restrict
+    |
+    ;
+
+ParameterModifier
+    : "throw" "(" ")"
+    ;
+
+ParameterModifierOpt
+    : ParameterModifier
+    |
+    ;
+
+ParameterTail
+    : TypedParameterListOpt[formal] ")" ParameterModifierOpt { $$ = CYNew CYTypeFunctionWith($formal->variadic_, $formal->parameters_); }
     ;
 
 SuffixedType
-    : SuffixedTypeOpt[typed] "[" NumericLiteral[size] "]" { $$ = $typed; $$->modifier_ = CYNew CYTypeArrayOf($size, $$->modifier_); }
-    | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameterListOpt[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); }
-    | TypeSignifier[typed] "(" TypedParameterListOpt[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeFunctionWith($parameters, $$->modifier_); }
-    | "("[parenthesis] TypedParameterListOpt[parameters] ")" { $$ = CYNew CYTypedIdentifier(@parenthesis); $$->modifier_ = CYNew CYTypeFunctionWith($parameters, $$->modifier_); }
+    : SuffixedTypeOpt[typed] "[" RestrictOpt NumericLiteral[size] "]" { $$ = $typed; $$->modifier_ = CYNew CYTypeArrayOf($size, $$->modifier_); }
+    | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameters[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); }
+    | TypeSignifier[typed] "(" ParameterTail[modifier] { $$ = $typed; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
+    | "("[parenthesis] ParameterTail[modifier] { $$ = CYNew CYTypedName(@parenthesis); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
     ;
 
 SuffixedTypeOpt
@@ -2015,6 +2098,7 @@ TypeQualifierRight
     | PrefixedType[pass] { $$ = $pass; }
     | "const" TypeQualifierRightOpt[typed] { $$ = $typed; $$->modifier_ = CYNew CYTypeConstant($$->modifier_); }
     | "volatile" TypeQualifierRightOpt[typed] { $$ = $typed; $$->modifier_ = CYNew CYTypeVolatile($$->modifier_); }
+    | Restrict TypeQualifierRightOpt[typed] { $$ = $typed; }
     ;
 
 TypeQualifierRightOpt
@@ -2023,48 +2107,97 @@ TypeQualifierRightOpt
     ;
 
 IntegerType
-    : "int" { $$ = CYNew CYTypeVariable("int"); }
-    | "unsigned" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeUnsigned($specifier); }
-    | "signed" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeSigned($specifier); }
-    | "long" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeLong($specifier); }
-    | "short" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeShort($specifier); }
+    : "int" { $$ = CYNew CYTypeIntegral(CYTypeNeutral); }
+    | "unsigned" IntegerTypeOpt[integral] { $$ = $integral->Unsigned(); if ($$ == NULL) CYERR(@1, "incompatible unsigned"); }
+    | "signed" IntegerTypeOpt[integral] { $$ = $integral->Signed(); if ($$ == NULL) CYERR(@1, "incompatible signed"); }
+    | "long" IntegerTypeOpt[integral] { $$ = $integral->Long(); if ($$ == NULL) CYERR(@1, "incompatible long"); }
+    | "short" IntegerTypeOpt[integral] { $$ = $integral->Short(); if ($$ == NULL) CYERR(@1, "incompatible short"); }
     ;
 
 IntegerTypeOpt
     : IntegerType[pass] { $$ = $pass; }
-    | { $$ = CYNew CYTypeVariable("int"); }
+    | { $$ = CYNew CYTypeIntegral(CYTypeNeutral); }
     ;
 
 StructFieldListOpt
-    : TypedIdentifierMaybe[typed] ";" StructFieldListOpt[next] { $$ = CYNew CYTypeStructField($typed, $next); }
+    : TypedIdentifierField[typed] ";" StructFieldListOpt[next] { $$ = CYNew CYTypeStructField($typed, $typed->name_, $next); }
     | { $$ = NULL; }
     ;
 
+IntegerNumber
+    : NumericLiteral[pass] { $$ = $pass; }
+    | "-" NumericLiteral[positive] { $$ = $positive; $$->value_ = -$$->value_; }
+    ;
+
+EnumConstantListOpt_
+    : "," EnumConstantListOpt[pass] { $$ = $pass; }
+    | { $$ = NULL; }
+    ;
+
+EnumConstantListOpt
+    : IdentifierType[name] "=" IntegerNumber[value] EnumConstantListOpt_[next] { $$ = CYNew CYEnumConstant($name, $value, $next); }
+    | { $$ = NULL; }
+    ;
+
+TypeSigning
+    : { $$ = CYTypeNeutral; }
+    | "signed" { $$ = CYTypeSigned; }
+    | "unsigned" { $$ = CYTypeUnsigned; }
+    ;
+
 PrimitiveType
     : IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
     | IntegerType[pass] { $$ = $pass; }
-    | "char" { $$ = CYNew CYTypeVariable("char"); }
-    | "signed" "char" { $$ = CYNew CYTypeSigned(CYNew CYTypeVariable("char")); }
-    | "unsigned" "char" { $$ = CYNew CYTypeUnsigned(CYNew CYTypeVariable("char")); }
-    | "struct" IdentifierTypeOpt[name] "{" StructFieldListOpt[fields] "}" { $$ = CYNew CYTypeStruct($name, $fields); }
+    | TypeSigning[signing] "char" { $$ = CYNew CYTypeCharacter($signing); }
+    | TypeSigning[signing] "__int128" { $$ = CYNew CYTypeInt128($signing); }
+    ;
+
+PrimitiveReference
+    : PrimitiveType[pass] { $$ = $pass; }
+    | "struct" IdentifierType[name] { $$ = CYNew CYTypeReference(CYTypeReferenceStruct, $name); }
+    | "enum" IdentifierType[name] { $$ = CYNew CYTypeReference(CYTypeReferenceEnum, $name); }
+    | "struct" AutoComplete { driver.mode_ = CYDriver::AutoStruct; YYACCEPT; }
+    | "enum" AutoComplete { driver.mode_ = CYDriver::AutoEnum; YYACCEPT; }
     ;
 
 TypedIdentifierMaybe
-    : TypeQualifierLeftOpt[modifier] PrimitiveType[specifier] TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = $specifier; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
-    | TypeQualifierLeft[modifier] "void" TypeQualifierRight[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
+    : TypeQualifierLeft[modifier] "void" TypeQualifierRight[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
     | "void" TypeQualifierRight[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); }
+    | TypeQualifierLeftOpt[modifier] PrimitiveReference[specifier] TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = $specifier; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
     ;
 
 TypedIdentifierYes
-    : TypedIdentifierMaybe[typed] { if ($typed->identifier_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; }
+    : TypedIdentifierMaybe[typed] { if ($typed->name_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; }
     ;
 
 TypedIdentifierNo
-    : TypedIdentifierMaybe[typed] { if ($typed->identifier_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; }
+    : TypedIdentifierMaybe[typed] { if ($typed->name_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; }
+    ;
+
+TypedIdentifierTagged
+    : TypeQualifierLeftOpt[modifier] "struct" "{" StructFieldListOpt[fields] "}" TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeStruct(NULL, CYNew CYStructTail($fields)); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
+    | TypeQualifierLeftOpt[modifier] "enum" ":" PrimitiveType[specifier] "{" EnumConstantListOpt[constants] "}" TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeEnum(NULL, $specifier, $constants); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
+    ;
+
+TypedIdentifierField
+    : TypedIdentifierYes[pass] { $$ = $pass; }
+    | TypedIdentifierTagged[typed] { if ($typed->name_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; }
+    ;
+
+TypedIdentifierEncoding
+    : TypedIdentifierNo[pass] { $$ = $pass; }
+    | TypedIdentifierTagged[typed] { if ($typed->name_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; }
+    | "void" TypeSignifierNone[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); }
+    ;
+
+TypedIdentifierDefinition
+    : TypedIdentifierYes[pass] { $$ = $pass; }
+    | TypeQualifierLeftOpt[modifier] "struct" IdentifierTypeOpt[name] "{" StructFieldListOpt[fields] "}" TypeQualifierRightOpt[typed] { if ($typed->name_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; $$->specifier_ = CYNew CYTypeStruct($name, CYNew CYStructTail($fields)); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
+    | "void" TypeSignifier[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); }
     ;
 
 PrimaryExpression
-    : "@encode" "(" TypedIdentifierMaybe[typed] ")" { $$ = CYNew CYEncodedType($typed); }
+    : "@encode" "(" TypedIdentifierEncoding[typed] ")" { $$ = CYNew CYEncodedType($typed); }
     ;
 /* }}} */
 @end
@@ -2078,7 +2211,7 @@ ClassSuperOpt
     ;
 
 ImplementationFieldListOpt
-    : TypedIdentifierMaybe[typed] ";" ImplementationFieldListOpt[next] { $$ = CYNew CYImplementationField($typed, $next); }
+    : TypedIdentifierField[typed] ";" ImplementationFieldListOpt[next] { $$ = CYNew CYImplementationField($typed, $typed->name_, $next); }
     | { $$ = NULL; }
     ;
 
@@ -2089,11 +2222,11 @@ MessageScope
 
 TypeOpt
     : "(" TypedIdentifierNo[type] ")" { $$ = $type; }
-    | { $$ = CYNew CYTypedIdentifier(CYNew CYTypeVariable("id")); }
+    | { $$ = CYNew CYType(CYNew CYTypeVariable("id")); }
     ;
 
 MessageParameter
-    : Word[tag] ":" TypeOpt[type] BindingIdentifier[identifier] { $type->identifier_ = $identifier; $$ = CYNew CYMessageParameter($tag, $type); }
+    : Word[tag] ":" TypeOpt[type] BindingIdentifier[identifier] { $$ = CYNew CYMessageParameter($tag, $type, $identifier); }
     ;
 
 MessageParameterList
@@ -2102,12 +2235,12 @@ MessageParameterList
 
 MessageParameterListOpt
     : MessageParameterList[pass] { $$ = $pass; }
-    | { $$ = NULL; }
+    | TypedParameterList_[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); /*XXX*/ if ($formal->parameters_ != NULL) CYERR(@$, "temporarily unsupported"); $$ = NULL; }
     ;
 
 MessageParameters
     : MessageParameterList[pass] { $$ = $pass; }
-    | Word[tag] { $$ = CYNew CYMessageParameter($tag, NULL); }
+    | Word[tag] { $$ = CYNew CYMessageParameter($tag); }
     ;
 
 ClassMessageDeclaration
@@ -2220,15 +2353,29 @@ BoxableExpression
     | BooleanLiteral[pass] { $$ = $pass; }
     | NumericLiteral[pass] { $$ = $pass; }
     | StringLiteral[pass] { $$ = $pass; }
-    | ArrayLiteral[pass] { $$ = $pass; }
-    | ObjectLiteral[pass] { $$ = $pass; }
     | CoverParenthesizedExpressionAndArrowParameterList[pass] { $$ = $pass; }
     | "YES" { $$ = CYNew CYTrue(); }
     | "NO" { $$ = CYNew CYFalse(); }
     ;
 
+KeyValuePairList_
+    : "," KeyValuePairListOpt[next] { $$ = $next; }
+    | { $$ = NULL; }
+
+KeyValuePairList
+    : AssignmentExpression[key] ":" AssignmentExpression[value] KeyValuePairList_[next] { $$ = CYNew CYObjCKeyValue($key, $value, $next); }
+    ;
+
+KeyValuePairListOpt
+    : KeyValuePairList[pass] { $$ = $pass; }
+    | LexOf { $$ = NULL; }
+    ;
+
 PrimaryExpression
     : "@" BoxableExpression[expression] { $$ = CYNew CYBox($expression); }
+    | "@" "[" ElementListOpt[elements] "]" { $$ = CYNew CYObjCArray($elements); }
+    | "@" "{" KeyValuePairListOpt[pairs] "}" { $$ = CYNew CYObjCDictionary($pairs); }
+
     | "@YES" { $$ = CYNew CYBox(CYNew CYTrue()); }
     | "@NO" { $$ = CYNew CYBox(CYNew CYFalse()); }
     | "@true" { $$ = CYNew CYBox(CYNew CYTrue()); }
@@ -2271,21 +2418,40 @@ MemberAccess
 /* Cycript (C): Lambda Expressions {{{ */
 TypedParameterList_
     : "," TypedParameterList[parameters] { $$ = $parameters; }
-    | { $$ = NULL; }
+    | { $$ = CYNew CYTypedFormal(false); }
     ;
 
 TypedParameterList
-    : TypedIdentifierMaybe[typed] TypedParameterList_[next] { $$ = CYNew CYTypedParameter($typed, $next); }
+    : TypedIdentifierMaybe[typed] TypedParameterList_[formal] { CYIdentifier *identifier; if ($typed->name_ == NULL) identifier = NULL; else { identifier = $typed->name_->Identifier(); if (identifier == NULL) CYERR($typed->location_, "invalid identifier"); } $$ = $formal; $$->parameters_ = CYNew CYTypedParameter($typed, identifier, $$->parameters_); }
+    | "..." { $$ = CYNew CYTypedFormal(true); }
     ;
 
 TypedParameterListOpt
     : TypedParameterList[pass] { $$ = $pass; }
-    | "void" { $$ = NULL; }
-    | { $$ = NULL; }
+    | "void" { $$ = CYNew CYTypedFormal(false); }
+    | { $$ = CYNew CYTypedFormal(false); }
+    ;
+
+TypedParameters
+    : TypedParameterListOpt[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); $$ = $formal->parameters_; }
+    ;
+
+PrimaryExpression
+    : "[" LexOf "&" "]" "(" TypedParameters[parameters] ")" "->" TypedIdentifierNo[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); }
+    ;
+/* }}} */
+/* Cycript (C): Structure Definitions {{{ */
+IdentifierNoOf
+    : "struct" NewLineOpt { $$ = CYNew CYIdentifier("struct"); }
+    ;
+
+Statement__
+    : "struct" NewLineNot IdentifierType[name] "{" StructFieldListOpt[fields] "}" { $$ = CYNew CYStructDefinition($name, CYNew CYStructTail($fields)); }
     ;
 
 PrimaryExpression
-    : "[" LexOf "&" "]" "(" TypedParameterListOpt[parameters] ")" "->" TypedIdentifierMaybe[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); }
+    : "(" LexOf "struct" NewLineOpt IdentifierType[name] TypeQualifierRightOpt[typed] ")" { $typed->specifier_ = CYNew CYTypeReference(CYTypeReferenceStruct, $name); $$ = CYNew CYTypeExpression($typed); }
+    | "(" LexOf "struct" NewLineOpt AutoComplete { driver.mode_ = CYDriver::AutoStruct; YYACCEPT; }
     ;
 /* }}} */
 /* Cycript (C): Type Definitions {{{ */
@@ -2294,7 +2460,7 @@ IdentifierNoOf
     ;
 
 TypeDefinition
-    : "typedef" NewLineNot TypedIdentifierYes[typed] TerminatorHard { $$ = CYNew CYTypeDefinition($typed); }
+    : "typedef" NewLineNot TypedIdentifierDefinition[typed] TerminatorHard { CYIdentifier *identifier; if ($typed->name_ == NULL) identifier = NULL; else { identifier = $typed->name_->Identifier(); if (identifier == NULL) CYERR($typed->location_, "invalid identifier"); } $$ = CYNew CYTypeDefinition($typed, identifier); }
     ;
 
 Statement__
@@ -2302,7 +2468,7 @@ Statement__
     ;
 
 PrimaryExpression
-    : "(" LexOf "typedef" NewLineOpt TypedIdentifierNo[typed] ")" { $$ = CYNew CYTypeExpression($typed); }
+    : "(" LexOf "typedef" NewLineOpt TypedIdentifierEncoding[typed] ")" { $$ = CYNew CYTypeExpression($typed); }
     ;
 /* }}} */
 /* Cycript (C): extern "C" {{{ */
@@ -2311,7 +2477,7 @@ IdentifierNoOf
     ;
 
 ExternCStatement
-    : TypedIdentifierYes[typed] TerminatorHard { $$ = CYNew CYExternal(CYNew CYString("C"), $typed); }
+    : TypedIdentifierField[typed] TerminatorHard { CYIdentifier *identifier; if ($typed->name_ == NULL) identifier = NULL; else { identifier = $typed->name_->Identifier(); if (identifier == NULL) CYERR($typed->location_, "invalid identifier"); } $$ = CYNew CYExternalDefinition(CYNew CYString("C"), $typed, identifier); }
     | TypeDefinition[pass] { $$ = $pass; }
     ;
 
@@ -2325,11 +2491,18 @@ ExternC
     | ExternCStatement[pass] { $$ = $pass; }
     ;
 
+ABI
+    : StringLiteral[abi] { if (strcmp($abi->Value(), "C") != 0) CYERR(@abi, "unknown extern binding"); }
+    ;
+
 Statement__
-    : "extern" NewLineNot StringLiteral[abi] { if (strcmp($abi->Value(), "C") != 0) CYERR(@abi, "unknown extern binding"); } ExternC[pass] { $$ = $pass; }
+    : "extern" NewLineNot ABI[abi] ExternC[pass] { $$ = $pass; }
     ;
-/* }}} */
 
+PrimaryExpression
+    : "(" LexOf "extern" NewLineOpt ABI[abi] TypedIdentifierField[typed] ")" { $$ = CYNew CYExternalExpression(CYNew CYString("C"), $typed, $typed->name_); }
+    ;
+/* }}} */
 @end
 
 @begin E4X
@@ -2549,16 +2722,23 @@ 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: Subscript Access {{{ */
+MemberAccess
+    : "." "[" AssignmentExpression[property] "]" { $$ = CYNew CYSubscriptMember(NULL, $property); }
+    ;
+/* }}} */
+
+/* JavaScript FTW: Java "Anonymous Inner Classes" {{{ */
+BracedParameter
+    : "{" PropertyDefinitionListOpt[properties] "}" { $$ = CYNew CYExtend(NULL, $properties); }
+    ;
+/* }}} */
+
 /* JavaScript FTW: Ruby Blocks {{{ */
 RubyProcParameterList_
     : "," RubyProcParameterList[parameters] { $$ = $parameters; }
@@ -2580,22 +2760,34 @@ RubyProcParametersOpt
     | { $$ = NULL; }
     ;
 
-RubyProcExpression
-    : "{" RubyProcParametersOpt[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyProc($parameters, $code); }
+BracedParameter
+    : ";{" RubyProcParametersOpt[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyBlock(NULL, CYNew CYRubyProc($parameters, $code)); }
     ;
 
 PrimaryExpression
     : "{" RubyProcParameters[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyProc($parameters, $code); }
     ;
 
-RubyBlockExpression_
+BracedExpression_
     : AccessExpression[pass] LexNewLineOrOpt { $$ = $pass; }
-    | RubyBlockExpression_[lhs] RubyProcExpression[rhs] LexNewLineOrOpt { $$ = CYNew CYRubyBlock($lhs, $rhs); }
+    | BracedExpression_[lhs] { if (!$lhs->IsNew()) CYMAP(OpenBrace_, OpenBrace); } BracedParameter[rhs] LexNewLineOrOpt { $rhs->SetLeft($lhs); $$ = $rhs; }
     ;
 
-RubyBlockExpression
-    : RubyBlockExpression_[pass] "\n" { $$ = $pass; }
-    | RubyBlockExpression_[pass] { $$ = $pass; }
+BracedExpression
+    : BracedExpression_[pass] "\n" { $$ = $pass; }
+    | BracedExpression_[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()); }
     ;
 /* }}} */