/* YACC grammar for Chill expressions, for GDB.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
%{
#include "defs.h"
+#include <string.h>
+#include <ctype.h>
#include "expression.h"
#include "language.h"
#include "value.h"
#include "parser-defs.h"
#include "ch-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
#define yypgo chill_pgo
#define yyact chill_act
#define yyexca chill_exca
-#define yyerrflag chill_errflag
-#define yynerrs chill_nerrs
+#define yyerrflag chill_errflag
+#define yynerrs chill_nerrs
#define yyps chill_ps
#define yypv chill_pv
#define yys chill_s
#define yy_yyv chill_yyv
#define yyval chill_val
#define yylloc chill_lloc
-#define yyreds chill_reds /* With YYDEBUG defined */
-#define yytoks chill_toks /* With YYDEBUG defined */
+#define yyreds chill_reds /* With YYDEBUG defined */
+#define yytoks chill_toks /* With YYDEBUG defined */
+#define yylhs chill_yylhs
+#define yylen chill_yylen
+#define yydefred chill_yydefred
+#define yydgoto chill_yydgoto
+#define yysindex chill_yysindex
+#define yyrindex chill_yyrindex
+#define yygindex chill_yygindex
+#define yytable chill_yytable
+#define yycheck chill_yycheck
#ifndef YYDEBUG
#define YYDEBUG 0 /* Default to no yydebug support */
int *ivec;
}
-%token <voidval> FIXME
-
%token <typed_val> INTEGER_LITERAL
%token <ulval> BOOLEAN_LITERAL
%token <typed_val> CHARACTER_LITERAL
%token <dval> FLOAT_LITERAL
%token <ssym> GENERAL_PROCEDURE_NAME
%token <ssym> LOCATION_NAME
-%token <voidval> SET_LITERAL
%token <voidval> EMPTINESS_LITERAL
-%token <voidval> CHARACTER_STRING_LITERAL
-%token <voidval> BIT_STRING_LITERAL
+%token <sval> CHARACTER_STRING_LITERAL
+%token <sval> BIT_STRING_LITERAL
+%token <tsym> TYPENAME
+%token <sval> FIELD_NAME
-%token <voidval> STRING
-%token <voidval> CONSTANT
%token <voidval> '.'
%token <voidval> ';'
%token <voidval> ':'
%token <voidval> NOT
%token <voidval> POINTER
%token <voidval> RECEIVE
-%token <voidval> SC
%token <voidval> '['
%token <voidval> ']'
%token <voidval> '('
%token <voidval> FI
%token <voidval> ELSIF
%token <voidval> ILLEGAL_TOKEN
+%token <voidval> NUM
+%token <voidval> PRED
+%token <voidval> SUCC
+%token <voidval> ABS
+%token <voidval> CARD
+%token <voidval> MAX_TOKEN
+%token <voidval> MIN_TOKEN
+%token <voidval> ADDR_TOKEN
+%token <voidval> SIZE
+%token <voidval> UPPER
+%token <voidval> LOWER
+%token <voidval> LENGTH
+%token <voidval> ARRAY
/* Tokens which are not Chill tokens used in expressions, but rather GDB
specific things that we recognize in the same context as Chill tokens
%token <ivar> GDB_VARIABLE /* Convenience variable */
%token <voidval> GDB_ASSIGNMENT /* Assign value to somewhere */
-%type <voidval> location
%type <voidval> access_name
%type <voidval> primitive_value
-%type <voidval> location_contents
%type <voidval> value_name
%type <voidval> literal
%type <voidval> tuple
-%type <voidval> value_string_element
-%type <voidval> value_string_slice
-%type <voidval> value_array_element
-%type <voidval> value_array_slice
-%type <voidval> value_structure_field
+%type <voidval> slice
%type <voidval> expression_conversion
-%type <voidval> value_procedure_call
%type <voidval> value_built_in_routine_call
-%type <voidval> start_expression
-%type <voidval> zero_adic_operator
%type <voidval> parenthesised_expression
%type <voidval> value
-%type <voidval> undefined_value
%type <voidval> expression
%type <voidval> conditional_expression
%type <voidval> then_alternative
%type <voidval> else_alternative
-%type <voidval> sub_expression
-%type <voidval> value_case_alternative
%type <voidval> operand_0
%type <voidval> operand_1
%type <voidval> operand_2
%type <voidval> operand_4
%type <voidval> operand_5
%type <voidval> operand_6
-%type <voidval> integer_literal_expression
-%type <voidval> synonym_name
-%type <voidval> value_enumeration_name
-%type <voidval> value_do_with_name
-%type <voidval> value_receive_name
-%type <voidval> string_primitive_value
-%type <voidval> start_element
-%type <voidval> left_element
-%type <voidval> right_element
-%type <voidval> slice_size
-%type <voidval> array_primitive_value
%type <voidval> expression_list
-%type <voidval> lower_element
-%type <voidval> upper_element
-%type <voidval> first_element
-%type <voidval> structure_primitive_value
-%type <voidval> field_name
-%type <voidval> mode_name
-%type <voidval> boolean_expression
-%type <voidval> case_selector_list
-%type <voidval> subexpression
-%type <voidval> case_label_specification
-%type <voidval> buffer_location
-
+%type <tval> mode_argument
%type <voidval> single_assignment_action
+%type <tsym> mode_name
+%type <lval> rparen
+
+/* Not implemented:
+%type <voidval> undefined_value
+%type <voidval> array_mode_name
+%type <voidval> string_mode_name
+%type <voidval> variant_structure_mode_name
+*/
%%
/* Z.200, 5.3.1 */
+start : value { }
+ | mode_name
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1.type);
+ write_exp_elt_opcode(OP_TYPE);}
+ ;
+
value : expression
- {
- $$ = 0; /* FIXME */
- }
+/*
| undefined_value
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-undefined_value : FIXME
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-/* Z.200, 4.2.1 */
-
-location : access_name
- {
- $$ = 0; /* FIXME */
- }
- | FIXME
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
+*/
;
/* Z.200, 4.2.2 */
access_name : LOCATION_NAME
{
write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
write_exp_elt_intern ($1);
write_exp_elt_opcode (OP_INTERNALVAR);
}
- | FIXME
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 4.2.8 */
{
arglist_len++;
}
+ ;
-/* Z.200, 5.2.1 */
-
-primitive_value : location_contents
- {
- $$ = 0; /* FIXME */
- }
- | value_name
- {
- $$ = 0; /* FIXME */
- }
- | literal
+maybe_expression_list: /* EMPTY */
{
- $$ = 0; /* FIXME */
+ arglist_len = 0;
}
- | tuple
- {
- $$ = 0; /* FIXME */
- }
- | value_string_element
- {
- $$ = 0; /* FIXME */
- }
- | value_string_slice
+ | expression_list
+ ;
+
+
+/* Z.200, 5.2.1 */
+
+primitive_value_lparen: primitive_value '('
+ /* This is to save the value of arglist_len
+ being accumulated for each dimension. */
+ { start_arglist (); }
+ ;
+
+rparen : ')'
+ { $$ = end_arglist (); }
+ ;
+
+primitive_value :
+ access_name
+ | primitive_value_lparen maybe_expression_list rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ($3);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
}
- | value_array_element
- {
- $$ = 0; /* FIXME */
+ | primitive_value FIELD_NAME
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($2);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
}
- | value_array_slice
+ | primitive_value POINTER
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_IND);
}
- | value_structure_field
+ | primitive_value POINTER mode_name
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (lookup_pointer_type ($3.type));
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_opcode (UNOP_IND);
}
+ | value_name
+ | literal
+ | tuple
+ | slice
| expression_conversion
- {
- $$ = 0; /* FIXME */
- }
- | value_procedure_call
- {
- $$ = 0; /* FIXME */
- }
| value_built_in_routine_call
- {
- $$ = 0; /* FIXME */
- }
+/*
| start_expression
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
| zero_adic_operator
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
+*/
| parenthesised_expression
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-/* Z.200, 5.2.2 */
-
-location_contents: location
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 5.2.3 */
-value_name : synonym_name
- {
- $$ = 0; /* FIXME */
- }
- | value_enumeration_name
- {
- $$ = 0; /* FIXME */
- }
- | value_do_with_name
- {
- $$ = 0; /* FIXME */
- }
- | value_receive_name
- {
- $$ = 0; /* FIXME */
- }
- | GENERAL_PROCEDURE_NAME
+value_name : GENERAL_PROCEDURE_NAME
{
write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
write_exp_elt_dblcst ($1);
write_exp_elt_opcode (OP_DOUBLE);
}
- | SET_LITERAL
- {
- $$ = 0; /* FIXME */
- }
| EMPTINESS_LITERAL
{
- $$ = 0; /* FIXME */
+ struct type *void_ptr_type
+ = lookup_pointer_type (builtin_type_void);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (void_ptr_type);
+ write_exp_elt_longcst (0);
+ write_exp_elt_opcode (OP_LONG);
}
| CHARACTER_STRING_LITERAL
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
}
| BIT_STRING_LITERAL
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_BITSTRING);
+ write_exp_bitstring ($1);
+ write_exp_elt_opcode (OP_BITSTRING);
}
;
/* Z.200, 5.2.5 */
-tuple : FIXME
- {
- $$ = 0; /* FIXME */
- }
+tuple_element : expression
+ | named_record_element
;
-
-/* Z.200, 5.2.6 */
-
-value_string_element: string_primitive_value '(' start_element ')'
- {
- $$ = 0; /* FIXME */
+named_record_element: FIELD_NAME ',' named_record_element
+ { write_exp_elt_opcode (OP_LABELED);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_LABELED);
+ }
+ | FIELD_NAME ':' expression
+ { write_exp_elt_opcode (OP_LABELED);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_LABELED);
}
;
-/* Z.200, 5.2.7 */
-
-value_string_slice: string_primitive_value '(' left_element ':' right_element ')'
+tuple_elements : tuple_element
{
- $$ = 0; /* FIXME */
+ arglist_len = 1;
}
- | string_primitive_value '(' start_element UP slice_size ')'
+ | tuple_elements ',' tuple_element
{
- $$ = 0; /* FIXME */
+ arglist_len++;
}
;
-/* Z.200, 5.2.8 */
-
-value_array_element: array_primitive_value '('
- /* This is to save the value of arglist_len
- being accumulated for each dimension. */
- { start_arglist (); }
- expression_list ')'
- {
- write_exp_elt_opcode (MULTI_SUBSCRIPT);
- write_exp_elt_longcst ((LONGEST) end_arglist ());
- write_exp_elt_opcode (MULTI_SUBSCRIPT);
- }
+maybe_tuple_elements : tuple_elements
+ | /* EMPTY */
;
-/* Z.200, 5.2.9 */
-
-value_array_slice: array_primitive_value '(' lower_element ':' upper_element ')'
+tuple : '['
+ { start_arglist (); }
+ maybe_tuple_elements ']'
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
}
- | array_primitive_value '(' first_element UP slice_size ')'
+ |
+ mode_name '['
+ { start_arglist (); }
+ maybe_tuple_elements ']'
{
- $$ = 0; /* FIXME */
- }
- ;
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
-/* Z.200, 5.2.10 */
-
-value_structure_field: structure_primitive_value '.' field_name
- {
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_opcode (UNOP_CAST);
}
;
-/* Z.200, 5.2.11 */
-expression_conversion: mode_name '(' expression ')'
- {
- $$ = 0; /* FIXME */
- }
- ;
+/* Z.200, 5.2.6 */
-/* Z.200, 5.2.12 */
-value_procedure_call: FIXME
+slice: primitive_value_lparen expression ':' expression rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (TERNOP_SLICE);
}
- ;
-
-/* Z.200, 5.2.13 */
-
-value_built_in_routine_call: FIXME
+ | primitive_value_lparen expression UP expression rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (TERNOP_SLICE_COUNT);
}
;
-/* Z.200, 5.2.14 */
-
-start_expression: FIXME
- {
- $$ = 0; /* FIXME */
- } /* Not in GNU-Chill */
- ;
-
-/* Z.200, 5.2.15 */
+/* Z.200, 5.2.11 */
-zero_adic_operator: FIXME
+expression_conversion: mode_name parenthesised_expression
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+ | ARRAY '(' ')' mode_name parenthesised_expression
+ /* This is pseudo-Chill, similar to C's '(TYPE[])EXPR'
+ which casts to an artificial array. */
+ {
+ struct type *range_type
+ = create_range_type ((struct type *) NULL,
+ builtin_type_int, 0, 0);
+ struct type *array_type
+ = create_array_type ((struct type *) NULL,
+ $4.type, range_type);
+ TYPE_ARRAY_UPPER_BOUND_TYPE(array_type)
+ = BOUND_CANNOT_BE_DETERMINED;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (array_type);
+ write_exp_elt_opcode (UNOP_CAST);
}
;
/* Z.200, 5.2.16 */
parenthesised_expression: '(' expression ')'
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 5.3.2 */
expression : operand_0
- {
- $$ = 0; /* FIXME */
- }
+ | single_assignment_action
| conditional_expression
- {
- $$ = 0; /* FIXME */
- }
;
-conditional_expression : IF boolean_expression then_alternative else_alternative FI
- {
- $$ = 0; /* FIXME */
- }
- | CASE case_selector_list OF value_case_alternative '[' ELSE sub_expression ']' ESAC
- {
- $$ = 0; /* FIXME */
- }
+conditional_expression : IF expression then_alternative else_alternative FI
+ { write_exp_elt_opcode (TERNOP_COND); }
+/*
+ | CASE case_selector_list OF value_case_alternative ELSE expression ESAC
+ { error ("not implemented: CASE expression" }
+*/
;
-then_alternative: THEN subexpression
- {
- $$ = 0; /* FIXME */
- }
+then_alternative: THEN expression
;
-else_alternative: ELSE subexpression
- {
- $$ = 0; /* FIXME */
- }
- | ELSIF boolean_expression then_alternative else_alternative
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-sub_expression : expression
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-value_case_alternative: case_label_specification ':' sub_expression ';'
- {
- $$ = 0; /* FIXME */
- }
+else_alternative: ELSE expression
+ | ELSIF expression then_alternative else_alternative
+ { write_exp_elt_opcode (TERNOP_COND); }
;
/* Z.200, 5.3.3 */
operand_0 : operand_1
- {
- $$ = 0; /* FIXME */
- }
| operand_0 LOGIOR operand_1
{
write_exp_elt_opcode (BINOP_BITWISE_IOR);
}
| operand_0 ORIF operand_1
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_LOGICAL_OR);
}
| operand_0 LOGXOR operand_1
{
write_exp_elt_opcode (BINOP_BITWISE_XOR);
}
- | single_assignment_action
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 5.3.4 */
operand_1 : operand_2
- {
- $$ = 0; /* FIXME */
- }
| operand_1 LOGAND operand_2
{
write_exp_elt_opcode (BINOP_BITWISE_AND);
}
| operand_1 ANDIF operand_2
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_LOGICAL_AND);
}
;
/* Z.200, 5.3.5 */
operand_2 : operand_3
- {
- $$ = 0; /* FIXME */
- }
| operand_2 '=' operand_3
{
write_exp_elt_opcode (BINOP_EQUAL);
}
| operand_2 IN operand_3
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_IN);
}
;
/* Z.200, 5.3.6 */
operand_3 : operand_4
- {
- $$ = 0; /* FIXME */
- }
| operand_3 '+' operand_4
{
write_exp_elt_opcode (BINOP_ADD);
}
| operand_3 SLASH_SLASH operand_4
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_CONCAT);
}
;
/* Z.200, 5.3.7 */
operand_4 : operand_5
- {
- $$ = 0; /* FIXME */
- }
| operand_4 '*' operand_5
{
write_exp_elt_opcode (BINOP_MUL);
/* Z.200, 5.3.8 */
operand_5 : operand_6
- {
- $$ = 0; /* FIXME */
- }
| '-' operand_6
{
write_exp_elt_opcode (UNOP_NEG);
{
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
}
- | '(' integer_literal_expression ')' operand_6
+ | parenthesised_expression literal
+/* We require the string operand to be a literal, to avoid some
+ nasty parsing ambiguities. */
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_CONCAT);
}
;
/* Z.200, 5.3.9 */
-operand_6 : POINTER location
+operand_6 : POINTER primitive_value
{
- $$ = 0; /* FIXME */
- }
- | RECEIVE buffer_location
- {
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
}
+ | RECEIVE expression
+ { error ("not implemented: RECEIVE expression"); }
| primitive_value
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 6.2 */
-single_assignment_action : location GDB_ASSIGNMENT value
+single_assignment_action :
+ primitive_value GDB_ASSIGNMENT value
{
write_exp_elt_opcode (BINOP_ASSIGN);
}
+ ;
-/* Z.200, 12.4.3 */
-/* FIXME: For now we just accept only a single integer literal. */
+/* Z.200, 6.20.3 */
+
+value_built_in_routine_call :
+ NUM '(' expression ')'
+ {
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+ | PRED '(' expression ')'
+ { error ("not implemented: PRED builtin function"); }
+ | SUCC '(' expression ')'
+ { error ("not implemented: SUCC builtin function"); }
+ | ADDR_TOKEN '(' expression ')'
+ { write_exp_elt_opcode (UNOP_ADDR); }
+ | ABS '(' expression ')'
+ { error ("not implemented: ABS builtin function"); }
+ | CARD '(' expression ')'
+ { error ("not implemented: CARD builtin function"); }
+ | MAX_TOKEN '(' expression ')'
+ { error ("not implemented: MAX builtin function"); }
+ | MIN_TOKEN '(' expression ')'
+ { error ("not implemented: MIN builtin function"); }
+ | SIZE '(' expression ')'
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ | SIZE '(' mode_argument ')'
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ | LOWER '(' mode_argument ')'
+ { write_lower_upper_value (UNOP_LOWER, $3); }
+ | UPPER '(' mode_argument ')'
+ { write_lower_upper_value (UNOP_UPPER, $3); }
+ | LOWER '(' expression ')'
+ { write_exp_elt_opcode (UNOP_LOWER); }
+ | UPPER '(' expression ')'
+ { write_exp_elt_opcode (UNOP_UPPER); }
+ | LENGTH '(' expression ')'
+ { write_exp_elt_opcode (UNOP_LENGTH); }
+ ;
-integer_literal_expression:
- INTEGER_LITERAL
+mode_argument : mode_name
{
- $$ = 0;
+ $$ = $1.type;
}
+/*
+ | array_mode_name '(' expression ')'
+ { ??? }
+ | string_mode_name '(' expression ')'
+ { ??? }
+ | variant_structure_mode_name '(' expression_list ')'
+ { ??? }
+*/
+ ;
-/* Z.200, 12.4.3 */
+mode_name : TYPENAME
+ ;
-array_primitive_value : primitive_value
- {
- $$ = 0;
- }
+%%
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. */
-/* Things which still need productions... */
-
-synonym_name : FIXME { $$ = 0; }
-value_enumeration_name : FIXME { $$ = 0; }
-value_do_with_name : FIXME { $$ = 0; }
-value_receive_name : FIXME { $$ = 0; }
-string_primitive_value : FIXME { $$ = 0; }
-start_element : FIXME { $$ = 0; }
-left_element : FIXME { $$ = 0; }
-right_element : FIXME { $$ = 0; }
-slice_size : FIXME { $$ = 0; }
-lower_element : FIXME { $$ = 0; }
-upper_element : FIXME { $$ = 0; }
-first_element : FIXME { $$ = 0; }
-structure_primitive_value: FIXME { $$ = 0; }
-field_name : FIXME { $$ = 0; }
-mode_name : FIXME { $$ = 0; }
-boolean_expression : FIXME { $$ = 0; }
-case_selector_list : FIXME { $$ = 0; }
-subexpression : FIXME { $$ = 0; }
-case_label_specification: FIXME { $$ = 0; }
-buffer_location : FIXME { $$ = 0; }
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
-%%
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ {
+ tempbuf = (char *) malloc (tempbufsize);
+ }
+ else
+ {
+ tempbuf = (char *) realloc (tempbuf, tempbufsize);
+ }
+}
/* Try to consume a simple name string token. If successful, returns
a pointer to a nullbyte terminated copy of the name that can be used
{
char *tokptr = lexptr;
- if (isalpha (*tokptr))
+ if (isalpha (*tokptr) || *tokptr == '_')
{
+ char *result;
do {
tokptr++;
- } while (isalpha (*tokptr) || isdigit (*tokptr) || (*tokptr == '_'));
+ } while (isalnum (*tokptr) || (*tokptr == '_'));
yylval.sval.ptr = lexptr;
yylval.sval.length = tokptr - lexptr;
lexptr = tokptr;
- return (copy_name (yylval.sval));
+ result = copy_name (yylval.sval);
+ return result;
}
return (NULL);
}
while (*tokptr != '\0')
{
- temp = tolower (*tokptr);
+ temp = *tokptr;
+ if (isupper (temp))
+ temp = tolower (temp);
tokptr++;
switch (temp)
{
char *tokptr = lexptr;
char *buf;
char *copy;
- char ch;
double dval;
extern double strtod ();
return (0);
}
+/* Recognize a string literal. A string literal is a sequence
+ of characters enclosed in matching single or double quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. "this""is""one""string") */
+
+static int
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ {
+ tokptr++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ tempbuf[tempbufindex++] = *tokptr;
+ }
+ if (*tokptr == '\0' /* no terminator */
+ || (tempbufindex == 1 && *tokptr == '\'')) /* char literal */
+ {
+ return (0);
+ }
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return (CHARACTER_STRING_LITERAL);
+ }
+}
+
/* Recognize a character literal. A character literal is single character
or a control sequence, enclosed in single quotes. A control sequence
is a comma separated list of one or more integer literals, enclosed
As a GNU chill extension, the syntax C'xx' is also recognized as a
character literal, where xx is a hex value for the character.
+ Note that more than a single character, enclosed in single quotes, is
+ a string literal.
+
+ Also note that the control sequence form is not in GNU Chill since it
+ is ambiguous with the string literal form using single quotes. I.E.
+ is '^(7)' a character literal or a string literal. In theory it it
+ possible to tell by context, but GNU Chill doesn't accept the control
+ sequence form, so neither do we (for now the code is disabled).
+
Returns CHARACTER_LITERAL if a match is found.
*/
char *tokptr = lexptr;
int ival = 0;
- if ((tolower (*tokptr) == 'c') && (*(tokptr + 1) == '\''))
+ if ((*tokptr == 'c' || *tokptr == 'C') && (*(tokptr + 1) == '\''))
{
/* We have a GNU chill extension form, so skip the leading "C'",
decode the hex value, and then ensure that we have a trailing
if ((*tokptr == '^') && (*(tokptr + 1) == '('))
{
+#if 0 /* Disable, see note above. -fnf */
/* Match and decode a control sequence. Return zero if we don't
find a valid integer literal, or if the next unconsumed character
after the integer literal is not the trailing ')'.
{
return (0);
}
+#else
+ return (0);
+#endif
}
else
{
}
}
+/* Recognize a bit-string literal, as specified in Z.200 sec 5.2.4.8
+ Note that according to 5.2.4.8, a single "_" is also a valid bit-string
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any bit-string literal. */
+
+static int
+match_bitstring_literal ()
+{
+ register char *tokptr = lexptr;
+ int bitoffset = 0;
+ int bitcount = 0;
+ int bits_per_char;
+ int digit;
+
+ tempbufindex = 0;
+ CHECKBUF (1);
+ tempbuf[0] = 0;
+
+ /* Look for the required explicit base specifier. */
+
+ switch (*tokptr++)
+ {
+ case 'b':
+ case 'B':
+ bits_per_char = 1;
+ break;
+ case 'o':
+ case 'O':
+ bits_per_char = 3;
+ break;
+ case 'h':
+ case 'H':
+ bits_per_char = 4;
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* Ensure that the character after the explicit base is a single quote. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+
+ while (*tokptr != '\0' && *tokptr != '\'')
+ {
+ digit = *tokptr;
+ if (isupper (digit))
+ digit = tolower (digit);
+ tokptr++;
+ switch (digit)
+ {
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ digit -= '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ digit -= 'a';
+ digit += 10;
+ break;
+ default:
+ return (0);
+ break;
+ }
+ if (digit >= 1 << bits_per_char)
+ {
+ /* Found something not in domain for current base. */
+ return (0);
+ }
+ else
+ {
+ /* Extract bits from digit, packing them into the bitstring byte. */
+ int k = TARGET_BYTE_ORDER == BIG_ENDIAN ? bits_per_char - 1 : 0;
+ for (; TARGET_BYTE_ORDER == BIG_ENDIAN ? k >= 0 : k < bits_per_char;
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? k-- : k++)
+ {
+ bitcount++;
+ if (digit & (1 << k))
+ {
+ tempbuf[tempbufindex] |=
+ (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ ? (1 << (HOST_CHAR_BIT - 1 - bitoffset))
+ : (1 << bitoffset);
+ }
+ bitoffset++;
+ if (bitoffset == HOST_CHAR_BIT)
+ {
+ bitoffset = 0;
+ tempbufindex++;
+ CHECKBUF(1);
+ tempbuf[tempbufindex] = 0;
+ }
+ }
+ }
+ }
+
+ /* Verify that we consumed everything up to the trailing single quote,
+ and that we found some bits (IE not just underbars). */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = bitcount;
+ lexptr = tokptr;
+ return (BIT_STRING_LITERAL);
+ }
+}
+
/* Recognize tokens that start with '$'. These include:
$regname A native register name or a "standard
&& !isalnum (tokptr[namelength]))
{
yylval.lval = regno;
- lexptr += namelength + 1;
+ lexptr += namelength;
return (GDB_REGNAME);
}
}
int token;
};
-static const struct token tokentab5[] =
-{
- { "ANDIF", ANDIF }
-};
-
-static const struct token tokentab4[] =
-{
- { "ORIF", ORIF }
-};
-
-static const struct token tokentab3[] =
+static const struct token idtokentab[] =
{
- { "MOD", MOD },
- { "REM", REM },
- { "NOT", NOT },
- { "XOR", LOGXOR },
- { "AND", LOGAND }
+ { "array", ARRAY },
+ { "length", LENGTH },
+ { "lower", LOWER },
+ { "upper", UPPER },
+ { "andif", ANDIF },
+ { "pred", PRED },
+ { "succ", SUCC },
+ { "card", CARD },
+ { "size", SIZE },
+ { "orif", ORIF },
+ { "num", NUM },
+ { "abs", ABS },
+ { "max", MAX_TOKEN },
+ { "min", MIN_TOKEN },
+ { "mod", MOD },
+ { "rem", REM },
+ { "not", NOT },
+ { "xor", LOGXOR },
+ { "and", LOGAND },
+ { "in", IN },
+ { "or", LOGIOR },
+ { "up", UP },
+ { "addr", ADDR_TOKEN },
+ { "null", EMPTINESS_LITERAL }
};
static const struct token tokentab2[] =
{
{ ":=", GDB_ASSIGNMENT },
{ "//", SLASH_SLASH },
+ { "->", POINTER },
{ "/=", NOTEQUAL },
{ "<=", LEQ },
- { ">=", GTR },
- { "IN", IN },
- { "OR", LOGIOR }
+ { ">=", GTR }
};
/* Read one token, getting characters through lexptr. */
{
unsigned int i;
int token;
- char *simplename;
+ char *inputname;
struct symbol *sym;
/* Skip over any leading whitespace. */
case ';':
case '!':
case '+':
- case '-':
case '*':
- case '/':
case '(':
case ')':
case '[':
}
/* Look for characters which start a particular kind of multicharacter
token, such as a character literal, register name, convenience
- variable name, etc. */
+ variable name, string literal, etc. */
switch (*lexptr)
{
+ case '\'':
+ case '\"':
+ /* First try to match a string literal, which is any
+ sequence of characters enclosed in matching single or double
+ quotes, except that a single character inside single quotes
+ is a character literal, so we have to catch that case also. */
+ token = match_string_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ if (*lexptr == '\'')
+ {
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ }
+ break;
case 'C':
case 'c':
- case '\'':
token = match_character_literal ();
if (token != 0)
{
}
break;
}
- /* See if it is a special token of length 5. */
- for (i = 0; i < sizeof (tokentab5) / sizeof (tokentab5[0]); i++)
- {
- if (STREQN (lexptr, tokentab5[i].operator, 5))
- {
- lexptr += 5;
- return (tokentab5[i].token);
- }
- }
- /* See if it is a special token of length 4. */
- for (i = 0; i < sizeof (tokentab4) / sizeof (tokentab4[0]); i++)
- {
- if (STREQN (lexptr, tokentab4[i].operator, 4))
- {
- lexptr += 4;
- return (tokentab4[i].token);
- }
- }
- /* See if it is a special token of length 3. */
- for (i = 0; i < sizeof (tokentab3) / sizeof (tokentab3[0]); i++)
- {
- if (STREQN (lexptr, tokentab3[i].operator, 3))
- {
- lexptr += 3;
- return (tokentab3[i].token);
- }
- }
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
{
would already have found it. */
switch (*lexptr)
{
+ case '-':
case ':':
case '/':
case '<':
case '>':
return (*lexptr++);
}
- /* Look for other special tokens. */
- if (STREQN (lexptr, "TRUE", 4)) /* FIXME: What about lowercase? */
- {
- yylval.ulval = 1;
- lexptr += 4;
- return (BOOLEAN_LITERAL);
- }
- if (STREQN (lexptr, "FALSE", 5)) /* FIXME: What about lowercase? */
- {
- yylval.ulval = 0;
- lexptr += 5;
- return (BOOLEAN_LITERAL);
- }
/* Look for a float literal before looking for an integer literal, so
we match as much of the input stream as possible. */
token = match_float_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ token = match_bitstring_literal ();
if (token != 0)
{
return (token);
the token from lexptr, so we can't back out if we later find that
we can't classify what sort of name it is. */
- simplename = match_simple_name_string ();
- if (simplename != NULL)
+ inputname = match_simple_name_string ();
+
+ if (inputname != NULL)
{
- sym = lookup_symbol (simplename, expression_context_block,
+ char *simplename = (char*) alloca (strlen (inputname) + 1);
+
+ char *dptr = simplename, *sptr = inputname;
+ for (; *sptr; sptr++)
+ *dptr++ = isupper (*sptr) ? tolower(*sptr) : *sptr;
+ *dptr = '\0';
+
+ /* See if it is a reserved identifier. */
+ for (i = 0; i < sizeof (idtokentab) / sizeof (idtokentab[0]); i++)
+ {
+ if (STREQ (simplename, idtokentab[i].operator))
+ {
+ return (idtokentab[i].token);
+ }
+ }
+
+ /* Look for other special tokens. */
+ if (STREQ (simplename, "true"))
+ {
+ yylval.ulval = 1;
+ return (BOOLEAN_LITERAL);
+ }
+ if (STREQ (simplename, "false"))
+ {
+ yylval.ulval = 0;
+ return (BOOLEAN_LITERAL);
+ }
+
+ sym = lookup_symbol (inputname, expression_context_block,
VAR_NAMESPACE, (int *) NULL,
(struct symtab **) NULL);
+ if (sym == NULL && strcmp (inputname, simplename) != 0)
+ {
+ sym = lookup_symbol (simplename, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ }
if (sym != NULL)
{
yylval.ssym.stoken.ptr = NULL;
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
case LOC_LOCAL:
case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
if (innermost_block == NULL
|| contained_in (block_found, innermost_block))
{
case LOC_LABEL:
return (LOCATION_NAME);
break;
- case LOC_UNDEF:
case LOC_TYPEDEF:
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ case LOC_UNDEF:
case LOC_CONST_BYTES:
- error ("Symbol \"%s\" names no location.", simplename);
+ case LOC_OPTIMIZED_OUT:
+ error ("Symbol \"%s\" names no location.", inputname);
break;
}
}
}
else
{
- error ("No symbol \"%s\" in current context.", simplename);
+ error ("No symbol \"%s\" in current context.", inputname);
}
}
switch (*lexptr)
{
case '.': /* Not float for example. */
- return (*lexptr++);
+ lexptr++;
+ while (isspace (*lexptr)) lexptr++;
+ inputname = match_simple_name_string ();
+ if (!inputname)
+ return '.';
+ return FIELD_NAME;
}
return (ILLEGAL_TOKEN);
}
+void
+write_lower_upper_value (opcode, type)
+ enum exp_opcode opcode; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+{
+ extern LONGEST type_lower_upper ();
+ struct type *result_type;
+ LONGEST val = type_lower_upper (opcode, type, &result_type);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (result_type);
+ write_exp_elt_longcst (val);
+ write_exp_elt_opcode (OP_LONG);
+}
+
void
yyerror (msg)
- char *msg; /* unused */
+ char *msg;
{
- printf ("Parsing: %s\n", lexptr);
- if (yychar < 256)
- {
- error ("Invalid syntax in expression near character '%c'.", yychar);
- }
- else
- {
- error ("Invalid syntax in expression");
- }
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}