Commit bfb48750 authored by Timothy Arceri's avatar Timothy Arceri

glsl: Add ARB_arrays_of_arrays support to yacc definition and ast

Adds array specifier object to hold array information
Signed-off-by: Timothy Arceri's avatarTimothy Arceri <t_arceri@yahoo.com.au>
Reviewed-by: Paul Berry's avatarPaul Berry <stereotype441@gmail.com>
parent 72288e0c
...@@ -276,6 +276,43 @@ private: ...@@ -276,6 +276,43 @@ private:
bool cons; bool cons;
}; };
class ast_array_specifier : public ast_node {
public:
/** Unsized array specifier ([]) */
explicit ast_array_specifier(const struct YYLTYPE &locp)
: dimension_count(1), is_unsized_array(true)
{
set_location(locp);
}
/** Sized array specifier ([dim]) */
ast_array_specifier(const struct YYLTYPE &locp, ast_expression *dim)
: dimension_count(1), is_unsized_array(false)
{
set_location(locp);
array_dimensions.push_tail(&dim->link);
}
void add_dimension(ast_expression *dim)
{
array_dimensions.push_tail(&dim->link);
dimension_count++;
}
virtual void print(void) const;
/* Count including sized and unsized dimensions */
unsigned dimension_count;
/* If true, this means that the array has an unsized outermost dimension. */
bool is_unsized_array;
/* This list contains objects of type ast_node containing the
* sized dimensions only, in outermost-to-innermost order.
*/
exec_list array_dimensions;
};
/** /**
* C-style aggregate initialization class * C-style aggregate initialization class
* *
...@@ -334,14 +371,15 @@ public: ...@@ -334,14 +371,15 @@ public:
class ast_declaration : public ast_node { class ast_declaration : public ast_node {
public: public:
ast_declaration(const char *identifier, bool is_array, ast_expression *array_size, ast_declaration(const char *identifier, bool is_array,
ast_expression *initializer); ast_array_specifier *array_specifier,
ast_expression *initializer);
virtual void print(void) const; virtual void print(void) const;
const char *identifier; const char *identifier;
bool is_array; bool is_array;
ast_expression *array_size; ast_array_specifier *array_specifier;
ast_expression *initializer; ast_expression *initializer;
}; };
...@@ -551,9 +589,9 @@ public: ...@@ -551,9 +589,9 @@ public:
* be modified. Zeros the inherited ast_node's fields. * be modified. Zeros the inherited ast_node's fields.
*/ */
ast_type_specifier(const ast_type_specifier *that, bool is_array, ast_type_specifier(const ast_type_specifier *that, bool is_array,
ast_expression *array_size) ast_array_specifier *array_specifier)
: ast_node(), type_name(that->type_name), structure(that->structure), : ast_node(), type_name(that->type_name), structure(that->structure),
is_array(is_array), array_size(array_size), is_array(is_array), array_specifier(array_specifier),
default_precision(that->default_precision) default_precision(that->default_precision)
{ {
/* empty */ /* empty */
...@@ -562,7 +600,7 @@ public: ...@@ -562,7 +600,7 @@ public:
/** Construct a type specifier from a type name */ /** Construct a type specifier from a type name */
ast_type_specifier(const char *name) ast_type_specifier(const char *name)
: type_name(name), structure(NULL), : type_name(name), structure(NULL),
is_array(false), array_size(NULL), is_array(false), array_specifier(NULL),
default_precision(ast_precision_none) default_precision(ast_precision_none)
{ {
/* empty */ /* empty */
...@@ -571,7 +609,7 @@ public: ...@@ -571,7 +609,7 @@ public:
/** Construct a type specifier from a structure definition */ /** Construct a type specifier from a structure definition */
ast_type_specifier(ast_struct_specifier *s) ast_type_specifier(ast_struct_specifier *s)
: type_name(s->name), structure(s), : type_name(s->name), structure(s),
is_array(false), array_size(NULL), is_array(false), array_specifier(NULL),
default_precision(ast_precision_none) default_precision(ast_precision_none)
{ {
/* empty */ /* empty */
...@@ -589,7 +627,7 @@ public: ...@@ -589,7 +627,7 @@ public:
ast_struct_specifier *structure; ast_struct_specifier *structure;
bool is_array; bool is_array;
ast_expression *array_size; ast_array_specifier *array_specifier;
/** For precision statements, this is the given precision; otherwise none. */ /** For precision statements, this is the given precision; otherwise none. */
unsigned default_precision:2; unsigned default_precision:2;
...@@ -643,7 +681,7 @@ public: ...@@ -643,7 +681,7 @@ public:
type(NULL), type(NULL),
identifier(NULL), identifier(NULL),
is_array(false), is_array(false),
array_size(NULL), array_specifier(NULL),
formal_parameter(false), formal_parameter(false),
is_void(false) is_void(false)
{ {
...@@ -658,7 +696,7 @@ public: ...@@ -658,7 +696,7 @@ public:
ast_fully_specified_type *type; ast_fully_specified_type *type;
const char *identifier; const char *identifier;
bool is_array; bool is_array;
ast_expression *array_size; ast_array_specifier *array_specifier;
static void parameters_to_hir(exec_list *ast_parameters, static void parameters_to_hir(exec_list *ast_parameters,
bool formal, exec_list *ir_parameters, bool formal, exec_list *ir_parameters,
...@@ -906,12 +944,12 @@ public: ...@@ -906,12 +944,12 @@ public:
ast_interface_block(ast_type_qualifier layout, ast_interface_block(ast_type_qualifier layout,
const char *instance_name, const char *instance_name,
bool is_array, bool is_array,
ast_expression *array_size) ast_array_specifier *array_specifier)
: layout(layout), block_name(NULL), instance_name(instance_name), : layout(layout), block_name(NULL), instance_name(instance_name),
is_array(is_array), array_size(array_size) is_array(is_array), array_specifier(array_specifier)
{ {
if (!is_array) if (!is_array)
assert(array_size == NULL); assert(array_specifier == NULL);
} }
virtual ir_rvalue *hir(exec_list *instructions, virtual ir_rvalue *hir(exec_list *instructions,
...@@ -946,7 +984,7 @@ public: ...@@ -946,7 +984,7 @@ public:
* If the block is not declared as an array or if the block instance array * If the block is not declared as an array or if the block instance array
* is unsized, this field will be \c NULL. * is unsized, this field will be \c NULL.
*/ */
ast_expression *array_size; ast_array_specifier *array_specifier;
}; };
......
...@@ -25,6 +25,19 @@ ...@@ -25,6 +25,19 @@
#include "glsl_types.h" #include "glsl_types.h"
#include "ir.h" #include "ir.h"
void
ast_array_specifier::print(void) const
{
if (this->is_unsized_array) {
printf("[ ] ");
}
foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
printf("[ ");
array_dimension->print();
printf("] ");
}
}
/** /**
* If \c ir is a reference to an array for which we are tracking the max array * If \c ir is a reference to an array for which we are tracking the max array
......
...@@ -1771,64 +1771,108 @@ ast_compound_statement::hir(exec_list *instructions, ...@@ -1771,64 +1771,108 @@ ast_compound_statement::hir(exec_list *instructions,
return NULL; return NULL;
} }
/**
* Evaluate the given exec_node (which should be an ast_node representing
* a single array dimension) and return its integer value.
*/
static const unsigned
process_array_size(exec_node *node,
struct _mesa_glsl_parse_state *state)
{
exec_list dummy_instructions;
ast_node *array_size = exec_node_data(ast_node, node, link);
ir_rvalue *const ir = array_size->hir(& dummy_instructions,
state);
YYLTYPE loc = array_size->get_location();
if (ir == NULL) {
_mesa_glsl_error(& loc, state,
"array size could not be resolved");
return 0;
}
if (!ir->type->is_integer()) {
_mesa_glsl_error(& loc, state,
"array size must be integer type");
return 0;
}
if (!ir->type->is_scalar()) {
_mesa_glsl_error(& loc, state,
"array size must be scalar type");
return 0;
}
ir_constant *const size = ir->constant_expression_value();
if (size == NULL) {
_mesa_glsl_error(& loc, state, "array size must be a "
"constant valued expression");
return 0;
}
if (size->value.i[0] <= 0) {
_mesa_glsl_error(& loc, state, "array size must be > 0");
return 0;
}
assert(size->type == ir->type);
/* If the array size is const (and we've verified that
* it is) then no instructions should have been emitted
* when we converted it to HIR. If they were emitted,
* then either the array size isn't const after all, or
* we are emitting unnecessary instructions.
*/
assert(dummy_instructions.is_empty());
return size->value.u[0];
}
static const glsl_type * static const glsl_type *
process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, process_array_type(YYLTYPE *loc, const glsl_type *base,
struct _mesa_glsl_parse_state *state) ast_array_specifier *array_specifier,
struct _mesa_glsl_parse_state *state)
{ {
unsigned length = 0; const glsl_type *array_type = base;
if (base == NULL) if (array_specifier != NULL) {
return glsl_type::error_type; if (base->is_array()) {
/* From page 19 (page 25) of the GLSL 1.20 spec: /* From page 19 (page 25) of the GLSL 1.20 spec:
* *
* "Only one-dimensional arrays may be declared." * "Only one-dimensional arrays may be declared."
*/ */
if (base->is_array()) { if (!state->ARB_arrays_of_arrays_enable) {
_mesa_glsl_error(loc, state, _mesa_glsl_error(loc, state,
"invalid array of `%s' (only one-dimensional arrays " "invalid array of `%s'"
"may be declared)", "GL_ARB_arrays_of_arrays "
base->name); "required for defining arrays of arrays",
return glsl_type::error_type; base->name);
} return glsl_type::error_type;
}
if (array_size != NULL) { if (base->length == 0) {
exec_list dummy_instructions; _mesa_glsl_error(loc, state,
ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); "only the outermost array dimension can "
YYLTYPE loc = array_size->get_location(); "be unsized",
base->name);
return glsl_type::error_type;
}
}
if (ir != NULL) { for (exec_node *node = array_specifier->array_dimensions.tail_pred;
if (!ir->type->is_integer()) { !node->is_head_sentinel(); node = node->prev) {
_mesa_glsl_error(& loc, state, "array size must be integer type"); unsigned array_size = process_array_size(node, state);
} else if (!ir->type->is_scalar()) { array_type = glsl_type::get_array_instance(array_type,
_mesa_glsl_error(& loc, state, "array size must be scalar type"); array_size);
} else {
ir_constant *const size = ir->constant_expression_value();
if (size == NULL) {
_mesa_glsl_error(& loc, state, "array size must be a "
"constant valued expression");
} else if (size->value.i[0] <= 0) {
_mesa_glsl_error(& loc, state, "array size must be > 0");
} else {
assert(size->type == ir->type);
length = size->value.u[0];
/* If the array size is const (and we've verified that
* it is) then no instructions should have been emitted
* when we converted it to HIR. If they were emitted,
* then either the array size isn't const after all, or
* we are emitting unnecessary instructions.
*/
assert(dummy_instructions.is_empty());
}
}
} }
if (array_specifier->is_unsized_array)
array_type = glsl_type::get_array_instance(array_type, 0);
} }
const glsl_type *array_type = glsl_type::get_array_instance(base, length); return array_type;
return array_type != NULL ? array_type : glsl_type::error_type;
} }
...@@ -1841,10 +1885,8 @@ ast_type_specifier::glsl_type(const char **name, ...@@ -1841,10 +1885,8 @@ ast_type_specifier::glsl_type(const char **name,
type = state->symbols->get_type(this->type_name); type = state->symbols->get_type(this->type_name);
*name = this->type_name; *name = this->type_name;
if (this->is_array) { YYLTYPE loc = this->get_location();
YYLTYPE loc = this->get_location(); type = process_array_type(&loc, type, this->array_specifier, state);
type = process_array_type(&loc, type, this->array_size, state);
}
return type; return type;
} }
...@@ -2831,7 +2873,7 @@ ast_declarator_list::hir(exec_list *instructions, ...@@ -2831,7 +2873,7 @@ ast_declarator_list::hir(exec_list *instructions,
foreach_list_typed (ast_declaration, decl, link, &this->declarations) { foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
assert(!decl->is_array); assert(!decl->is_array);
assert(decl->array_size == NULL); assert(decl->array_specifier == NULL);
assert(decl->initializer == NULL); assert(decl->initializer == NULL);
ir_variable *const earlier = ir_variable *const earlier =
...@@ -2966,14 +3008,8 @@ ast_declarator_list::hir(exec_list *instructions, ...@@ -2966,14 +3008,8 @@ ast_declarator_list::hir(exec_list *instructions,
continue; continue;
} }
if (decl->is_array) { var_type = process_array_type(&loc, decl_type, decl->array_specifier,
var_type = process_array_type(&loc, decl_type, decl->array_size, state);
state);
if (var_type->is_error())
continue;
} else {
var_type = decl_type;
}
var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
...@@ -3530,9 +3566,7 @@ ast_parameter_declarator::hir(exec_list *instructions, ...@@ -3530,9 +3566,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
/* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...) /* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...)
* call already handled the "vec4[..] foo" case. * call already handled the "vec4[..] foo" case.
*/ */
if (this->is_array) { type = process_array_type(&loc, type, this->array_specifier, state);
type = process_array_type(&loc, type, this->array_size, state);
}
if (!type->is_error() && type->is_unsized_array()) { if (!type->is_error() && type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "arrays passed as parameters must have " _mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
...@@ -4660,10 +4694,8 @@ ast_process_structure_or_interface_block(exec_list *instructions, ...@@ -4660,10 +4694,8 @@ ast_process_structure_or_interface_block(exec_list *instructions,
"members"); "members");
} }
if (decl->is_array) { field_type = process_array_type(&loc, decl_type,
field_type = process_array_type(&loc, decl_type, decl->array_size, decl->array_specifier, state);
state);
}
fields[i].type = field_type; fields[i].type = field_type;
fields[i].name = decl->identifier; fields[i].name = decl->identifier;
fields[i].location = -1; fields[i].location = -1;
...@@ -5045,7 +5077,7 @@ ast_interface_block::hir(exec_list *instructions, ...@@ -5045,7 +5077,7 @@ ast_interface_block::hir(exec_list *instructions,
* interface array size *doesn't* need to be specified is on a * interface array size *doesn't* need to be specified is on a
* geometry shader input. * geometry shader input.
*/ */
if (this->array_size == NULL && if (this->array_specifier->is_unsized_array &&
(state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) { (state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) {
_mesa_glsl_error(&loc, state, _mesa_glsl_error(&loc, state,
"only geometry shader inputs may be unsized " "only geometry shader inputs may be unsized "
...@@ -5054,7 +5086,7 @@ ast_interface_block::hir(exec_list *instructions, ...@@ -5054,7 +5086,7 @@ ast_interface_block::hir(exec_list *instructions,
} }
const glsl_type *block_array_type = const glsl_type *block_array_type =
process_array_type(&loc, block_type, this->array_size, state); process_array_type(&loc, block_type, this->array_specifier, state);
var = new(state) ir_variable(block_array_type, var = new(state) ir_variable(block_array_type,
this->instance_name, this->instance_name,
......
...@@ -33,13 +33,9 @@ ast_type_specifier::print(void) const ...@@ -33,13 +33,9 @@ ast_type_specifier::print(void) const
} }
if (is_array) { if (is_array) {
printf("[ "); if (array_specifier) {
array_specifier->print();
if (array_size) {
array_size->print();
} }
printf("] ");
} }
} }
......
...@@ -97,6 +97,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, ...@@ -97,6 +97,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
ast_node *node; ast_node *node;
ast_type_specifier *type_specifier; ast_type_specifier *type_specifier;
ast_array_specifier *array_specifier;
ast_fully_specified_type *fully_specified_type; ast_fully_specified_type *fully_specified_type;
ast_function *function; ast_function *function;
ast_parameter_declarator *parameter_declarator; ast_parameter_declarator *parameter_declarator;
...@@ -202,6 +203,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, ...@@ -202,6 +203,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%type <type_qualifier> interface_qualifier %type <type_qualifier> interface_qualifier
%type <type_specifier> type_specifier %type <type_specifier> type_specifier
%type <type_specifier> type_specifier_nonarray %type <type_specifier> type_specifier_nonarray
%type <array_specifier> array_specifier
%type <identifier> basic_type_specifier_nonarray %type <identifier> basic_type_specifier_nonarray
%type <fully_specified_type> fully_specified_type %type <fully_specified_type> fully_specified_type
%type <function> function_prototype %type <function> function_prototype
...@@ -880,7 +882,7 @@ parameter_declarator: ...@@ -880,7 +882,7 @@ parameter_declarator:
$$->type->specifier = $1; $$->type->specifier = $1;
$$->identifier = $2; $$->identifier = $2;
} }
| type_specifier any_identifier '[' constant_expression ']' | type_specifier any_identifier array_specifier
{ {
void *ctx = state; void *ctx = state;
$$ = new(ctx) ast_parameter_declarator(); $$ = new(ctx) ast_parameter_declarator();
...@@ -889,8 +891,7 @@ parameter_declarator: ...@@ -889,8 +891,7 @@ parameter_declarator:
$$->type->set_location(yylloc); $$->type->set_location(yylloc);
$$->type->specifier = $1; $$->type->specifier = $1;
$$->identifier = $2; $$->identifier = $2;
$$->is_array = true; $$->array_specifier = $3;
$$->array_size = $4;
} }
; ;
...@@ -983,40 +984,20 @@ init_declarator_list: ...@@ -983,40 +984,20 @@ init_declarator_list:
$$->declarations.push_tail(&decl->link); $$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
} }
| init_declarator_list ',' any_identifier '[' ']' | init_declarator_list ',' any_identifier array_specifier
{ {
void *ctx = state; void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL); ast_declaration *decl = new(ctx) ast_declaration($3, true, $4, NULL);
decl->set_location(yylloc); decl->set_location(yylloc);
$$ = $1; $$ = $1;
$$->declarations.push_tail(&decl->link); $$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
} }
| init_declarator_list ',' any_identifier '[' constant_expression ']' | init_declarator_list ',' any_identifier array_specifier '=' initializer
{ {
void *ctx = state; void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL); ast_declaration *decl = new(ctx) ast_declaration($3, true, $4, $6);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
| init_declarator_list ',' any_identifier '[' ']' '=' initializer
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
decl->set_location(yylloc);
$$ = $1;
$$->declarations.push_tail(&decl->link);
state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
}
| init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
decl->set_location(yylloc); decl->set_location(yylloc);
$$ = $1; $$ = $1;
...@@ -1053,37 +1034,19 @@ single_declaration: ...@@ -1053,37 +1034,19 @@ single_declaration:
$$->set_location(yylloc); $$->set_location(yylloc);
$$->declarations.push_tail(&decl->link); $$->declarations.push_tail(&decl->link);
} }
| fully_specified_type any_identifier '[' ']' | fully_specified_type any_identifier array_specifier
{ {
void *ctx = state; void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL); ast_declaration *decl = new(ctx) ast_declaration($2, true, $3, NULL);
$$ = new(ctx) ast_declarator_list($1); $$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc); $$->set_location(yylloc);
$$->declarations.push_tail(&decl->link); $$->declarations.push_tail(&decl->link);
} }
| fully_specified_type any_identifier '[' constant_expression ']' | fully_specified_type any_identifier array_specifier '=' initializer
{ {
void *ctx = state; void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL); ast_declaration *decl = new(ctx) ast_declaration($2, true, $3, $5);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
| fully_specified_type any_identifier '[' ']' '=' initializer
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
$$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc);
$$->declarations.push_tail(&decl->link);
}
| fully_specified_type any_identifier '[' constant_expression ']' '=' initializer
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
$$ = new(ctx) ast_declarator_list($1); $$ = new(ctx) ast_declarator_list($1);
$$->set_location(yylloc); $$->set_location(yylloc);
...@@ -1584,19 +1547,51 @@ storage_qualifier: ...@@ -1584,19 +1547,51 @@ storage_qualifier:
} }
; ;
type_specifier: array_specifier:
type_specifier_nonarray '[' ']'
| type_specifier_nonarray '[' ']' {
void *ctx = state;
$$ = new(ctx) ast_array_specifier(yylloc);
}
| '[' constant_expression ']'
{
void *ctx = state;
$$ = new(ctx) ast_array_specifier(yylloc, $2);
}
| array_specifier '[' ']'
{
$$ = $1;
if (!state->ARB_arrays_of_arrays_enable) {
_mesa_glsl_error(& @1, state,
"GL_ARB_arrays_of_arrays "
"required for defining arrays of arrays");
} else {
_mesa_glsl_error(& @1, state,
"only the outermost array dimension can "
"be unsized");
}
}
| array_specifier '[' constant_expression ']'
{ {
$$ = $1; $$ = $1;
$$->is_array = true;
$$->array_size = NULL; if (!state->ARB_arrays_of_arrays_enable) {
_mesa_glsl_error(& @1, state,
"GL_ARB_arrays_of_arrays "
"required for defining arrays of arrays");
}
$$->add_dimension($3);
} }
| type_specifier_nonarray '[' constant_expression ']' ;
type_specifier:
type_specifier_nonarray
| type_specifier_nonarray array_specifier
{ {
$$ = $1; $$ = $1;
$$->is_array = true; $$->array_specifier = $2;
$$->array_size = $3;
} }
; ;
...@@ -1779,16 +1774,10 @@ struct_declarator: ...@@ -1779,16 +1774,10 @@ struct_declarator:
$$ = new(ctx) ast_declaration($1, false, NULL, NULL); $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
$$->set_location(yylloc); $$->set_location(yylloc);
} }
| any_identifier '[' ']' | any_identifier array_specifier
{ {
void *ctx = state; void *ctx = state;
$$ = new(ctx) ast_declaration($1, true, NULL, NULL); $$ = new(ctx) ast_declaration($1, true, $2, NULL);
$$->set_location(yylloc);
}
| any_identifier '[' constant_expression ']'