%token STRUCT
%token SWITCH
%token THIS
-%token THROW
+%token THROW
%token TRUE
%token TRY
%token TYPEOF
%token WHEN
%token INTERPOLATED_STRING
%token INTERPOLATED_STRING_END
+%token THROW_EXPR
/* C# keywords which are not really keywords */
%token GET
%token GENERIC_DIMENSION
%token DEFAULT_COLON
%token OPEN_BRACKET_EXPR
+%token OPEN_PARENS_DECONSTRUCT
// Make the parser go into eval mode parsing (statements and compilation units).
%token EVAL_STATEMENT_PARSER
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod);
lbag.AddLocation ($$, GetLocation($2));
}
+ | identifier_inside_body COLON OUT named_argument_expr_or_out_variable_declaration
+ {
+ if (lang_version <= LanguageVersion.V_3)
+ FeatureIsNotAvailable (GetLocation ($1), "named argument");
+
+ var lt = (LocatedToken) $1;
+ $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, Argument.AType.Out);
+ lbag.AddLocation ($$, GetLocation($2));
+ }
;
named_argument_expr
: expression_or_error
-// | declaration_expression
+ ;
+
+named_argument_expr_or_out_variable_declaration
+ : expression_or_error
+ | out_variable_declaration
;
opt_named_modifier
{
$$ = Argument.AType.Ref;
}
- | OUT
- {
- $$ = Argument.AType.Out;
- }
;
opt_class_member_declarations
field_declaration
: opt_attributes
opt_modifiers
- member_type IDENTIFIER
+ ref_member_type IDENTIFIER
{
lexer.parsing_generic_declaration = false;
// Was added earlier in the case of body being eof for full ast
}
- method_body_expression_block
+ method_body
{
Method method = (Method) $1;
method.Block = (ToplevelBlock) $3;
}
;
+ref_member_type
+ : member_type
+ {
+ $$ = $1;
+ }
+ | REF
+ {
+ lexer.parsing_generic_declaration = true;
+ }
+ type
+ {
+ if (lang_version < LanguageVersion.V_7) {
+ FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+ }
+
+ $$ = new ReferenceTypeExpr ((FullNamedExpression) $3, GetLocation ($1));
+ }
+ ;
+
method_header
: opt_attributes
opt_modifiers
- member_type
+ ref_member_type
method_declaration_name OPEN_PARENS
{
valid_param_mod = ParameterModifierType.All;
}
| opt_attributes
opt_modifiers
- member_type
+ ref_member_type
modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
MemberName name = (MemberName) $5;
}
| opt_attributes
opt_modifiers
- member_type
+ ref_member_type
method_declaration_name error
{
Error_SyntaxError (yyToken);
}
;
-method_body_expression_block
- : method_body
- | expression_block
- ;
-
method_body
: block
+ | expression_block
| SEMICOLON { $$ = null; }
;
+destructor_body
+ : method_body
+ ;
+
+constructor_body
+ : block_prepared
+ | SEMICOLON { current_block = null; $$ = null; }
+ | ARROW
+ {
+ if (lang_version < LanguageVersion.V_7) {
+ FeatureIsNotAvailable (GetLocation ($1), "expression body constructor");
+ }
+
+ ++lexer.parsing_block;
+ }
+ expression SEMICOLON
+ {
+ lexer.parsing_block = 0;
+ current_block.AddStatement (new ContextualReturn ((Expression) $3));
+ var b = end_block (GetLocation ($4));
+ b.IsCompilerGenerated = true;
+ $$ = b;
+ current_block = null;
+ }
+ ;
+
expression_block
: ARROW
{
++lexer.parsing_block;
start_block (GetLocation ($1));
}
- expression SEMICOLON
+ lambda_arrow_expression SEMICOLON
{
lexer.parsing_block = 0;
current_block.AddStatement (new ContextualReturn ((Expression) $3));
property_declaration
: opt_attributes
opt_modifiers
- member_type
+ ref_member_type
member_declaration_name
{
lexer.parsing_generic_declaration = false;
if (doc_support)
current_property.DocComment = ConsumeStoredComment ();
+
+ if ($3 is ReferenceTypeExpr) {
+ if (current_property.Get == null) {
+ report.Error (8146, GetLocation ($4), "`{0}': property and indexer which return by reference must have a get accessor", current_property.GetSignatureForError ());
+ }
+
+ if (current_property.Set != null) {
+ report.Error (8147, GetLocation ($4), "`{0}': property and indexer which return by reference cannot have set accessors", current_property.GetSignatureForError ());
+ }
+ }
}
CLOSE_BRACE
{
}
| opt_attributes
opt_modifiers
- member_type
+ ref_member_type
member_declaration_name
{
lexer.parsing_generic_declaration = false;
indexer_declaration
: opt_attributes opt_modifiers
- member_type indexer_declaration_name OPEN_BRACKET
+ ref_member_type indexer_declaration_name OPEN_BRACKET
{
valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue;
}
if (doc_support)
current_property.DocComment = ConsumeStoredComment ();
+
+ if ($3 is ReferenceTypeExpr) {
+ if (current_property.Get == null) {
+ report.Error (8146, GetLocation ($4), "`{0}': property and indexer which return by reference must have a get accessor", current_property.GetSignatureForError ());
+ }
+
+ if (current_property.Set != null) {
+ report.Error (8147, GetLocation ($4), "`{0}': property and indexer which return by reference cannot have set accessors", current_property.GetSignatureForError ());
+ }
+ }
current_property = null;
}
;
accessor_body
- : block
+ : block
+ | expression_block
| SEMICOLON
{
// TODO: lbag
}
;
+
interface_declaration
: opt_attributes
opt_modifiers
: opt_attributes opt_modifiers operator_declarator
{
}
- method_body_expression_block
+ method_body
{
OperatorDeclaration decl = (OperatorDeclaration) $3;
if (decl != null) {
}
;
-constructor_body
- : block_prepared
- | SEMICOLON { current_block = null; $$ = null; }
- ;
-
opt_constructor_initializer
: /* Empty */
| constructor_initializer
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters;
}
- IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body
+ IDENTIFIER OPEN_PARENS CLOSE_PARENS destructor_body
{
var lt = (LocatedToken) $5;
if (lt.Value != current_container.MemberName.Name){
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null);
lbag.AddLocation ($$, GetLocation ($1));
}
- | COMMA IDENTIFIER ASSIGN
- {
- ++lexer.parsing_block;
- }
- event_variable_initializer
+ | COMMA IDENTIFIER ASSIGN event_variable_initializer
{
- --lexer.parsing_block;
var lt = (LocatedToken) $2;
- $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5);
+ $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $4);
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3));
}
;
if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) {
report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer",
current_event_field.GetSignatureForError ());
- }
+ }
+
+ ++lexer.parsing_block;
+ current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters;
+ start_block (lexer.Location);
}
variable_initializer
{
$$ = $2;
+
+ --lexer.parsing_block;
+ end_block (lexer.Location);
+ current_local_parameters = null;
}
;
report.Error (73, lexer.Location, "An add or remove accessor must have a body");
$$ = null;
}
- | block;
+ | block
+ | expression_block
;
attributes_without_members
: opt_attributes
opt_modifiers
DELEGATE
- member_type type_declaration_name
+ ref_member_type type_declaration_name
OPEN_PARENS
{
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue;
$$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | OPEN_PARENS tuple_elements CLOSE_PARENS opt_nullable
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+ if (a.Item1.Count < 2) {
+ report.Error (8124, GetLocation ($1), "Tuple must contain at least two elements");
+ }
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+
+ if ($4 != null)
+ $$ = new ComposedCast ((FullNamedExpression) $$, (ComposedTypeSpecifier) $4);
+ }
+ ;
+
+tuple_elements
+ : tuple_element tuple_element_name
+ {
+ var type_args = new TypeArguments ();
+ type_args.Add ((FullNamedExpression) $1);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_elements COMMA tuple_element tuple_element_name
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
+tuple_element_name
+ : /* empty */
+ | IDENTIFIER
+ ;
+
+tuple_element
+ : parameter_type
;
void_invalid
literal
: boolean_literal
+ | tuple_literal
| LITERAL
| NULL { $$ = new NullLiteral (GetLocation ($1)); }
;
| FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); }
;
+tuple_literal
+ : OPEN_PARENS tuple_literal_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ $$ = new TupleLiteral ((List<TupleLiteralElement>)$2, GetLocation ($1));
+ }
+ ;
+
+tuple_literal_elements
+ : tuple_literal_element COMMA tuple_literal_element
+ {
+ $$ = new List<TupleLiteralElement> () {
+ (TupleLiteralElement) $1, (TupleLiteralElement) $3
+ };
+ }
+ | tuple_literal_elements COMMA tuple_literal_element
+ {
+ var list = (List<TupleLiteralElement>)$1;
+ list.Add ((TupleLiteralElement) $3);
+ }
+ ;
+
+tuple_literal_element
+ : expression
+ {
+ $$ = new TupleLiteralElement ((Expression) $1);
+ }
+ | IDENTIFIER COLON expression
+ {
+ var lt = (LocatedToken) $1;
+ $$ = new TupleLiteralElement (lt.Value, (Expression) $3, lt.Location);
+ }
+ ;
+
interpolated_string
: INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END
{
$$ = new Argument ((Expression) $2, Argument.AType.Ref);
lbag.AddLocation ($$, GetLocation ($1));
}
- | REF declaration_expression
- {
- $$ = new Argument ((Expression) $2, Argument.AType.Ref);
- }
| OUT variable_reference
{
$$ = new Argument ((Expression) $2, Argument.AType.Out);
lbag.AddLocation ($$, GetLocation ($1));
}
- | OUT declaration_expression
+ | OUT out_variable_declaration
{
$$ = new Argument ((Expression) $2, Argument.AType.Out);
}
}
;
-declaration_expression
- : OPEN_PARENS declaration_expression CLOSE_PARENS
- {
- $$ = new ParenthesizedExpression ((Expression) $2, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3));
- }
-/*
- | CHECKED open_parens_any declaration_expression CLOSE_PARENS
- {
- $$ = new CheckedExpr ((Expression) $3, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
- }
- | UNCHECKED open_parens_any declaration_expression CLOSE_PARENS
- {
- $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1));
- lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4));
- }
-*/
- | variable_type identifier_inside_body
+out_variable_declaration
+ : variable_type identifier_inside_body
{
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($1), "declaration expression");
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "out variable declaration");
var lt = (LocatedToken) $2;
var lv = new LocalVariable (current_block, lt.Value, lt.Location);
current_block.AddLocalName (lv);
$$ = new DeclarationExpression ((FullNamedExpression) $1, lv);
}
- | variable_type identifier_inside_body ASSIGN expression
- {
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($1), "declaration expression");
-
- var lt = (LocatedToken) $2;
- var lv = new LocalVariable (current_block, lt.Value, lt.Location);
- current_block.AddLocalName (lv);
- $$ = new DeclarationExpression ((FullNamedExpression) $1, lv) {
- Initializer = (Expression) $4
- };
- }
;
variable_reference
$$ = new ArrayCreation ((FullNamedExpression) $2, (List<Expression>) $4,
new ComposedTypeSpecifier (((List<Expression>) $4).Count, GetLocation ($3)) {
Next = (ComposedTypeSpecifier) $6
- }, (ArrayInitializer) $7, GetLocation ($1));
+ }, (ArrayInitializer) $7, GetLocation ($1)) {
+ NoEmptyInterpolation = true
+ };
+
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5));
}
| NEW new_expr_type rank_specifiers opt_array_initializer
$$ = new Await ((Expression) $2, GetLocation ($1));
}
+ | THROW_EXPR prefixed_unary_expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (lexer.Location, "throw expression");
+
+ $$ = new ThrowExpression ((Expression) $2, GetLocation ($1));
+ }
| BANG error
{
Error_SyntaxError (yyToken);
$$ = new Unary (Unary.Operator.AddressOf, null, GetLocation ($1));
}
- ;
multiplicative_expression
: prefixed_unary_expression
}
| additive_expression IS pattern_type_expr opt_identifier
{
- var is_expr = new Is ((Expression) $1, (Expression) $3, GetLocation ($2));
+ var is_expr = new Is ((Expression) $1, ((FullNamedExpression) $3), GetLocation ($2));
if ($4 != null) {
- if (lang_version != LanguageVersion.Experimental)
- FeatureIsNotAvailable (GetLocation ($4), "type pattern matching");
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($4), "pattern matching");
var lt = (LocatedToken) $4;
- is_expr.Variable = new LocalVariable (current_block, lt.Value, lt.Location);
- current_block.AddLocalName (is_expr.Variable);
+ var lv = new LocalVariable (current_block, lt.Value, lt.Location);
+ is_expr.Variable = lv;
+ current_block.AddLocalName (lv);
}
$$ = is_expr;
{
$$ = new WildcardPattern (GetLocation ($1));
}
- | pattern_expr_invocation
+/* | pattern_expr_invocation */
| pattern_property
;
+/*
pattern_expr_invocation
: type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS
{
$$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2));
}
;
+*/
pattern_property
: type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE
}
;
+/*
opt_pattern_list
- : /* empty */
+ : // empty
{
$$ = new Arguments (0);
}
}
;
+
pattern_argument
: pattern
{
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
}
;
+*/
shift_expression
: additive_expression
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2));
lbag.AddLocation ($$, GetLocation ($4));
}
+ | null_coalescing_expression INTERR expression COLON THROW prefixed_unary_expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (lexer.Location, "throw expression");
+
+ var expr = new ThrowExpression ((Expression) $6, GetLocation ($5));
+ $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, expr, GetLocation ($2));
+ lbag.AddLocation ($$, GetLocation ($4));
+ }
| null_coalescing_expression INTERR expression error
{
Error_SyntaxError (yyToken);
$$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
lbag.AddLocation ($$, GetLocation ($2));
}
+ | OPEN_PARENS_DECONSTRUCT deconstruct_exprs CLOSE_PARENS ASSIGN expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var exprs = (List<Expression>) $2;
+ $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4));
+ }
+ ;
+
+deconstruct_exprs
+ : expression COMMA expression
+ {
+ $$ = new List<Expression> () {
+ (Expression) $1,
+ (Expression) $3
+ };
+ }
+ | deconstruct_exprs COMMA expression
+ {
+ var src = (List<Expression>) $1;
+ src.Add ((Expression) $3);
+ $$ = src;
+ }
;
lambda_parameter_list
: {
start_block (Location.Null);
}
- expression // All expressions must handle error or current block won't be restored and breaking ast completely
+ lambda_arrow_expression // All expressions must handle error or current block won't be restored and breaking ast completely
{
Block b = end_block (Location.Null);
b.IsCompilerGenerated = true;
}
;
+lambda_arrow_expression
+ : expression
+ | reference_expression
+ ;
+
expression_or_error
: expression
| error
variable_type_simple
: type_name_expression opt_nullable
{
- // Ok, the above "primary_expression" is there to get rid of
- // both reduce/reduce and shift/reduces in the grammar, it should
- // really just be "type_name". If you use type_name, a reduce/reduce
- // creeps up. If you use namespace_or_type_name (which is all we need
- // really) two shift/reduces appear.
- //
-
- // So the super-trick is that primary_expression
- // can only be either a SimpleName or a MemberAccess.
- // The MemberAccess case arises when you have a fully qualified type-name like :
- // Foo.Bar.Blah i;
- // SimpleName is when you have
- // Blah i;
-
var expr = (ATypeNameExpression) $1;
if ($2 == null) {
if (expr.Name == "var" && expr is SimpleName)
$$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | tuple_type opt_nullable
+ {
+ if ($2 == null)
+ $$ = $1;
+ else
+ $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2);
+ }
| void_invalid
;
-
+
+tuple_type
+ : OPEN_PARENS tuple_type_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+ }
+ ;
+
+tuple_type_elements
+ : variable_type IDENTIFIER /* opt_identifier */ COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var type_args = new TypeArguments ();
+
+ type_args.Add ((FullNamedExpression) $1);
+ type_args.Add ((FullNamedExpression) $4);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+ lt = (LocatedToken) $5;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_type_elements COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
pointer_stars
: pointer_star
| pointer_star pointer_stars
current_variable = null;
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($7));
}
+ | REF variable_type identifier_inside_body
+ {
+ if (lang_version < LanguageVersion.V_7) {
+ FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+ }
+
+ var lt = (LocatedToken) $3;
+ var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ByRef, lt.Location);
+ current_block.AddLocalName (li);
+ current_variable = new BlockVariable ((FullNamedExpression) $2, li);
+ }
+ opt_local_variable_initializer opt_variable_declarators SEMICOLON
+ {
+ $$ = current_variable;
+ current_variable = null;
+ if ($5 != null) {
+ lbag.AddLocation ($$, PopLocation (), GetLocation ($7));
+ } else {
+ report.Error (8174, GetLocation ($3), "A declaration of a by-reference variable must have an initializer");
+ lbag.AddLocation ($$, GetLocation ($7));
+ }
+ }
;
opt_local_variable_initializer
report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type");
$$ = new StackAlloc ((Expression) $2, null, GetLocation ($1));
}
+ | reference_expression
+ ;
+
+reference_expression
+ : REF expression
+ {
+ if (lang_version < LanguageVersion.V_7) {
+ FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+ }
+
+ $$ = new ReferenceExpression ((Expression) $2, GetLocation ($1));
+ }
;
expression_statement
lbag.AddLocation ($$, GetLocation ($3));
}
*/
+
+ | CASE pattern_type_expr IDENTIFIER COLON
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "pattern matching");
+
+// $$ = new SwitchLabel ((FullNamedExpression) $2), GetLocation ($1)) {
+// PatternMatching = true
+// };
+
+ throw new NotImplementedException ("type pattern matching");
+ }
| DEFAULT_COLON
{
$$ = new SwitchLabel (null, GetLocation ($1));
$$ = new Return ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3));
}
+ | RETURN reference_expression SEMICOLON
+ {
+ $$ = new Return ((Expression) $2, GetLocation ($1));
+ lbag.AddStatement ($$, GetLocation ($3));
+ }
| RETURN expression error
{
Error_SyntaxError (yyToken);
;
throw_statement
- : THROW opt_expression SEMICOLON
+ : THROW expression SEMICOLON
{
$$ = new Throw ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3));
}
+ | THROW SEMICOLON
+ {
+ $$ = new Throw (null, GetLocation ($1));
+ lbag.AddStatement ($$, GetLocation ($2));
+ }
| THROW expression error
{
Error_SyntaxError (yyToken);
}
}
-Block
-end_block (Location loc)
+Block end_block (Location loc)
{
Block retval = current_block.Explicit;
retval.SetEndLocation (loc);
case Token.THIS:
return "this";
case Token.THROW:
+ case Token.THROW_EXPR:
return "throw";
case Token.TRUE:
return "true";
return "]";
case Token.OPEN_PARENS_CAST:
case Token.OPEN_PARENS_LAMBDA:
+ case Token.OPEN_PARENS_DECONSTRUCT:
case Token.OPEN_PARENS:
return "(";
case Token.CLOSE_PARENS: