/* -*- c -*- emacs mode c */
|
/* -*- c -*- emacs mode c */
|
/* TREELANG Compiler parser.
|
/* TREELANG Compiler parser.
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
|
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
under the terms of the GNU General Public License as published by the
|
under the terms of the GNU General Public License as published by the
|
Free Software Foundation; either version 3, or (at your option) any
|
Free Software Foundation; either version 3, or (at your option) any
|
later version.
|
later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; see the file COPYING3. If not see
|
along with this program; see the file COPYING3. If not see
|
.
|
.
|
|
|
In other words, you are welcome to use, share and improve this program.
|
In other words, you are welcome to use, share and improve this program.
|
You are forbidden to forbid anyone else to use, share and improve
|
You are forbidden to forbid anyone else to use, share and improve
|
what you give them. Help stamp out software-hoarding!
|
what you give them. Help stamp out software-hoarding!
|
|
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
Written by Tim Josling 1999-2001, based in part on other parts of
|
Written by Tim Josling 1999-2001, based in part on other parts of
|
the GCC compiler. */
|
the GCC compiler. */
|
|
|
/* Grammar Conflicts
|
/* Grammar Conflicts
|
*****************
|
*****************
|
There are no conflicts in this grammar. Please keep it that way. */
|
There are no conflicts in this grammar. Please keep it that way. */
|
|
|
%{
|
%{
|
#include "config.h"
|
#include "config.h"
|
#include "system.h"
|
#include "system.h"
|
#include "coretypes.h"
|
#include "coretypes.h"
|
#include "tm.h"
|
#include "tm.h"
|
#include "timevar.h"
|
#include "timevar.h"
|
#include "tree.h"
|
#include "tree.h"
|
|
|
#include "treelang.h"
|
#include "treelang.h"
|
#include "treetree.h"
|
#include "treetree.h"
|
#include "toplev.h"
|
#include "toplev.h"
|
|
|
#define YYDEBUG 1
|
#define YYDEBUG 1
|
#define YYPRINT(file, type, value) print_token (file, type, value)
|
#define YYPRINT(file, type, value) print_token (file, type, value)
|
#define YYERROR_VERBOSE YES
|
#define YYERROR_VERBOSE YES
|
|
|
/* My yylex routine used to intercept calls to flex generated code, to
|
/* My yylex routine used to intercept calls to flex generated code, to
|
record lex time. */
|
record lex time. */
|
int yylex (void);
|
int yylex (void);
|
static inline int my_yylex (void);
|
static inline int my_yylex (void);
|
|
|
/* Call lex, but ensure time is charged to TV_LEX. */
|
/* Call lex, but ensure time is charged to TV_LEX. */
|
static inline int
|
static inline int
|
my_yylex (void)
|
my_yylex (void)
|
{
|
{
|
int res;
|
int res;
|
timevar_push (TV_LEX);
|
timevar_push (TV_LEX);
|
res = yylex ();
|
res = yylex ();
|
timevar_pop (TV_LEX);
|
timevar_pop (TV_LEX);
|
return res;
|
return res;
|
}
|
}
|
#define yylex my_yylex
|
#define yylex my_yylex
|
|
|
extern int option_parser_trace;
|
extern int option_parser_trace;
|
|
|
/* Local prototypes. */
|
/* Local prototypes. */
|
static void yyerror (const char *error_message);
|
static void yyerror (const char *error_message);
|
int yyparse (void);
|
int yyparse (void);
|
void print_token (FILE *file, unsigned int type ATTRIBUTE_UNUSED,
|
void print_token (FILE *file, unsigned int type ATTRIBUTE_UNUSED,
|
YYSTYPE value);
|
YYSTYPE value);
|
static struct prod_token_parm_item *reverse_prod_list
|
static struct prod_token_parm_item *reverse_prod_list
|
(struct prod_token_parm_item *old_first);
|
(struct prod_token_parm_item *old_first);
|
static void ensure_not_void (unsigned int type,
|
static void ensure_not_void (unsigned int type,
|
struct prod_token_parm_item *name);
|
struct prod_token_parm_item *name);
|
static int check_type_match (int type_num, struct prod_token_parm_item *exp);
|
static int check_type_match (int type_num, struct prod_token_parm_item *exp);
|
static int get_common_type (struct prod_token_parm_item *type1,
|
static int get_common_type (struct prod_token_parm_item *type1,
|
struct prod_token_parm_item *type2);
|
struct prod_token_parm_item *type2);
|
static struct prod_token_parm_item *make_integer_constant
|
static struct prod_token_parm_item *make_integer_constant
|
(struct prod_token_parm_item *value);
|
(struct prod_token_parm_item *value);
|
static struct prod_token_parm_item *make_plus_expression
|
static struct prod_token_parm_item *make_plus_expression
|
(struct prod_token_parm_item *tok, struct prod_token_parm_item *op1,
|
(struct prod_token_parm_item *tok, struct prod_token_parm_item *op1,
|
struct prod_token_parm_item *op2, int type_code, int prod_code);
|
struct prod_token_parm_item *op2, int type_code, int prod_code);
|
static void set_storage (struct prod_token_parm_item *prod);
|
static void set_storage (struct prod_token_parm_item *prod);
|
|
|
/* File global variables. */
|
/* File global variables. */
|
static struct prod_token_parm_item *current_function = NULL;
|
static struct prod_token_parm_item *current_function = NULL;
|
%}
|
%}
|
|
|
/* Not %raw - seems to have bugs. */
|
/* Not %raw - seems to have bugs. */
|
%token_table
|
%token_table
|
|
|
/* Punctuation. */
|
/* Punctuation. */
|
%token RIGHT_BRACE
|
%token RIGHT_BRACE
|
%token LEFT_BRACE
|
%token LEFT_BRACE
|
%token RIGHT_SQUARE_BRACKET
|
%token RIGHT_SQUARE_BRACKET
|
%token LEFT_SQUARE_BRACKET
|
%token LEFT_SQUARE_BRACKET
|
%token RIGHT_PARENTHESIS
|
%token RIGHT_PARENTHESIS
|
%token LEFT_PARENTHESIS
|
%token LEFT_PARENTHESIS
|
%token SEMICOLON
|
%token SEMICOLON
|
%token ASTERISK
|
%token ASTERISK
|
%token COMMA
|
%token COMMA
|
%right EQUALS
|
%right EQUALS
|
%right ASSIGN
|
%right ASSIGN
|
%left tl_PLUS
|
%left tl_PLUS
|
%left tl_MINUS
|
%left tl_MINUS
|
|
|
/* Literals. */
|
/* Literals. */
|
%token INTEGER
|
%token INTEGER
|
|
|
/* Keywords. */
|
/* Keywords. */
|
%token IF
|
%token IF
|
%token ELSE
|
%token ELSE
|
%token tl_RETURN
|
%token tl_RETURN
|
%token CHAR
|
%token CHAR
|
%token INT
|
%token INT
|
%token UNSIGNED
|
%token UNSIGNED
|
%token VOID
|
%token VOID
|
%token TYPEDEF
|
%token TYPEDEF
|
%token NAME
|
%token NAME
|
%token STATIC
|
%token STATIC
|
%token AUTOMATIC
|
%token AUTOMATIC
|
%token EXTERNAL_DEFINITION
|
%token EXTERNAL_DEFINITION
|
%token EXTERNAL_REFERENCE
|
%token EXTERNAL_REFERENCE
|
|
|
/* Tokens not passed to parser. */
|
/* Tokens not passed to parser. */
|
%token WHITESPACE
|
%token WHITESPACE
|
%token COMMENT
|
%token COMMENT
|
|
|
/* Pseudo tokens - productions. */
|
/* Pseudo tokens - productions. */
|
%token PROD_VARIABLE_NAME
|
%token PROD_VARIABLE_NAME
|
%token PROD_TYPE_NAME
|
%token PROD_TYPE_NAME
|
%token PROD_FUNCTION_NAME
|
%token PROD_FUNCTION_NAME
|
%token PROD_INTEGER_CONSTANT
|
%token PROD_INTEGER_CONSTANT
|
%token PROD_PLUS_EXPRESSION
|
%token PROD_PLUS_EXPRESSION
|
%token PROD_MINUS_EXPRESSION
|
%token PROD_MINUS_EXPRESSION
|
%token PROD_ASSIGN_EXPRESSION
|
%token PROD_ASSIGN_EXPRESSION
|
%token PROD_VARIABLE_REFERENCE_EXPRESSION
|
%token PROD_VARIABLE_REFERENCE_EXPRESSION
|
%token PROD_PARAMETER
|
%token PROD_PARAMETER
|
%token PROD_FUNCTION_INVOCATION
|
%token PROD_FUNCTION_INVOCATION
|
%expect 0
|
%expect 0
|
%%
|
%%
|
|
|
file:
|
file:
|
/* Nil. */ {
|
/* Nil. */ {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|declarations {
|
|declarations {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
|
|
declarations:
|
declarations:
|
declaration {
|
declaration {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
| declarations declaration {
|
| declarations declaration {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
declaration:
|
declaration:
|
variable_def {
|
variable_def {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|function_prototype {
|
|function_prototype {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|function {
|
|function {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
variable_def:
|
variable_def:
|
storage typename NAME init_opt SEMICOLON {
|
storage typename NAME init_opt SEMICOLON {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $3;
|
tok = $3;
|
prod = make_production (PROD_VARIABLE_NAME, tok);
|
prod = make_production (PROD_VARIABLE_NAME, tok);
|
SYMBOL_TABLE_NAME (prod) = tok;
|
SYMBOL_TABLE_NAME (prod) = tok;
|
EXPRESSION_TYPE (prod) = $2;
|
EXPRESSION_TYPE (prod) = $2;
|
VAR_INIT (prod) = $4;
|
VAR_INIT (prod) = $4;
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
ensure_not_void (NUMERIC_TYPE (prod), tok);
|
ensure_not_void (NUMERIC_TYPE (prod), tok);
|
if (insert_tree_name (prod))
|
if (insert_tree_name (prod))
|
{
|
{
|
YYERROR;
|
YYERROR;
|
}
|
}
|
STORAGE_CLASS_TOKEN (prod) = $1;
|
STORAGE_CLASS_TOKEN (prod) = $1;
|
set_storage (prod);
|
set_storage (prod);
|
|
|
if (VAR_INIT (prod))
|
if (VAR_INIT (prod))
|
{
|
{
|
gcc_assert (((struct prod_token_parm_item *)
|
gcc_assert (((struct prod_token_parm_item *)
|
VAR_INIT (prod))->tp.pro.code);
|
VAR_INIT (prod))->tp.pro.code);
|
if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE)
|
if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE)
|
{
|
{
|
error("%Hexternal reference variable %q.*s has an initial value",
|
error("%Hexternal reference variable %q.*s has an initial value",
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
VAR_INIT (prod) = NULL;
|
VAR_INIT (prod) = NULL;
|
}
|
}
|
|
|
}
|
}
|
|
|
prod->tp.pro.code = tree_code_create_variable
|
prod->tp.pro.code = tree_code_create_variable
|
(STORAGE_CLASS (prod),
|
(STORAGE_CLASS (prod),
|
((struct prod_token_parm_item *)SYMBOL_TABLE_NAME (prod))->tp.tok.chars,
|
((struct prod_token_parm_item *)SYMBOL_TABLE_NAME (prod))->tp.tok.chars,
|
((struct prod_token_parm_item *)SYMBOL_TABLE_NAME (prod))->tp.tok.length,
|
((struct prod_token_parm_item *)SYMBOL_TABLE_NAME (prod))->tp.tok.length,
|
NUMERIC_TYPE (prod),
|
NUMERIC_TYPE (prod),
|
VAR_INIT (prod) ?
|
VAR_INIT (prod) ?
|
((struct prod_token_parm_item *)VAR_INIT (prod))->tp.pro.code : NULL,
|
((struct prod_token_parm_item *)VAR_INIT (prod))->tp.pro.code : NULL,
|
tok->tp.tok.location);
|
tok->tp.tok.location);
|
gcc_assert (prod->tp.pro.code);
|
gcc_assert (prod->tp.pro.code);
|
}
|
}
|
;
|
;
|
|
|
storage:
|
storage:
|
STATIC
|
STATIC
|
|AUTOMATIC
|
|AUTOMATIC
|
|EXTERNAL_DEFINITION
|
|EXTERNAL_DEFINITION
|
|EXTERNAL_REFERENCE
|
|EXTERNAL_REFERENCE
|
;
|
;
|
|
|
parameter:
|
parameter:
|
typename NAME {
|
typename NAME {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod2;
|
struct prod_token_parm_item *prod2;
|
tok = $2;
|
tok = $2;
|
prod = make_production (PROD_VARIABLE_NAME, tok);
|
prod = make_production (PROD_VARIABLE_NAME, tok);
|
SYMBOL_TABLE_NAME (prod) = $2;
|
SYMBOL_TABLE_NAME (prod) = $2;
|
EXPRESSION_TYPE (prod) = $1;
|
EXPRESSION_TYPE (prod) = $1;
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
ensure_not_void (NUMERIC_TYPE (prod), tok);
|
ensure_not_void (NUMERIC_TYPE (prod), tok);
|
if (insert_tree_name (prod))
|
if (insert_tree_name (prod))
|
{
|
{
|
YYERROR;
|
YYERROR;
|
}
|
}
|
prod2 = make_production (PROD_PARAMETER, tok);
|
prod2 = make_production (PROD_PARAMETER, tok);
|
VARIABLE (prod2) = prod;
|
VARIABLE (prod2) = prod;
|
$$ = prod2;
|
$$ = prod2;
|
}
|
}
|
;
|
;
|
|
|
function_prototype:
|
function_prototype:
|
storage typename NAME LEFT_PARENTHESIS parameters_opt RIGHT_PARENTHESIS SEMICOLON {
|
storage typename NAME LEFT_PARENTHESIS parameters_opt RIGHT_PARENTHESIS SEMICOLON {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *type;
|
struct prod_token_parm_item *type;
|
struct prod_token_parm_item *first_parms;
|
struct prod_token_parm_item *first_parms;
|
struct prod_token_parm_item *last_parms;
|
struct prod_token_parm_item *last_parms;
|
struct prod_token_parm_item *this_parms;
|
struct prod_token_parm_item *this_parms;
|
struct prod_token_parm_item *this_parm;
|
struct prod_token_parm_item *this_parm;
|
struct prod_token_parm_item *this_parm_var;
|
struct prod_token_parm_item *this_parm_var;
|
tok = $3;
|
tok = $3;
|
prod = make_production (PROD_FUNCTION_NAME, $3);
|
prod = make_production (PROD_FUNCTION_NAME, $3);
|
SYMBOL_TABLE_NAME (prod) = $3;
|
SYMBOL_TABLE_NAME (prod) = $3;
|
EXPRESSION_TYPE (prod) = $2;
|
EXPRESSION_TYPE (prod) = $2;
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (prod) =
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
NUMERIC_TYPE (( (struct prod_token_parm_item *)EXPRESSION_TYPE (prod)));
|
PARAMETERS (prod) = reverse_prod_list ($5);
|
PARAMETERS (prod) = reverse_prod_list ($5);
|
insert_tree_name (prod);
|
insert_tree_name (prod);
|
STORAGE_CLASS_TOKEN (prod) = $1;
|
STORAGE_CLASS_TOKEN (prod) = $1;
|
set_storage (prod);
|
set_storage (prod);
|
switch (STORAGE_CLASS (prod))
|
switch (STORAGE_CLASS (prod))
|
{
|
{
|
case STATIC_STORAGE:
|
case STATIC_STORAGE:
|
case EXTERNAL_DEFINITION_STORAGE:
|
case EXTERNAL_DEFINITION_STORAGE:
|
case EXTERNAL_REFERENCE_STORAGE:
|
case EXTERNAL_REFERENCE_STORAGE:
|
break;
|
break;
|
|
|
case AUTOMATIC_STORAGE:
|
case AUTOMATIC_STORAGE:
|
error ("%Hfunction %q.*s cannot be automatic",
|
error ("%Hfunction %q.*s cannot be automatic",
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
break;
|
break;
|
|
|
default:
|
default:
|
gcc_unreachable ();
|
gcc_unreachable ();
|
}
|
}
|
type = EXPRESSION_TYPE (prod);
|
type = EXPRESSION_TYPE (prod);
|
/* Create a parameter list in a non-front end specific format. */
|
/* Create a parameter list in a non-front end specific format. */
|
for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS (prod);
|
for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS (prod);
|
this_parm;
|
this_parm;
|
this_parm = this_parm->tp.pro.next)
|
this_parm = this_parm->tp.pro.next)
|
{
|
{
|
gcc_assert (this_parm->category == production_category);
|
gcc_assert (this_parm->category == production_category);
|
this_parm_var = VARIABLE (this_parm);
|
this_parm_var = VARIABLE (this_parm);
|
|
|
gcc_assert (this_parm_var);
|
gcc_assert (this_parm_var);
|
gcc_assert (this_parm_var->category == production_category);
|
gcc_assert (this_parm_var->category == production_category);
|
gcc_assert (this_parm_var->tp.pro.main_token);
|
gcc_assert (this_parm_var->tp.pro.main_token);
|
|
|
this_parms = my_malloc (sizeof (struct prod_token_parm_item));
|
this_parms = my_malloc (sizeof (struct prod_token_parm_item));
|
|
|
this_parms->tp.par.variable_name =
|
this_parms->tp.par.variable_name =
|
this_parm_var->tp.pro.main_token->tp.tok.chars;
|
this_parm_var->tp.pro.main_token->tp.tok.chars;
|
this_parms->category = parameter_category;
|
this_parms->category = parameter_category;
|
this_parms->type = NUMERIC_TYPE
|
this_parms->type = NUMERIC_TYPE
|
(( (struct prod_token_parm_item *)EXPRESSION_TYPE (this_parm_var)));
|
(( (struct prod_token_parm_item *)EXPRESSION_TYPE (this_parm_var)));
|
if (last_parms)
|
if (last_parms)
|
{
|
{
|
last_parms->tp.par.next = this_parms;
|
last_parms->tp.par.next = this_parms;
|
last_parms = this_parms;
|
last_parms = this_parms;
|
}
|
}
|
else
|
else
|
{
|
{
|
first_parms = this_parms;
|
first_parms = this_parms;
|
last_parms = this_parms;
|
last_parms = this_parms;
|
}
|
}
|
this_parms->tp.par.where_to_put_var_tree =
|
this_parms->tp.par.where_to_put_var_tree =
|
& (((struct prod_token_parm_item *)VARIABLE (this_parm))->tp.pro.code);
|
& (((struct prod_token_parm_item *)VARIABLE (this_parm))->tp.pro.code);
|
}
|
}
|
FIRST_PARMS (prod) = first_parms;
|
FIRST_PARMS (prod) = first_parms;
|
|
|
prod->tp.pro.code =
|
prod->tp.pro.code =
|
tree_code_create_function_prototype (tok->tp.tok.chars,
|
tree_code_create_function_prototype (tok->tp.tok.chars,
|
STORAGE_CLASS (prod),
|
STORAGE_CLASS (prod),
|
NUMERIC_TYPE (type),
|
NUMERIC_TYPE (type),
|
first_parms, tok->tp.tok.location);
|
first_parms, tok->tp.tok.location);
|
|
|
#ifdef ENABLE_CHECKING
|
#ifdef ENABLE_CHECKING
|
/* Check all the parameters have code. */
|
/* Check all the parameters have code. */
|
for (this_parm = PARAMETERS (prod);
|
for (this_parm = PARAMETERS (prod);
|
this_parm;
|
this_parm;
|
this_parm = this_parm->tp.pro.next)
|
this_parm = this_parm->tp.pro.next)
|
{
|
{
|
gcc_assert ((struct prod_token_parm_item *)VARIABLE (this_parm));
|
gcc_assert ((struct prod_token_parm_item *)VARIABLE (this_parm));
|
gcc_assert (((struct prod_token_parm_item *)
|
gcc_assert (((struct prod_token_parm_item *)
|
VARIABLE (this_parm))->tp.pro.code);
|
VARIABLE (this_parm))->tp.pro.code);
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
;
|
;
|
|
|
function:
|
function:
|
NAME LEFT_BRACE {
|
NAME LEFT_BRACE {
|
struct prod_token_parm_item *proto;
|
struct prod_token_parm_item *proto;
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
tok = $1;
|
tok = $1;
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
search_prod.category = token_category;
|
search_prod.category = token_category;
|
current_function = proto = lookup_tree_name (&search_prod);
|
current_function = proto = lookup_tree_name (&search_prod);
|
if (!proto)
|
if (!proto)
|
{
|
{
|
error ("%Hno prototype found for %q.*s", &tok->tp.tok.location,
|
error ("%Hno prototype found for %q.*s", &tok->tp.tok.location,
|
tok->tp.tok.length, tok->tp.tok.chars);
|
tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
}
|
}
|
|
|
gcc_assert (proto->tp.pro.code);
|
gcc_assert (proto->tp.pro.code);
|
|
|
tree_code_create_function_initial (proto->tp.pro.code, tok->tp.tok.location);
|
tree_code_create_function_initial (proto->tp.pro.code, tok->tp.tok.location);
|
}
|
}
|
|
|
variable_defs_opt statements_opt RIGHT_BRACE {
|
variable_defs_opt statements_opt RIGHT_BRACE {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
tok = $1;
|
tok = $1;
|
tree_code_create_function_wrapup (tok->tp.tok.location);
|
tree_code_create_function_wrapup (tok->tp.tok.location);
|
current_function = NULL;
|
current_function = NULL;
|
}
|
}
|
;
|
;
|
|
|
variable_defs_opt:
|
variable_defs_opt:
|
/* Nil. */ {
|
/* Nil. */ {
|
$$ = 0;
|
$$ = 0;
|
}
|
}
|
|variable_defs {
|
|variable_defs {
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
statements_opt:
|
statements_opt:
|
/* Nil. */ {
|
/* Nil. */ {
|
$$ = 0;
|
$$ = 0;
|
}
|
}
|
|statements {
|
|statements {
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
variable_defs:
|
variable_defs:
|
variable_def {
|
variable_def {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|variable_defs variable_def {
|
|variable_defs variable_def {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
typename:
|
typename:
|
INT {
|
INT {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_TYPE_NAME, tok);
|
prod = make_production (PROD_TYPE_NAME, tok);
|
NUMERIC_TYPE (prod) = SIGNED_INT;
|
NUMERIC_TYPE (prod) = SIGNED_INT;
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
|UNSIGNED INT {
|
|UNSIGNED INT {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_TYPE_NAME, tok);
|
prod = make_production (PROD_TYPE_NAME, tok);
|
NUMERIC_TYPE (prod) = UNSIGNED_INT;
|
NUMERIC_TYPE (prod) = UNSIGNED_INT;
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
|CHAR {
|
|CHAR {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_TYPE_NAME, tok);
|
prod = make_production (PROD_TYPE_NAME, tok);
|
NUMERIC_TYPE (prod) = SIGNED_CHAR;
|
NUMERIC_TYPE (prod) = SIGNED_CHAR;
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
|UNSIGNED CHAR {
|
|UNSIGNED CHAR {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_TYPE_NAME, tok);
|
prod = make_production (PROD_TYPE_NAME, tok);
|
NUMERIC_TYPE (prod) = UNSIGNED_CHAR;
|
NUMERIC_TYPE (prod) = UNSIGNED_CHAR;
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
|VOID {
|
|VOID {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_TYPE_NAME, tok);
|
prod = make_production (PROD_TYPE_NAME, tok);
|
NUMERIC_TYPE (prod) = VOID_TYPE;
|
NUMERIC_TYPE (prod) = VOID_TYPE;
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod));
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
;
|
;
|
|
|
parameters_opt:
|
parameters_opt:
|
/* Nothing to do. */ {
|
/* Nothing to do. */ {
|
$$ = 0;
|
$$ = 0;
|
}
|
}
|
| parameters {
|
| parameters {
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
parameters:
|
parameters:
|
parameter {
|
parameter {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
|parameters COMMA parameter {
|
|parameters COMMA parameter {
|
struct prod_token_parm_item *prod1;
|
struct prod_token_parm_item *prod1;
|
prod1 = $3;
|
prod1 = $3;
|
prod1->tp.pro.next = $1; /* Insert in reverse order. */
|
prod1->tp.pro.next = $1; /* Insert in reverse order. */
|
$$ = prod1;
|
$$ = prod1;
|
}
|
}
|
;
|
;
|
|
|
statements:
|
statements:
|
statement {
|
statement {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|statements statement {
|
|statements statement {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
statement:
|
statement:
|
expression SEMICOLON {
|
expression SEMICOLON {
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
exp = $1;
|
exp = $1;
|
tree_code_output_expression_statement (exp->tp.pro.code,
|
tree_code_output_expression_statement (exp->tp.pro.code,
|
exp->tp.pro.main_token->tp.tok.location);
|
exp->tp.pro.main_token->tp.tok.location);
|
}
|
}
|
|return SEMICOLON {
|
|return SEMICOLON {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
|if_statement {
|
|if_statement {
|
/* Nothing to do. */
|
/* Nothing to do. */
|
}
|
}
|
;
|
;
|
|
|
if_statement:
|
if_statement:
|
IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS {
|
IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
tok = $1;
|
tok = $1;
|
exp = $3;
|
exp = $3;
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
tree_code_if_start (exp->tp.pro.code, tok->tp.tok.location);
|
tree_code_if_start (exp->tp.pro.code, tok->tp.tok.location);
|
}
|
}
|
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
/* Just let the statements flow. */
|
/* Just let the statements flow. */
|
}
|
}
|
ELSE {
|
ELSE {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
tok = $1;
|
tok = $1;
|
tree_code_if_else (tok->tp.tok.location);
|
tree_code_if_else (tok->tp.tok.location);
|
}
|
}
|
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
tok = $1;
|
tok = $1;
|
tree_code_if_end (tok->tp.tok.location);
|
tree_code_if_end (tok->tp.tok.location);
|
}
|
}
|
;
|
;
|
|
|
|
|
return:
|
return:
|
tl_RETURN expression_opt {
|
tl_RETURN expression_opt {
|
struct prod_token_parm_item *type_prod;
|
struct prod_token_parm_item *type_prod;
|
struct prod_token_parm_item *ret_tok = $1;
|
struct prod_token_parm_item *ret_tok = $1;
|
struct prod_token_parm_item *exp = $2;
|
struct prod_token_parm_item *exp = $2;
|
|
|
type_prod = EXPRESSION_TYPE (current_function);
|
type_prod = EXPRESSION_TYPE (current_function);
|
if (NUMERIC_TYPE (type_prod) == VOID_TYPE)
|
if (NUMERIC_TYPE (type_prod) == VOID_TYPE)
|
if (exp == NULL)
|
if (exp == NULL)
|
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
else
|
else
|
{
|
{
|
warning (0, "%Hredundant expression in return",
|
warning (0, "%Hredundant expression in return",
|
&ret_tok->tp.tok.location);
|
&ret_tok->tp.tok.location);
|
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
}
|
}
|
else
|
else
|
if (exp == NULL)
|
if (exp == NULL)
|
error ("%Hexpression missing in return", &ret_tok->tp.tok.location);
|
error ("%Hexpression missing in return", &ret_tok->tp.tok.location);
|
else
|
else
|
{
|
{
|
/* Check same type. */
|
/* Check same type. */
|
if (check_type_match (NUMERIC_TYPE (type_prod), exp))
|
if (check_type_match (NUMERIC_TYPE (type_prod), exp))
|
{
|
{
|
gcc_assert (type_prod->tp.pro.code);
|
gcc_assert (type_prod->tp.pro.code);
|
gcc_assert (exp->tp.pro.code);
|
gcc_assert (exp->tp.pro.code);
|
|
|
/* Generate the code. */
|
/* Generate the code. */
|
tree_code_generate_return (type_prod->tp.pro.code,
|
tree_code_generate_return (type_prod->tp.pro.code,
|
exp->tp.pro.code);
|
exp->tp.pro.code);
|
}
|
}
|
}
|
}
|
}
|
}
|
;
|
;
|
|
|
expression_opt:
|
expression_opt:
|
/* Nil. */ {
|
/* Nil. */ {
|
$$ = 0;
|
$$ = 0;
|
}
|
}
|
|expression {
|
|expression {
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
exp = $1;
|
exp = $1;
|
gcc_assert (exp->tp.pro.code);
|
gcc_assert (exp->tp.pro.code);
|
|
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
expression:
|
expression:
|
INTEGER {
|
INTEGER {
|
$$ = make_integer_constant ($1);
|
$$ = make_integer_constant ($1);
|
}
|
}
|
|variable_ref {
|
|variable_ref {
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
|expression tl_PLUS expression {
|
|expression tl_PLUS expression {
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op2 = $3;
|
struct prod_token_parm_item *op2 = $3;
|
int type_code = get_common_type (op1, op2);
|
int type_code = get_common_type (op1, op2);
|
if (!type_code)
|
if (!type_code)
|
YYERROR;
|
YYERROR;
|
$$ = make_plus_expression (tok, op1, op2, type_code, EXP_PLUS);
|
$$ = make_plus_expression (tok, op1, op2, type_code, EXP_PLUS);
|
}
|
}
|
|expression tl_MINUS expression %prec tl_PLUS {
|
|expression tl_MINUS expression %prec tl_PLUS {
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op2 = $3;
|
struct prod_token_parm_item *op2 = $3;
|
int type_code = get_common_type (op1, op2);
|
int type_code = get_common_type (op1, op2);
|
if (!type_code)
|
if (!type_code)
|
YYERROR;
|
YYERROR;
|
$$ = make_plus_expression (tok, op1, op2, type_code, EXP_MINUS);
|
$$ = make_plus_expression (tok, op1, op2, type_code, EXP_MINUS);
|
}
|
}
|
|expression EQUALS expression {
|
|expression EQUALS expression {
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op2 = $3;
|
struct prod_token_parm_item *op2 = $3;
|
int type_code = NUMERIC_TYPE (op1);
|
int type_code = NUMERIC_TYPE (op1);
|
if (!type_code)
|
if (!type_code)
|
YYERROR;
|
YYERROR;
|
$$ = make_plus_expression
|
$$ = make_plus_expression
|
(tok, op1, op2, type_code, EXP_EQUALS);
|
(tok, op1, op2, type_code, EXP_EQUALS);
|
}
|
}
|
|variable_ref ASSIGN expression {
|
|variable_ref ASSIGN expression {
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *tok = $2;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op1 = $1;
|
struct prod_token_parm_item *op2 = $3;
|
struct prod_token_parm_item *op2 = $3;
|
int type_code = NUMERIC_TYPE (op1);
|
int type_code = NUMERIC_TYPE (op1);
|
if (!type_code)
|
if (!type_code)
|
YYERROR;
|
YYERROR;
|
$$ = make_plus_expression
|
$$ = make_plus_expression
|
(tok, op1, op2, type_code, EXP_ASSIGN);
|
(tok, op1, op2, type_code, EXP_ASSIGN);
|
}
|
}
|
|function_invocation {
|
|function_invocation {
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
function_invocation:
|
function_invocation:
|
NAME LEFT_PARENTHESIS expressions_with_commas_opt RIGHT_PARENTHESIS {
|
NAME LEFT_PARENTHESIS expressions_with_commas_opt RIGHT_PARENTHESIS {
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item *proto;
|
struct prod_token_parm_item *proto;
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp_proto;
|
struct prod_token_parm_item *exp_proto;
|
struct prod_token_parm_item *var;
|
struct prod_token_parm_item *var;
|
int exp_proto_count;
|
int exp_proto_count;
|
int exp_count;
|
int exp_count;
|
tree parms;
|
tree parms;
|
tree type;
|
tree type;
|
|
|
tok = $1;
|
tok = $1;
|
prod = make_production (PROD_FUNCTION_INVOCATION, tok);
|
prod = make_production (PROD_FUNCTION_INVOCATION, tok);
|
SYMBOL_TABLE_NAME (prod) = tok;
|
SYMBOL_TABLE_NAME (prod) = tok;
|
PARAMETERS (prod) = reverse_prod_list ($3);
|
PARAMETERS (prod) = reverse_prod_list ($3);
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
search_prod.category = token_category;
|
search_prod.category = token_category;
|
proto = lookup_tree_name (&search_prod);
|
proto = lookup_tree_name (&search_prod);
|
if (!proto)
|
if (!proto)
|
{
|
{
|
error ("%Hfunction prototype not found for %q.*s",
|
error ("%Hfunction prototype not found for %q.*s",
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
}
|
}
|
EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto);
|
EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto);
|
NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto);
|
NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto);
|
/* Count the expressions and ensure they match the prototype. */
|
/* Count the expressions and ensure they match the prototype. */
|
for (exp_proto_count = 0, exp_proto = PARAMETERS (proto);
|
for (exp_proto_count = 0, exp_proto = PARAMETERS (proto);
|
exp_proto; exp_proto = exp_proto->tp.pro.next)
|
exp_proto; exp_proto = exp_proto->tp.pro.next)
|
exp_proto_count++;
|
exp_proto_count++;
|
|
|
for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->tp.pro.next)
|
for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->tp.pro.next)
|
exp_count++;
|
exp_count++;
|
|
|
if (exp_count != exp_proto_count)
|
if (exp_count != exp_proto_count)
|
{
|
{
|
error ("%Hexpression count mismatch %q.*s with prototype",
|
error ("%Hexpression count mismatch %q.*s with prototype",
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
}
|
}
|
parms = tree_code_init_parameters ();
|
parms = tree_code_init_parameters ();
|
for (exp_proto = PARAMETERS (proto), exp = PARAMETERS (prod);
|
for (exp_proto = PARAMETERS (proto), exp = PARAMETERS (prod);
|
exp_proto;
|
exp_proto;
|
exp = exp->tp.pro.next, exp_proto = exp_proto->tp.pro.next)
|
exp = exp->tp.pro.next, exp_proto = exp_proto->tp.pro.next)
|
{
|
{
|
gcc_assert (exp);
|
gcc_assert (exp);
|
gcc_assert (exp_proto);
|
gcc_assert (exp_proto);
|
gcc_assert (exp->tp.pro.code);
|
gcc_assert (exp->tp.pro.code);
|
|
|
var = VARIABLE (exp_proto);
|
var = VARIABLE (exp_proto);
|
|
|
gcc_assert (var);
|
gcc_assert (var);
|
gcc_assert (var->tp.pro.code);
|
gcc_assert (var->tp.pro.code);
|
|
|
parms = tree_code_add_parameter (parms, var->tp.pro.code,
|
parms = tree_code_add_parameter (parms, var->tp.pro.code,
|
exp->tp.pro.code);
|
exp->tp.pro.code);
|
}
|
}
|
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
prod->tp.pro.code = tree_code_get_expression (EXP_FUNCTION_INVOCATION, type,
|
prod->tp.pro.code = tree_code_get_expression (EXP_FUNCTION_INVOCATION, type,
|
proto->tp.pro.code,
|
proto->tp.pro.code,
|
nreverse (parms),
|
nreverse (parms),
|
NULL, tok->tp.tok.location);
|
NULL, tok->tp.tok.location);
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
;
|
;
|
|
|
expressions_with_commas_opt:
|
expressions_with_commas_opt:
|
/* Nil. */ {
|
/* Nil. */ {
|
$$ = 0
|
$$ = 0
|
}
|
}
|
|expressions_with_commas { $$ = $1 }
|
|expressions_with_commas { $$ = $1 }
|
;
|
;
|
|
|
expressions_with_commas:
|
expressions_with_commas:
|
expression {
|
expression {
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
exp = $1;
|
exp = $1;
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
|expressions_with_commas COMMA expression {
|
|expressions_with_commas COMMA expression {
|
struct prod_token_parm_item *exp;
|
struct prod_token_parm_item *exp;
|
exp = $3;
|
exp = $3;
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
exp->tp.pro.next = $1; /* Reverse order. */
|
exp->tp.pro.next = $1; /* Reverse order. */
|
$$ = exp;
|
$$ = exp;
|
}
|
}
|
;
|
;
|
|
|
variable_ref:
|
variable_ref:
|
NAME {
|
NAME {
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item search_prod;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *symbol_table_entry;
|
struct prod_token_parm_item *symbol_table_entry;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
tree type;
|
tree type;
|
|
|
tok = $1;
|
tok = $1;
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
SYMBOL_TABLE_NAME ((&search_prod)) = tok;
|
search_prod.category = token_category;
|
search_prod.category = token_category;
|
symbol_table_entry = lookup_tree_name (&search_prod);
|
symbol_table_entry = lookup_tree_name (&search_prod);
|
if (!symbol_table_entry)
|
if (!symbol_table_entry)
|
{
|
{
|
error ("%Hvariable %q.*s not defined",
|
error ("%Hvariable %q.*s not defined",
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
&tok->tp.tok.location, tok->tp.tok.length, tok->tp.tok.chars);
|
YYERROR;
|
YYERROR;
|
}
|
}
|
|
|
prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok);
|
prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok);
|
NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry);
|
NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry);
|
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
if (!NUMERIC_TYPE (prod))
|
if (!NUMERIC_TYPE (prod))
|
YYERROR;
|
YYERROR;
|
OP1 (prod) = $1;
|
OP1 (prod) = $1;
|
|
|
prod->tp.pro.code =
|
prod->tp.pro.code =
|
tree_code_get_expression (EXP_REFERENCE, type,
|
tree_code_get_expression (EXP_REFERENCE, type,
|
symbol_table_entry->tp.pro.code, NULL, NULL,
|
symbol_table_entry->tp.pro.code, NULL, NULL,
|
tok->tp.tok.location);
|
tok->tp.tok.location);
|
$$ = prod;
|
$$ = prod;
|
}
|
}
|
;
|
;
|
|
|
init_opt:
|
init_opt:
|
/* Nil. */ {
|
/* Nil. */ {
|
$$ = 0;
|
$$ = 0;
|
}
|
}
|
|init {
|
|init {
|
/* Pass the initialization value up. */
|
/* Pass the initialization value up. */
|
$$ = $1;
|
$$ = $1;
|
};
|
};
|
|
|
init:
|
init:
|
ASSIGN init_element {
|
ASSIGN init_element {
|
$$ = $2;
|
$$ = $2;
|
}
|
}
|
;
|
;
|
|
|
init_element:
|
init_element:
|
INTEGER {
|
INTEGER {
|
$$ = make_integer_constant ($1);
|
$$ = make_integer_constant ($1);
|
}
|
}
|
;
|
;
|
|
|
%%
|
%%
|
|
|
/* Print a token VALUE to file FILE. Ignore TYPE which is the token
|
/* Print a token VALUE to file FILE. Ignore TYPE which is the token
|
type. */
|
type. */
|
|
|
void
|
void
|
print_token (FILE *file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value)
|
print_token (FILE *file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value)
|
{
|
{
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
unsigned int ix;
|
unsigned int ix;
|
|
|
tok = value;
|
tok = value;
|
fprintf (file, "%d \"", LOCATION_LINE (tok->tp.tok.location));
|
fprintf (file, "%d \"", LOCATION_LINE (tok->tp.tok.location));
|
for (ix = 0; ix < tok->tp.tok.length; ix++)
|
for (ix = 0; ix < tok->tp.tok.length; ix++)
|
fprintf (file, "%c", tok->tp.tok.chars[ix]);
|
fprintf (file, "%c", tok->tp.tok.chars[ix]);
|
|
|
fprintf (file, "\"");
|
fprintf (file, "\"");
|
}
|
}
|
|
|
/* Output a message ERROR_MESSAGE from the parser. */
|
/* Output a message ERROR_MESSAGE from the parser. */
|
static void
|
static void
|
yyerror (const char *error_message)
|
yyerror (const char *error_message)
|
{
|
{
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
|
|
tok = yylval;
|
tok = yylval;
|
if (tok)
|
if (tok)
|
error ("%H%s", &tok->tp.tok.location, error_message);
|
error ("%H%s", &tok->tp.tok.location, error_message);
|
else
|
else
|
error ("%s", error_message);
|
error ("%s", error_message);
|
}
|
}
|
|
|
/* Reverse the order of a token list, linked by parse_next, old first
|
/* Reverse the order of a token list, linked by parse_next, old first
|
token is OLD_FIRST. */
|
token is OLD_FIRST. */
|
|
|
static struct prod_token_parm_item*
|
static struct prod_token_parm_item*
|
reverse_prod_list (struct prod_token_parm_item *old_first)
|
reverse_prod_list (struct prod_token_parm_item *old_first)
|
{
|
{
|
struct prod_token_parm_item *current;
|
struct prod_token_parm_item *current;
|
struct prod_token_parm_item *next;
|
struct prod_token_parm_item *next;
|
struct prod_token_parm_item *prev = NULL;
|
struct prod_token_parm_item *prev = NULL;
|
|
|
current = old_first;
|
current = old_first;
|
prev = NULL;
|
prev = NULL;
|
|
|
while (current)
|
while (current)
|
{
|
{
|
gcc_assert (current->category == production_category);
|
gcc_assert (current->category == production_category);
|
|
|
next = current->tp.pro.next;
|
next = current->tp.pro.next;
|
current->tp.pro.next = prev;
|
current->tp.pro.next = prev;
|
prev = current;
|
prev = current;
|
current = next;
|
current = next;
|
}
|
}
|
return prev;
|
return prev;
|
}
|
}
|
|
|
/* Ensure TYPE is not VOID. Use NAME as the token for the error location. */
|
/* Ensure TYPE is not VOID. Use NAME as the token for the error location. */
|
|
|
static void
|
static void
|
ensure_not_void (unsigned int type, struct prod_token_parm_item* name)
|
ensure_not_void (unsigned int type, struct prod_token_parm_item* name)
|
{
|
{
|
if (type == VOID_TYPE)
|
if (type == VOID_TYPE)
|
error ("%Htype must not be void in this context",
|
error ("%Htype must not be void in this context",
|
&name->tp.tok.location);
|
&name->tp.tok.location);
|
}
|
}
|
|
|
/* Check TYPE1 and TYPE2 which are integral types. Return the lowest
|
/* Check TYPE1 and TYPE2 which are integral types. Return the lowest
|
common type (min is signed int). */
|
common type (min is signed int). */
|
|
|
static int
|
static int
|
get_common_type (struct prod_token_parm_item *type1,
|
get_common_type (struct prod_token_parm_item *type1,
|
struct prod_token_parm_item *type2)
|
struct prod_token_parm_item *type2)
|
{
|
{
|
if (NUMERIC_TYPE (type1) == UNSIGNED_INT)
|
if (NUMERIC_TYPE (type1) == UNSIGNED_INT)
|
return UNSIGNED_INT;
|
return UNSIGNED_INT;
|
if (NUMERIC_TYPE (type2) == UNSIGNED_INT)
|
if (NUMERIC_TYPE (type2) == UNSIGNED_INT)
|
return UNSIGNED_INT;
|
return UNSIGNED_INT;
|
|
|
return SIGNED_INT;
|
return SIGNED_INT;
|
}
|
}
|
|
|
/* Check type (TYPE_NUM) and expression (EXP) match. Return the 1 if
|
/* Check type (TYPE_NUM) and expression (EXP) match. Return the 1 if
|
OK else 0. Must be exact match - same name unless it is an
|
OK else 0. Must be exact match - same name unless it is an
|
integral type. */
|
integral type. */
|
|
|
static int
|
static int
|
check_type_match (int type_num, struct prod_token_parm_item *exp)
|
check_type_match (int type_num, struct prod_token_parm_item *exp)
|
{
|
{
|
switch (type_num)
|
switch (type_num)
|
{
|
{
|
case SIGNED_INT:
|
case SIGNED_INT:
|
case UNSIGNED_INT:
|
case UNSIGNED_INT:
|
case SIGNED_CHAR:
|
case SIGNED_CHAR:
|
case UNSIGNED_CHAR:
|
case UNSIGNED_CHAR:
|
switch (NUMERIC_TYPE (exp))
|
switch (NUMERIC_TYPE (exp))
|
{
|
{
|
case SIGNED_INT:
|
case SIGNED_INT:
|
case UNSIGNED_INT:
|
case UNSIGNED_INT:
|
case SIGNED_CHAR:
|
case SIGNED_CHAR:
|
case UNSIGNED_CHAR:
|
case UNSIGNED_CHAR:
|
return 1;
|
return 1;
|
|
|
case VOID_TYPE:
|
case VOID_TYPE:
|
default:
|
default:
|
gcc_unreachable ();
|
gcc_unreachable ();
|
}
|
}
|
break;
|
break;
|
|
|
case VOID_TYPE:
|
case VOID_TYPE:
|
default:
|
default:
|
gcc_unreachable ();
|
gcc_unreachable ();
|
|
|
}
|
}
|
}
|
}
|
|
|
/* Make a production for an integer constant VALUE. */
|
/* Make a production for an integer constant VALUE. */
|
|
|
static struct prod_token_parm_item *
|
static struct prod_token_parm_item *
|
make_integer_constant (struct prod_token_parm_item* value)
|
make_integer_constant (struct prod_token_parm_item* value)
|
{
|
{
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *tok;
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tok = value;
|
tok = value;
|
prod = make_production (PROD_INTEGER_CONSTANT, tok);
|
prod = make_production (PROD_INTEGER_CONSTANT, tok);
|
if ((tok->tp.tok.chars[0] == (unsigned char)'-')
|
if ((tok->tp.tok.chars[0] == (unsigned char)'-')
|
|| (tok->tp.tok.chars[0] == (unsigned char)'+'))
|
|| (tok->tp.tok.chars[0] == (unsigned char)'+'))
|
NUMERIC_TYPE (prod) = SIGNED_INT;
|
NUMERIC_TYPE (prod) = SIGNED_INT;
|
else
|
else
|
NUMERIC_TYPE (prod) = UNSIGNED_INT;
|
NUMERIC_TYPE (prod) = UNSIGNED_INT;
|
prod->tp.pro.code = tree_code_get_integer_value (tok->tp.tok.chars,
|
prod->tp.pro.code = tree_code_get_integer_value (tok->tp.tok.chars,
|
tok->tp.tok.length);
|
tok->tp.tok.length);
|
return prod;
|
return prod;
|
}
|
}
|
|
|
|
|
/* Build a PROD_PLUS_EXPRESSION. This is uses for PLUS, MINUS, ASSIGN
|
/* Build a PROD_PLUS_EXPRESSION. This is uses for PLUS, MINUS, ASSIGN
|
and EQUALS expressions. */
|
and EQUALS expressions. */
|
|
|
static struct prod_token_parm_item *
|
static struct prod_token_parm_item *
|
make_plus_expression (struct prod_token_parm_item *tok,
|
make_plus_expression (struct prod_token_parm_item *tok,
|
struct prod_token_parm_item *op1,
|
struct prod_token_parm_item *op1,
|
struct prod_token_parm_item *op2,
|
struct prod_token_parm_item *op2,
|
int type_code, int prod_code)
|
int type_code, int prod_code)
|
{
|
{
|
struct prod_token_parm_item *prod;
|
struct prod_token_parm_item *prod;
|
tree type;
|
tree type;
|
|
|
ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token);
|
ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token);
|
|
|
prod = make_production (PROD_PLUS_EXPRESSION, tok);
|
prod = make_production (PROD_PLUS_EXPRESSION, tok);
|
|
|
NUMERIC_TYPE (prod) = type_code;
|
NUMERIC_TYPE (prod) = type_code;
|
type = tree_code_get_type (type_code);
|
type = tree_code_get_type (type_code);
|
|
|
gcc_assert (type);
|
gcc_assert (type);
|
|
|
OP1 (prod) = op1;
|
OP1 (prod) = op1;
|
OP2 (prod) = op2;
|
OP2 (prod) = op2;
|
|
|
prod->tp.pro.code = tree_code_get_expression (prod_code, type,
|
prod->tp.pro.code = tree_code_get_expression (prod_code, type,
|
op1->tp.pro.code,
|
op1->tp.pro.code,
|
op2->tp.pro.code, NULL,
|
op2->tp.pro.code, NULL,
|
tok->tp.tok.location);
|
tok->tp.tok.location);
|
|
|
return prod;
|
return prod;
|
}
|
}
|
|
|
|
|
/* Set STORAGE_CLASS in PROD according to CLASS_TOKEN. */
|
/* Set STORAGE_CLASS in PROD according to CLASS_TOKEN. */
|
|
|
static void
|
static void
|
set_storage (struct prod_token_parm_item *prod)
|
set_storage (struct prod_token_parm_item *prod)
|
{
|
{
|
struct prod_token_parm_item *stg_class;
|
struct prod_token_parm_item *stg_class;
|
stg_class = STORAGE_CLASS_TOKEN (prod);
|
stg_class = STORAGE_CLASS_TOKEN (prod);
|
switch (stg_class->type)
|
switch (stg_class->type)
|
{
|
{
|
case STATIC:
|
case STATIC:
|
STORAGE_CLASS (prod) = STATIC_STORAGE;
|
STORAGE_CLASS (prod) = STATIC_STORAGE;
|
break;
|
break;
|
|
|
case AUTOMATIC:
|
case AUTOMATIC:
|
STORAGE_CLASS (prod) = AUTOMATIC_STORAGE;
|
STORAGE_CLASS (prod) = AUTOMATIC_STORAGE;
|
break;
|
break;
|
|
|
case EXTERNAL_DEFINITION:
|
case EXTERNAL_DEFINITION:
|
STORAGE_CLASS (prod) = EXTERNAL_DEFINITION_STORAGE;
|
STORAGE_CLASS (prod) = EXTERNAL_DEFINITION_STORAGE;
|
break;
|
break;
|
|
|
case EXTERNAL_REFERENCE:
|
case EXTERNAL_REFERENCE:
|
STORAGE_CLASS (prod) = EXTERNAL_REFERENCE_STORAGE;
|
STORAGE_CLASS (prod) = EXTERNAL_REFERENCE_STORAGE;
|
break;
|
break;
|
|
|
default:
|
default:
|
gcc_unreachable ();
|
gcc_unreachable ();
|
}
|
}
|
}
|
}
|
|
|
/* Set parse trace. */
|
/* Set parse trace. */
|
|
|
void
|
void
|
treelang_debug (void)
|
treelang_debug (void)
|
{
|
{
|
if (option_parser_trace)
|
if (option_parser_trace)
|
yydebug = 1;
|
yydebug = 1;
|
}
|
}
|
|
|
#ifdef __XGETTEXT__
|
#ifdef __XGETTEXT__
|
/* Depending on the version of Bison used to compile this grammar,
|
/* Depending on the version of Bison used to compile this grammar,
|
it may issue generic diagnostics spelled "syntax error" or
|
it may issue generic diagnostics spelled "syntax error" or
|
"parse error". To prevent this from changing the translation
|
"parse error". To prevent this from changing the translation
|
template randomly, we list all the variants of this particular
|
template randomly, we list all the variants of this particular
|
diagnostic here. Translators: there is no fine distinction
|
diagnostic here. Translators: there is no fine distinction
|
between diagnostics with "syntax error" in them, and diagnostics
|
between diagnostics with "syntax error" in them, and diagnostics
|
with "parse error" in them. It's okay to give them both the same
|
with "parse error" in them. It's okay to give them both the same
|
translation. */
|
translation. */
|
const char d1[] = N_("syntax error");
|
const char d1[] = N_("syntax error");
|
const char d2[] = N_("parse error");
|
const char d2[] = N_("parse error");
|
const char d3[] = N_("syntax error; also virtual memory exhausted");
|
const char d3[] = N_("syntax error; also virtual memory exhausted");
|
const char d4[] = N_("parse error; also virtual memory exhausted");
|
const char d4[] = N_("parse error; also virtual memory exhausted");
|
const char d5[] = N_("syntax error: cannot back up");
|
const char d5[] = N_("syntax error: cannot back up");
|
const char d6[] = N_("parse error: cannot back up");
|
const char d6[] = N_("parse error: cannot back up");
|
#endif
|
#endif
|
|
|