%{
/*
*
* (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC.
* (c) Copyright 1989 HEWLETT-PACKARD COMPANY
* (c) Copyright 1989 DIGITAL EQUIPMENT CORPORATION
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this
* file for any purpose is hereby granted without fee, provided that
* the above copyright notices and this notice appears in all source
* code copies, and that none of the names of Open Software
* Foundation, Inc., Hewlett-Packard Company, or Digital Equipment
* Corporation be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Neither Open Software Foundation, Inc., Hewlett-
* Packard Company, nor Digital Equipment Corporation makes any
* representations about the suitability of this software for any
* purpose.
*
*/
/*
**
** NAME:
**
** IDL.Y
**
** FACILITY:
**
** Interface Definition Language (IDL) Compiler
**
** ABSTRACT:
**
** This module defines the main IDL grammar accepted
** by the IDL compiler.
**
** VERSION: DCE 1.0
**
*/
#ifdef vms
# include <types.h>
#else
# include <sys/types.h>
#endif
#include <nidl.h>
#include <nametbl.h>
#include <errors.h>
#include <ast.h>
#include <astp.h>
#include <frontend.h>
extern boolean search_attributes_table ;
int yyparse (
void
);
/*
** Local cells used for inter-production communication
*/
static ASTP_attr_k_t ASTP_bound_type; /* Array bound attribute */
%}
/* Declaration of yylval, yyval */
%union
{
NAMETABLE_id_t y_id ; /* Identifier */
STRTAB_str_t y_string ; /* String */
STRTAB_str_t y_float ; /* Float constant */
int y_ival ; /* Integer constant */
AST_export_n_t* y_export ; /* an export node */
AST_import_n_t* y_import ; /* Import node */
AST_exception_n_t* y_exception ; /* Exception node */
AST_constant_n_t* y_constant; /* Constant node */
AST_parameter_n_t* y_parameter ; /* Parameter node */
AST_type_n_t* y_type ; /* Type node */
AST_type_p_n_t* y_type_ptr ; /* Type pointer node */
AST_field_n_t* y_field ; /* Field node */
AST_arm_n_t* y_arm ; /* Union variant arm */
AST_operation_n_t* y_operation ; /* Routine node */
AST_interface_n_t* y_interface ; /* Interface node */
AST_case_label_n_t* y_label ; /* Union tags */
ASTP_declarator_n_t* y_declarator ; /* Declarator info */
ASTP_array_index_n_t* y_index ; /* Array index info */
nidl_uuid_t y_uuid ; /* Universal UID */
char y_char; /* character constant */
ASTP_attributes_t y_attributes; /* attributes flags */
struct {
AST_type_k_t int_size;
int int_signed;
} y_int_info; /* int size and signedness */
ASTP_exp_n_t y_exp; /* constant expression info */
}
/********************************************************************/
/* */
/* Tokens used by the IDL parser. */
/* */
/********************************************************************/
/* Keywords */
%token ALIGN_KW
%token BYTE_KW
%token CHAR_KW
%token CONST_KW
%token DEFAULT_KW
%token ENUM_KW
%token EXCEPTIONS_KW
%token FLOAT_KW
%token HYPER_KW
%token INT_KW
%token INTERFACE_KW
%token IMPORT_KW
%token LONG_KW
%token PIPE_KW
%token REF_KW
%token SMALL_KW
%token STRUCT_KW
%token TYPEDEF_KW
%token UNION_KW
%token UNSIGNED_KW
%token SHORT_KW
%token VOID_KW
%token DOUBLE_KW
%token BOOLEAN_KW
%token CASE_KW
%token SWITCH_KW
%token HANDLE_T_KW
%token TRUE_KW
%token FALSE_KW
%token NULL_KW
%token BROADCAST_KW
%token COMM_STATUS_KW
%token CONTEXT_HANDLE_KW
%token FIRST_IS_KW
%token HANDLE_KW
%token IDEMPOTENT_KW
%token IGNORE_KW
%token IMPLICIT_HANDLE_KW
%token IN_KW
%token LAST_IS_KW
%token LENGTH_IS_KW
%token LOCAL_KW
%token MAX_IS_KW
%token MAYBE_KW
%token MIN_IS_KW
%token MUTABLE_KW
%token OUT_KW
%token POINTER_DEFAULT_KW
%token ENDPOINT_KW
%token PTR_KW
%token REFLECT_DELETIONS_KW
%token REMOTE_KW
%token SECURE_KW
%token SHAPE_KW
%token SIZE_IS_KW
%token STRING_KW
%token SWITCH_IS_KW
%token SWITCH_TYPE_KW
%token TRANSMIT_AS_KW
%token UNIQUE_KW
%token UUID_KW
%token VERSION_KW
%token V1_ARRAY_KW
%token V1_STRING_KW
%token V1_ENUM_KW
%token V1_STRUCT_KW
/* Non-keyword tokens */
%token UUID_REP
/* Punctuation */
%token COLON
%token COMMA
%token DOTDOT
%token EQUAL
%token LBRACE
%token LBRACKET
%token LPAREN
%token RBRACE
%token RBRACKET
%token RPAREN
%token SEMI
%token STAR
%token QUESTION
%token BAR
%token BARBAR
%token LANGLE
%token LANGLEANGLE
%token RANGLE
%token RANGLEANGLE
%token AMP
%token AMPAMP
%token LESSEQUAL
%token GREATEREQUAL
%token EQUALEQUAL
%token CARET
%token PLUS
%token MINUS
%token NOT
%token NOTEQUAL
%token SLASH
%token PERCENT
%token TILDE
%token UNKNOWN /* Something that doesn't fit in any other token class */
/* Tokens setting yylval */
%token <y_id> IDENTIFIER
%token <y_string> STRING
%token <y_ival> INTEGER_NUMERIC
%token <y_char> CHAR
%token <y_float> FLOAT_NUMERIC
%start interface
%%
/********************************************************************/
/* */
/* Syntax description and actions for IDL */
/* */
/********************************************************************/
interface:
interface_init interface_start interface_tail
{
AST_finish_interface_node(the_interface);
}
;
interface_start:
interface_attributes INTERFACE_KW IDENTIFIER
{
the_interface->name = $<y_id>3;
ASTP_add_name_binding(the_interface->name, (char *)the_interface);
}
;
interface_init:
/* Always create the interface node and auto-import the system idl */
{
STRTAB_str_t nidl_idl_str;
nidl_idl_str = STRTAB_add_string (AUTO_IMPORT_FILE);
the_interface = AST_interface_node();
the_interface->imports = AST_import_node(nidl_idl_str);
the_interface->imports->interface = FE_parse_import (nidl_idl_str);
if (the_interface->imports->interface != NULL)
{
AST_CLR_OUT_OF_LINE(the_interface->imports->interface);
AST_SET_IN_LINE(the_interface->imports->interface);
}
}
;
interface_tail:
LBRACE interface_body RBRACE
{ $<y_interface>$ = $<y_interface>2; }
| error
{
$<y_interface>$ = NULL;
log_error(yylineno,NIDL_MISSONINTER);
}
| error RBRACE
{
$<y_interface>$ = NULL;
}
;
interface_body:
optional_imports exports extraneous_semi
{
/* May already be an import of nbase, so concat */
the_interface->imports = (AST_import_n_t *) AST_concat_element(
(ASTP_node_t *) the_interface->imports,
(ASTP_node_t *) $<y_import>1);
the_interface->exports = $<y_export>2;
}
;
optional_imports:
imports
| /* Nothing */
{
$<y_import>$ = (AST_import_n_t *)NULL;
}
imports:
import
| imports import
{
$<y_import>$ = (AST_import_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_import>1,
(ASTP_node_t *) $<y_import>2);
}
;
import:
IMPORT_KW error
{
$<y_import>$ = (AST_import_n_t *)NULL;
}
| IMPORT_KW error SEMI
{
$<y_import>$ = (AST_import_n_t *)NULL;
}
| IMPORT_KW import_files SEMI
{
$<y_import>$ = $<y_import>2;
}
;
import_files:
import_file
| import_files COMMA import_file
{
$<y_import>$ = (AST_import_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_import>1,
(ASTP_node_t *) $<y_import>3);
}
;
import_file:
STRING
{
AST_interface_n_t *int_p;
int_p = FE_parse_import ($<y_string>1);
if (int_p != (AST_interface_n_t *)NULL)
{
$<y_import>$ = AST_import_node($<y_string>1);
$<y_import>$->interface = int_p;
}
else
$<y_import>$ = (AST_import_n_t *)NULL;
}
;
exports:
export
| exports extraneous_semi export
{
$<y_export>$ = (AST_export_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_export>1,
(ASTP_node_t *) $<y_export>3) ;
}
;
export:
type_dcl SEMI
{
$<y_export>$ = AST_types_to_exports ($<y_type_ptr>1);
}
| const_dcl SEMI
{
$<y_export>$ = AST_export_node (
(ASTP_node_t *) $<y_constant>1, AST_constant_k);
}
| operation_dcl SEMI
{
if (ASTP_parsing_main_idl)
$<y_export>$ = AST_export_node (
(ASTP_node_t *) $<y_operation>1, AST_operation_k);
}
| error SEMI
{
$<y_export>$ = (AST_export_n_t *)NULL;
}
;
const_dcl:
CONST_KW type_spec declarator EQUAL const_exp
{
$<y_constant>$ = AST_finish_constant_node ($<y_constant>5,
$<y_declarator>3, $<y_type>2);
}
;
const_exp: expression
{
if ($<y_exp>1.type == AST_int_const_k)
$<y_constant>$ = AST_integer_constant ($<y_exp>1.val.integer) ;
else
$<y_constant>$ = $<y_exp>1.val.other;
}
;
type_dcl:
TYPEDEF_KW type_declarator
{
$<y_type_ptr>$ = $<y_type_ptr>2;
}
;
type_declarator:
attributes type_spec declarators
{
$<y_type_ptr>$ = AST_declarators_to_types($<y_type>2,
$<y_declarator>3, &$<y_attributes>1) ;
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
;
type_spec:
simple_type_spec
| constructed_type_spec
;
simple_type_spec:
floating_point_type_spec
| integer_type_spec
| char_type_spec
| boolean_type_spec
| byte_type_spec
| void_type_spec
| named_type_spec
| handle_type_spec
;
constructed_type_spec:
struct_type_spec
| union_type_spec
| enum_type_spec
| pipe_type_spec
;
named_type_spec:
IDENTIFIER
{
$<y_type>$ = AST_lookup_named_type($<y_id>1);
}
;
floating_point_type_spec:
FLOAT_KW
{
$<y_type>$ = AST_lookup_type_node(AST_short_float_k);
}
| DOUBLE_KW
{
$<y_type>$ = AST_lookup_type_node(AST_long_float_k);
}
;
extraneous_comma:
/* Nothing */
| COMMA
{ log_warning(yylineno, NIDL_EXTRAPUNCT, ",");}
;
extraneous_semi:
/* Nothing */
| SEMI
{ log_warning(yylineno, NIDL_EXTRAPUNCT, ";");}
;
optional_unsigned_kw:
UNSIGNED_KW { $<y_ival>$ = false; }
| /* Nothing */ { $<y_ival>$ = true; }
;
integer_size_spec:
SMALL_KW
{
$<y_int_info>$.int_size = AST_small_integer_k;
$<y_int_info>$.int_signed = true;
}
| SHORT_KW
{
$<y_int_info>$.int_size = AST_short_integer_k;
$<y_int_info>$.int_signed = true;
}
| LONG_KW
{
$<y_int_info>$.int_size = AST_long_integer_k;
$<y_int_info>$.int_signed = true;
}
| HYPER_KW
{
$<y_int_info>$.int_size = AST_hyper_integer_k;
$<y_int_info>$.int_signed = true;
}
;
integer_modifiers:
integer_size_spec
{ $<y_int_info>$ = $<y_int_info>1; }
| UNSIGNED_KW integer_size_spec
{
$<y_int_info>$.int_size = $<y_int_info>2.int_size;
$<y_int_info>$.int_signed = false;
}
| integer_size_spec UNSIGNED_KW
{
$<y_int_info>$.int_size = $<y_int_info>1.int_size;
$<y_int_info>$.int_signed = false;
}
;
integer_type_spec:
integer_modifiers
{ $<y_type>$ = AST_lookup_integer_type_node($<y_int_info>1.int_size,$<y_int_info>1.int_signed); }
| integer_modifiers INT_KW
{ $<y_type>$ = AST_lookup_integer_type_node($<y_int_info>1.int_size,$<y_int_info>1.int_signed); }
| optional_unsigned_kw INT_KW
{
log_warning(yylineno,NIDL_INTSIZEREQ);
$<y_type>$ = AST_lookup_integer_type_node(AST_long_integer_k,$<y_ival>1);
}
;
char_type_spec:
optional_unsigned_kw CHAR_KW
{ $<y_type>$ = AST_lookup_type_node(AST_character_k); }
;
boolean_type_spec:
BOOLEAN_KW
{ $<y_type>$ = AST_lookup_type_node(AST_boolean_k); }
;
byte_type_spec:
BYTE_KW
{ $<y_type>$ = AST_lookup_type_node(AST_byte_k); }
;
void_type_spec:
VOID_KW
{ $<y_type>$ = AST_lookup_type_node(AST_void_k); }
;
handle_type_spec:
HANDLE_T_KW
{ $<y_type>$ = AST_lookup_type_node(AST_handle_k); }
;
push_name_space:
LBRACE
{
NAMETABLE_push_level ();
}
;
pop_name_space:
RBRACE
{
ASTP_patch_field_reference ();
NAMETABLE_pop_level ();
}
;
union_type_spec:
UNION_KW ne_union_body
{
$<y_type>$ = AST_disc_union_node(
NAMETABLE_NIL_ID, /* tag name */
NAMETABLE_NIL_ID, /* union name */
NAMETABLE_NIL_ID, /* discriminant name */
NULL, /* discriminant type */
$<y_arm>2 ); /* the arm list */
}
|
UNION_KW SWITCH_KW LPAREN simple_type_spec IDENTIFIER RPAREN union_body
{
$<y_type>$ = AST_disc_union_node(
NAMETABLE_NIL_ID, /* tag name */
ASTP_tagged_union_id, /* union name */
$<y_id>5, /* discriminant name */
$<y_type>4, /* discriminant type */
$<y_arm>7 ); /* the arm list */
}
| UNION_KW IDENTIFIER ne_union_body
{
$<y_type>$ = AST_disc_union_node(
$<y_id>2, /* tag name */
NAMETABLE_NIL_ID, /* union name */
NAMETABLE_NIL_ID, /* discriminant name */
NULL, /* discriminant type */
$<y_arm>3 ); /* the arm list */
}
| UNION_KW SWITCH_KW LPAREN simple_type_spec IDENTIFIER RPAREN IDENTIFIER union_body
{
$<y_type>$ = AST_disc_union_node(
NAMETABLE_NIL_ID, /* tag name */
$<y_id>7, /* union name */
$<y_id>5, /* discriminant name */
$<y_type>4, /* discriminant type */
$<y_arm>8 ); /* the arm list */
}
| UNION_KW IDENTIFIER SWITCH_KW LPAREN simple_type_spec IDENTIFIER RPAREN union_body
{
$<y_type>$ = AST_disc_union_node(
$<y_id>2, /* tag name */
ASTP_tagged_union_id, /* union name */
$<y_id>6, /* discriminant name */
$<y_type>5, /* discriminant type */
$<y_arm>8 ); /* the arm list */
}
| UNION_KW IDENTIFIER SWITCH_KW LPAREN simple_type_spec IDENTIFIER RPAREN IDENTIFIER union_body
{
$<y_type>$ = AST_disc_union_node(
$<y_id>2, /* tag name */
$<y_id>8, /* union name */
$<y_id>6, /* discriminant name */
$<y_type>5, /* discriminant type */
$<y_arm>9 ); /* the arm list */
}
| UNION_KW IDENTIFIER
{
$<y_type>$ = AST_type_from_tag (AST_disc_union_k, $<y_id>2);
}
;
ne_union_body:
push_name_space ne_union_cases pop_name_space
{
$<y_arm>$ = $<y_arm>2;
}
;
union_body:
push_name_space union_cases pop_name_space
{
$<y_arm>$ = $<y_arm>2;
}
;
ne_union_cases:
ne_union_case
| ne_union_cases extraneous_semi ne_union_case
{
$<y_arm>$ = (AST_arm_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_arm>1,
(ASTP_node_t *) $<y_arm>3);
}
;
union_cases:
union_case
| union_cases extraneous_semi union_case
{
$<y_arm>$ = (AST_arm_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_arm>1,
(ASTP_node_t *) $<y_arm>3);
}
;
ne_union_case:
ne_union_member
{
$<y_arm>$ = $<y_arm>1;
}
;
union_case:
union_case_list union_member
{
$<y_arm>$ = AST_label_arm($<y_arm>2, $<y_label>1) ;
}
;
ne_union_case_list:
ne_union_case_label
| ne_union_case_list COMMA ne_union_case_label
{
$<y_label>$ = (AST_case_label_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_label>1,
(ASTP_node_t *) $<y_label>3);
}
;
union_case_list:
union_case_label
| union_case_list union_case_label
{
$<y_label>$ = (AST_case_label_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_label>1,
(ASTP_node_t *) $<y_label>2);
}
;
ne_union_case_label:
const_exp
{
$<y_label>$ = AST_case_label_node($<y_constant>1);
}
;
union_case_label:
CASE_KW const_exp COLON
{
$<y_label>$ = AST_case_label_node($<y_constant>2);
}
| DEFAULT_KW COLON
{
$<y_label>$ = AST_default_case_label_node();
}
;
ne_union_member:
attribute_opener rest_of_attribute_list SEMI
{
$<y_arm>$ = AST_declarator_to_arm(NULL, NULL, &$<y_attributes>2);
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>2.bounds);
}
| attribute_opener rest_of_attribute_list type_spec declarator SEMI
{
$<y_arm>$ = AST_declarator_to_arm($<y_type>3,
$<y_declarator>4, &$<y_attributes>2);
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>2.bounds);
}
;
union_member:
/* nothing */ SEMI
{
$<y_arm>$ = AST_arm_node(NAMETABLE_NIL_ID,NULL,NULL);
}
| attributes type_spec declarator SEMI
{
if (ASTP_TEST_ATTR(&$<y_attributes>1, ASTP_CASE))
{
ASTP_attr_flag_t attr1 = ASTP_CASE;
log_error(yylineno, NIDL_EUMEMATTR,
KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)));
}
if (ASTP_TEST_ATTR(&$<y_attributes>1, ASTP_DEFAULT))
{
ASTP_attr_flag_t attr1 = ASTP_DEFAULT;
log_error(yylineno, NIDL_EUMEMATTR,
KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)));
}
$<y_arm>$ = AST_declarator_to_arm($<y_type>2,
$<y_declarator>3, &$<y_attributes>1);
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
;
struct_type_spec:
STRUCT_KW push_name_space member_list pop_name_space
{
$<y_type>$ = AST_structure_node($<y_field>3, NAMETABLE_NIL_ID) ;
}
| STRUCT_KW IDENTIFIER push_name_space member_list pop_name_space
{
$<y_type>$ = AST_structure_node($<y_field>4, $<y_id>2) ;
}
| STRUCT_KW IDENTIFIER
{
$<y_type>$ = AST_type_from_tag (AST_structure_k, $<y_id>2);
}
;
member_list:
member
| member_list extraneous_semi member
{
$<y_field>$ = (AST_field_n_t *)AST_concat_element(
(ASTP_node_t *) $<y_field>1,
(ASTP_node_t *) $<y_field>3) ;
}
;
member:
attributes type_spec old_attribute_syntax declarators SEMI
{
$<y_field>$ = AST_declarators_to_fields($<y_declarator>4,
$<y_type>2,
&$<y_attributes>1);
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
;
enum_type_spec:
ENUM_KW enum_body
{
$<y_type>$ = AST_enumerator_node($<y_constant>2, AST_short_integer_k);
}
;
enum_body:
LBRACE enum_ids RBRACE
{
$<y_constant>$ = $<y_constant>2 ;
}
;
enum_ids:
enum_id
| enum_ids COMMA extraneous_comma enum_id
{
$<y_constant>$ = (AST_constant_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_constant>1,
(ASTP_node_t *) $<y_constant>4) ;
}
;
enum_id:
IDENTIFIER
{
$<y_constant>$ = AST_enum_constant($<y_id>1) ;
}
;
pipe_type_spec:
PIPE_KW type_spec
{
$<y_type>$ = AST_pipe_node ($<y_type>2);
}
;
declarators:
declarator
| declarators COMMA extraneous_comma declarator
{
$<y_declarator>$ = (ASTP_declarator_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_declarator>1,
(ASTP_node_t *) $<y_declarator>4) ;
}
;
declarator:
direct_declarator
{ $<y_declarator>$ = $<y_declarator>1; }
| pointer direct_declarator
{
$<y_declarator>$ = $<y_declarator>2;
AST_declarator_operation($<y_declarator>$, AST_pointer_k,
(ASTP_node_t *)NULL, $<y_ival>1 );
};
pointer :
STAR
{ $<y_ival>$ = 1;}
| STAR pointer
{ $<y_ival>$ = $<y_ival>2 + 1; };
direct_declarator:
IDENTIFIER
{ $<y_declarator>$ = AST_declarator_node ( $<y_id>1 ); }
| direct_declarator array_bounds
{
$<y_declarator>$ = $<y_declarator>$;
AST_declarator_operation($<y_declarator>$, AST_array_k,
(ASTP_node_t *) $<y_index>2, 0 );
}
| LPAREN declarator RPAREN
{
$<y_declarator>$ = $<y_declarator>2;
}
| direct_declarator parameter_dcls
{
$<y_declarator>$ = $<y_declarator>$;
AST_declarator_operation($<y_declarator>$, AST_function_k,
(ASTP_node_t *) $<y_parameter>2, 0 );
}
;
/*
* The following productions use an AST routine with the signature:
*
* ASTP_array_index_node( AST_constant_n_t * lower_bound,
* ASTP_bound_t lower_bound_type,
* AST_constant_n_t * upper_bound,
* ASTP_bound_t upper_bound_type);
*
* The type ASTP_bound_t is defined as:
*
* typedef enum {ASTP_constant_bound,
* ASTP_default_bound,
* ASTP_open_bound} ASTP_bound_t;
*
* The bound value passed is only used if the associated bound type is
* ASTP_constant_bound.
*/
array_bounds:
LBRACKET RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( NULL, ASTP_default_bound,
NULL, ASTP_open_bound);
}
| LBRACKET STAR RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( NULL, ASTP_default_bound,
NULL, ASTP_open_bound);
}
| LBRACKET const_exp RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( NULL, ASTP_default_bound,
$<y_constant>2, ASTP_constant_bound);
}
| LBRACKET STAR DOTDOT STAR RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( NULL, ASTP_open_bound,
NULL, ASTP_open_bound);
}
| LBRACKET STAR DOTDOT const_exp RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( NULL, ASTP_open_bound,
$<y_constant>4, ASTP_constant_bound);
}
| LBRACKET const_exp DOTDOT STAR RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( $<y_constant>2, ASTP_constant_bound,
NULL, ASTP_open_bound);
}
| LBRACKET const_exp DOTDOT const_exp RBRACKET
{
$<y_index>$ = ASTP_array_index_node ( $<y_constant>2, ASTP_constant_bound,
$<y_constant>4, ASTP_constant_bound);
}
operation_dcl:
attributes type_spec declarators
{
if (ASTP_parsing_main_idl)
$<y_operation>$ = AST_operation_node (
$<y_type>2, /*The type node*/
$<y_declarator>3, /* Declarator list */
&$<y_attributes>1); /* attributes */
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
| error declarators
{
log_error(yylineno,NIDL_MISSONOP);
$<y_operation>$ = NULL;
}
;
parameter_dcls:
param_names param_list end_param_names
{
$<y_parameter>$ = $<y_parameter>2;
}
;
param_names:
LPAREN
{
NAMETABLE_push_level ();
}
;
end_param_names:
extraneous_comma RPAREN
{
ASTP_patch_field_reference ();
NAMETABLE_pop_level ();
}
;
param_list:
param_dcl
| param_list COMMA extraneous_comma param_dcl
{
if (ASTP_parsing_main_idl)
$<y_parameter>$ = (AST_parameter_n_t *) AST_concat_element(
(ASTP_node_t *) $<y_parameter>1,
(ASTP_node_t *) $<y_parameter>4);
}
| /* nothing */
{
$<y_parameter>$ = (AST_parameter_n_t *)NULL;
}
;
param_dcl:
attributes type_spec old_attribute_syntax declarator_or_null
{
/*
* We have to use special code here to allow (void) as a parameter
* specification. If there are no declarators, then we need to
* make sure that the type is void and that there are no attributes .
*/
if ($<y_declarator>4 == NULL)
{
/*
* If the type is not void or some attribute is specified,
* there is a syntax error. Force a yacc error, so that
* we can safely recover from the lack of a declarator.
*/
if (($<y_type>2->kind != AST_void_k) ||
($<y_attributes>1.bounds != NULL) ||
($<y_attributes>1.attr_flags != 0))
{
yywhere(); /* Issue a syntax error for this line */
YYERROR; /* Allow natural error recovery */
}
$<y_parameter>$ = (AST_parameter_n_t *)NULL;
}
else
{
if (ASTP_parsing_main_idl)
$<y_parameter>$ = AST_declarator_to_param(
&$<y_attributes>1,
$<y_type>2,
$<y_declarator>4);
}
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
| error old_attribute_syntax declarator_or_null
{
log_error(yylineno, NIDL_MISSONPARAM);
$<y_parameter>$ = (AST_parameter_n_t *)NULL;
}
;
declarator_or_null:
declarator
{ $<y_declarator>$ = $<y_declarator>1; }
| /* nothing */
{ $<y_declarator>$ = NULL; }
;
/*
* Attribute definitions
*
* Attributes may appear on types, fields, parameters, operations and
* interfaces. Thes productions must be used around attributes in order
* for LEX to recognize attribute names as keywords instead of identifiers.
* The bounds productions are used in attribute options (such
* as size_is) because variable names the may look like attribute names
* should be allowed.
*/
attribute_opener:
LBRACKET
{
search_attributes_table = true;
}
;
attribute_closer:
RBRACKET
{
search_attributes_table = false;
}
;
bounds_opener:
LPAREN
{
search_attributes_table = false;
}
;
bounds_closer:
RPAREN
{
search_attributes_table = true;
}
;
/*
* Production to accept attributes in the old location, and issue a clear error that
* the translator should be used.
*/
old_attribute_syntax:
attributes
{
/* Give an error on notranslated sources */
if (($<y_attributes>1.bounds != NULL) ||
($<y_attributes>1.attr_flags != 0))
{
log_error(yylineno,NIDL_ATTRTRANS);
ASTP_free_simple_list((ASTP_node_t *)$<y_attributes>1.bounds);
}
}
;
/*
* Interface Attributes
*
* Interface attributes are special--there is no cross between interface
* attributes and other attributes (for instance on fields or types.
*/
interface_attributes:
attribute_opener interface_attr_list attribute_closer
| attribute_opener error attribute_closer
{
log_error(yylineno,NIDL_ERRINATTR);
}
| /* Nothing */
;
interface_attr_list:
interface_attr
| interface_attr_list COMMA extraneous_comma interface_attr
| /* nothing */
;
interface_attr:
UUID_KW error
{
log_error(yylineno,NIDL_SYNTAXUUID);
}
| UUID_KW UUID_REP
{
{
if (ASTP_IF_AF_SET(the_interface,ASTP_IF_UUID))
log_error(yylineno, NIDL_ATTRUSEMULT);
ASTP_SET_IF_AF(the_interface,ASTP_IF_UUID);
the_interface->uuid = $<y_uuid>2;
}
}
| ENDPOINT_KW LPAREN port_list RPAREN
{
if (ASTP_IF_AF_SET(the_interface,ASTP_IF_PORT))
log_error(yylineno, NIDL_ATTRUSEMULT);
ASTP_SET_IF_AF(the_interface,ASTP_IF_PORT);
}
| EXCEPTIONS_KW LPAREN excep_list RPAREN
{
if (ASTP_IF_AF_SET(the_interface, ASTP_IF_EXCEPTIONS))
log_error(yylineno, NIDL_ATTRUSEMULT);
ASTP_SET_IF_AF(the_interface, ASTP_IF_EXCEPTIONS);
}
| VERSION_KW LPAREN version_number RPAREN
{
{
if (ASTP_IF_AF_SET(the_interface,ASTP_IF_VERSION))
log_error(yylineno, NIDL_ATTRUSEMULT);
ASTP_SET_IF_AF(the_interface,ASTP_IF_VERSION);
}
}
| LOCAL_KW
{
{
if (AST_LOCAL_SET(the_interface))
log_warning(yylineno, NIDL_MULATTRDEF);
AST_SET_LOCAL(the_interface);
}
}
| POINTER_DEFAULT_KW LPAREN pointer_class RPAREN
{
if (interface_pointer_class != 0)
log_error(yylineno, NIDL_ATTRUSEMULT);
interface_pointer_class = $<y_ival>3;
}
;
pointer_class:
REF_KW { $<y_ival>$ = ASTP_REF; }
| PTR_KW { $<y_ival>$ = ASTP_PTR; }
| UNIQUE_KW { $<y_ival>$ = ASTP_UNIQUE; }
;
version_number:
INTEGER_NUMERIC
{
the_interface->version = $<y_ival>1;
if ($<y_ival>1 > (unsigned int)ASTP_C_USHORT_MAX)
log_error(yylineno, NIDL_MAJORTOOLARGE, ASTP_C_USHORT_MAX);
}
| FLOAT_NUMERIC
{
char *float_text;
unsigned int major_version,minor_version;
STRTAB_str_to_string($<y_string>1, &float_text);
sscanf(float_text,"%d.%d",&major_version,&minor_version);
if (major_version > (unsigned int)ASTP_C_USHORT_MAX)
log_error(yylineno, NIDL_MAJORTOOLARGE, ASTP_C_USHORT_MAX);
if (minor_version > (unsigned int)ASTP_C_USHORT_MAX)
log_error(yylineno, NIDL_MINORTOOLARGE, ASTP_C_USHORT_MAX);
the_interface->version = (minor_version * 65536) + major_version;
}
;
port_list:
port_spec
| port_list COMMA extraneous_comma port_spec
;
excep_list:
excep_spec
{
the_interface->exceptions = $<y_exception>1;
}
| excep_list COMMA extraneous_comma excep_spec
{
$<y_exception>$ = (AST_exception_n_t *) AST_concat_element(
(ASTP_node_t *) the_interface->exceptions,
(ASTP_node_t *) $<y_exception>4 );
}
;
port_spec:
STRING
{
ASTP_parse_port(the_interface,$<y_string>1);
}
;
excep_spec:
IDENTIFIER
{
if (ASTP_parsing_main_idl)
$<y_exception>$ = AST_exception_node($<y_id>1);
else
$<y_exception>$ = NULL;
}
;
/*
* Attributes that can appear on fields or parameters. These are the array
* bounds attributes, i.e., last_is and friends. They are handled differently
* from any other attributes.
*/
fp_attribute:
array_bound_type bounds_opener array_bound_id_list bounds_closer
{
$<y_attributes>$.bounds = $<y_attributes>3.bounds;
$<y_attributes>$.attr_flags = 0;
}
| neu_switch_type bounds_opener neu_switch_id bounds_closer
{
$<y_attributes>$.bounds = $<y_attributes>3.bounds;
$<y_attributes>$.attr_flags = 0;
}
;
array_bound_type:
FIRST_IS_KW
{
ASTP_bound_type = first_is_k;
}
| LAST_IS_KW
{
ASTP_bound_type = last_is_k;
}
| LENGTH_IS_KW
{
ASTP_bound_type = length_is_k;
}
| MAX_IS_KW
{
ASTP_bound_type = max_is_k;
}
| MIN_IS_KW
{
ASTP_bound_type = min_is_k;
}
| SIZE_IS_KW
{
ASTP_bound_type = size_is_k;
}
;
array_bound_id_list:
array_bound_id
| array_bound_id_list COMMA array_bound_id
{
$<y_attributes>$.bounds = (ASTP_type_attr_n_t *) AST_concat_element (
(ASTP_node_t*) $<y_attributes>1.bounds,
(ASTP_node_t*) $<y_attributes>3.bounds);
}
;
array_bound_id:
IDENTIFIER
{
$<y_attributes>$.bounds = AST_array_bound_info ($<y_id>1, ASTP_bound_type, FALSE);
}
| STAR IDENTIFIER
{
$<y_attributes>$.bounds = AST_array_bound_info ($<y_id>2, ASTP_bound_type, TRUE);
}
| /* nothing */
{
$<y_attributes>$.bounds = AST_array_bound_info (NAMETABLE_NIL_ID, ASTP_bound_type, FALSE);
}
;
neu_switch_type:
SWITCH_IS_KW
{
ASTP_bound_type = switch_is_k;
}
;
neu_switch_id:
IDENTIFIER
{
$<y_attributes>$.bounds = AST_array_bound_info ($<y_id>1, ASTP_bound_type, FALSE);
}
| STAR IDENTIFIER
{
$<y_attributes>$.bounds = AST_array_bound_info ($<y_id>2, ASTP_bound_type, TRUE);
}
;
/*
* Generalized Attribute processing
*/
attributes:
attribute_opener rest_of_attribute_list
{ $<y_attributes>$ = $<y_attributes>2; }
|
/* nothing */
{
$<y_attributes>$.bounds = NULL;
$<y_attributes>$.attr_flags = 0;
}
;
rest_of_attribute_list:
attribute_list attribute_closer
| error attribute_closer
{
/*
* Can't tell if we had any valid attributes in the list, so return
* none.
*/
$<y_attributes>$.bounds = NULL;
$<y_attributes>$.attr_flags = 0;
log_error(yylineno, NIDL_ERRINATTR);
}
| error SEMI
{
/*
* No closer to the attribute, so give a different message.
*/
$<y_attributes>$.bounds = NULL;
$<y_attributes>$.attr_flags = 0;
log_error(yylineno, NIDL_MISSONATTR);
search_attributes_table = false;
}
;
attribute_list:
attribute
{ $<y_attributes>$ = $<y_attributes>1; }
|
attribute_list COMMA extraneous_comma attribute
{
/*
* If the same bit has been specified more than once, then issue
* a message.
*/
if (($<y_attributes>1.attr_flags & $<y_attributes>4.attr_flags) != 0)
log_warning(yylineno, NIDL_MULATTRDEF);
$<y_attributes>$.attr_flags = $<y_attributes>1.attr_flags |
$<y_attributes>4.attr_flags;
$<y_attributes>$.bounds = (ASTP_type_attr_n_t *) AST_concat_element (
(ASTP_node_t*) $<y_attributes>1.bounds,
(ASTP_node_t*) $<y_attributes>4.bounds);
}
;
attribute:
/* bound attributes */
fp_attribute { $<y_attributes>$ = $<y_attributes>1; }
/* Operation Attributes */
| BROADCAST_KW { $<y_attributes>$.attr_flags = ASTP_BROADCAST;
$<y_attributes>$.bounds = NULL; }
| MAYBE_KW { $<y_attributes>$.attr_flags = ASTP_MAYBE;
$<y_attributes>$.bounds = NULL; }
| IDEMPOTENT_KW { $<y_attributes>$.attr_flags = ASTP_IDEMPOTENT;
$<y_attributes>$.bounds = NULL; }
| REFLECT_DELETIONS_KW { $<y_attributes>$.attr_flags = ASTP_REFLECT_DELETIONS;
$<y_attributes>$.bounds = NULL; }
/* Parameter-only Attributes */
| PTR_KW { $<y_attributes>$.attr_flags = ASTP_PTR;
$<y_attributes>$.bounds = NULL; }
| IN_KW { $<y_attributes>$.attr_flags = ASTP_IN;
$<y_attributes>$.bounds = NULL; }
| IN_KW LPAREN SHAPE_KW RPAREN
{ $<y_attributes>$.attr_flags =
ASTP_IN | ASTP_IN_SHAPE;
$<y_attributes>$.bounds = NULL; }
| OUT_KW { $<y_attributes>$.attr_flags = ASTP_OUT;
$<y_attributes>$.bounds = NULL; }
| OUT_KW LPAREN SHAPE_KW RPAREN
{ $<y_attributes>$.attr_flags =
ASTP_OUT | ASTP_OUT_SHAPE;
$<y_attributes>$.bounds = NULL; }
/* Type, Field, Parameter Attributes */
| V1_ARRAY_KW { $<y_attributes>$.attr_flags = ASTP_SMALL;
$<y_attributes>$.bounds = NULL; }
| STRING_KW { $<y_attributes>$.attr_flags = ASTP_STRING;
$<y_attributes>$.bounds = NULL; }
| V1_STRING_KW { $<y_attributes>$.attr_flags = ASTP_STRING0;
$<y_attributes>$.bounds = NULL; }
| UNIQUE_KW { $<y_attributes>$.attr_flags = ASTP_UNIQUE;
$<y_attributes>$.bounds = NULL; }
| REF_KW { $<y_attributes>$.attr_flags = ASTP_REF;
$<y_attributes>$.bounds = NULL; }
| IGNORE_KW { $<y_attributes>$.attr_flags = ASTP_IGNORE;
$<y_attributes>$.bounds = NULL; }
| CONTEXT_HANDLE_KW { $<y_attributes>$.attr_flags = ASTP_CONTEXT;
$<y_attributes>$.bounds = NULL; }
/* Type-only Attribute(s) */
| V1_STRUCT_KW { $<y_attributes>$.attr_flags = ASTP_UNALIGN;
$<y_attributes>$.bounds = NULL; }
| V1_ENUM_KW { $<y_attributes>$.attr_flags = ASTP_V1_ENUM;
$<y_attributes>$.bounds = NULL; }
| ALIGN_KW LPAREN SMALL_KW RPAREN
{ $<y_attributes>$.attr_flags = ASTP_ALIGN_SMALL;
$<y_attributes>$.bounds = NULL; }
| ALIGN_KW LPAREN SHORT_KW RPAREN
{ $<y_attributes>$.attr_flags = ASTP_ALIGN_SHORT;
$<y_attributes>$.bounds = NULL; }
| ALIGN_KW LPAREN LONG_KW RPAREN
{ $<y_attributes>$.attr_flags = ASTP_ALIGN_LONG;
$<y_attributes>$.bounds = NULL; }
| ALIGN_KW LPAREN HYPER_KW RPAREN
{ $<y_attributes>$.attr_flags = ASTP_ALIGN_HYPER;
$<y_attributes>$.bounds = NULL; }
| HANDLE_KW { $<y_attributes>$.attr_flags = ASTP_HANDLE;
$<y_attributes>$.bounds = NULL; }
| TRANSMIT_AS_KW LPAREN simple_type_spec RPAREN
{ $<y_attributes>$.attr_flags = ASTP_TRANSMIT_AS;
$<y_attributes>$.bounds = NULL;
ASTP_transmit_as_type = $<y_type>3;
}
| SWITCH_TYPE_KW LPAREN simple_type_spec RPAREN
{ $<y_attributes>$.attr_flags = ASTP_SWITCH_TYPE;
$<y_attributes>$.bounds = NULL;
ASTP_switch_type = $<y_type>3;
}
/* Arm-only Attribute(s) */
| CASE_KW LPAREN ne_union_case_list RPAREN
{ $<y_attributes>$.attr_flags = ASTP_CASE;
$<y_attributes>$.bounds = NULL;
ASTP_case = $<y_label>3;
}
| DEFAULT_KW { $<y_attributes>$.attr_flags = ASTP_DEFAULT;
$<y_attributes>$.bounds = NULL;
}
| IDENTIFIER /* Not an attribute, so give an error */
{
char *identifier; /* place to receive the identifier text */
NAMETABLE_id_to_string ($<y_id>1, &identifier);
log_error (yylineno, NIDL_UNKNOWNATTR, identifier);
$<y_attributes>$.attr_flags = 0;
$<y_attributes>$.bounds = NULL;
}
;
/********************************************************************/
/* */
/* Compiletime Integer expression evaluation */
/* */
/********************************************************************/
expression: conditional_expression
{$<y_exp>$ = $<y_exp>1;}
;
conditional_expression:
logical_OR_expression
{$<y_exp>$ = $<y_exp>1;}
| logical_OR_expression QUESTION expression COLON conditional_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
ASTP_validate_integer(&$<y_exp>5);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer ? $<y_exp>3.val.integer : $<y_exp>5.val.integer;
}
;
logical_OR_expression:
logical_AND_expression
{$<y_exp>$ = $<y_exp>1;}
| logical_OR_expression BARBAR logical_AND_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer || $<y_exp>3.val.integer;
}
;
logical_AND_expression:
inclusive_OR_expression
{$<y_exp>$ = $<y_exp>1;}
| logical_AND_expression AMPAMP inclusive_OR_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>2.val.integer && $<y_exp>3.val.integer;
}
;
inclusive_OR_expression:
exclusive_OR_expression
{$<y_exp>$ = $<y_exp>1;}
| inclusive_OR_expression BAR exclusive_OR_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer | $<y_exp>3.val.integer;
}
;
exclusive_OR_expression:
AND_expression
{$<y_exp>$ = $<y_exp>1;}
| exclusive_OR_expression CARET AND_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer ^ $<y_exp>3.val.integer;
}
;
AND_expression:
equality_expression
{$<y_exp>$ = $<y_exp>1;}
| AND_expression AMP equality_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer & $<y_exp>3.val.integer;
}
;
equality_expression:
relational_expression
{$<y_exp>$ = $<y_exp>1;}
| equality_expression EQUALEQUAL relational_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer == $<y_exp>3.val.integer;
}
| equality_expression NOTEQUAL relational_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer != $<y_exp>3.val.integer;
}
;
relational_expression:
shift_expression
{$<y_exp>$ = $<y_exp>1;}
| relational_expression LANGLE shift_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer < $<y_exp>3.val.integer;
}
| relational_expression RANGLE shift_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer > $<y_exp>3.val.integer;
}
| relational_expression LESSEQUAL shift_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer <= $<y_exp>3.val.integer;
}
| relational_expression GREATEREQUAL shift_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer >= $<y_exp>3.val.integer;
}
;
shift_expression:
additive_expression
{$<y_exp>$ = $<y_exp>1;}
| shift_expression LANGLEANGLE additive_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer << $<y_exp>3.val.integer;
}
| shift_expression RANGLEANGLE additive_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer >> $<y_exp>3.val.integer;
}
;
additive_expression:
multiplicative_expression
{$<y_exp>$ = $<y_exp>1;}
| additive_expression PLUS multiplicative_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer + $<y_exp>3.val.integer;
if (($<y_exp>$.val.integer < $<y_exp>1.val.integer) &&
($<y_exp>$.val.integer < $<y_exp>3.val.integer))
log_error (yylineno, NIDL_INTOVERFLOW, KEYWORDS_lookup_text(LONG_KW));
}
| additive_expression MINUS multiplicative_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer - $<y_exp>3.val.integer;
}
;
multiplicative_expression:
cast_expression
{$<y_exp>$ = $<y_exp>1;}
| multiplicative_expression STAR cast_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>1.val.integer * $<y_exp>3.val.integer;
if (($<y_exp>$.val.integer < $<y_exp>1.val.integer) &&
($<y_exp>$.val.integer < $<y_exp>3.val.integer))
log_error (yylineno, NIDL_INTOVERFLOW, KEYWORDS_lookup_text(LONG_KW));
}
| multiplicative_expression SLASH cast_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
if ($<y_exp>3.val.integer != 0)
$<y_exp>$.val.integer = $<y_exp>1.val.integer / $<y_exp>3.val.integer;
else
log_error (yylineno, NIDL_INTDIVBY0);
}
| multiplicative_expression PERCENT cast_expression
{
ASTP_validate_integer(&$<y_exp>1);
ASTP_validate_integer(&$<y_exp>3);
$<y_exp>$.type = AST_int_const_k;
if ($<y_exp>3.val.integer != 0)
$<y_exp>$.val.integer = $<y_exp>1.val.integer % $<y_exp>3.val.integer;
else
log_error (yylineno, NIDL_INTDIVBY0);
}
;
cast_expression: unary_expression
{$<y_exp>$ = $<y_exp>1;}
;
unary_expression:
primary_expression
{$<y_exp>$ = $<y_exp>1;}
| PLUS primary_expression
{
ASTP_validate_integer(&$<y_exp>2);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_exp>2.val.integer;
}
| MINUS primary_expression
{
ASTP_validate_integer(&$<y_exp>2);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = -$<y_exp>2.val.integer;
}
| TILDE primary_expression
{
ASTP_validate_integer(&$<y_exp>2);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = ~$<y_exp>2.val.integer;
}
| NOT primary_expression
{
ASTP_validate_integer(&$<y_exp>2);
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = !$<y_exp>2.val.integer;
}
;
primary_expression:
LPAREN expression RPAREN
{ $<y_exp>$ = $<y_exp>2; }
| INTEGER_NUMERIC
{
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = $<y_ival>1;
}
| CHAR
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_char_constant ($<y_char>1) ;
}
| IDENTIFIER
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_named_constant($<y_id>1) ;
}
| STRING
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_string_constant ($<y_string>1) ;
}
| NULL_KW
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_null_constant() ;
}
| TRUE_KW
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_boolean_constant(true) ;
}
| FALSE_KW
{
$<y_exp>$.type = AST_nil_const_k;
$<y_exp>$.val.other = AST_boolean_constant(false) ;
}
| FLOAT_NUMERIC
{
$<y_exp>$.type = AST_int_const_k;
$<y_exp>$.val.integer = 0;
log_error(yylineno, NIDL_FLOATCONSTNOSUP);
}
;
%%