treelang patch part 2 of 6
Tim Josling
tej@melbpc.org.au
Sat May 4 21:37:00 GMT 2002
+ what you give them. Help stamp out software-hoarding!
+
+
---------------------------------------------------------------------
+
+ Written by Tim Josling 1999-2001, based in part on other parts of
+ the GCC compiler.
+
+ */
+
+ /* Avoid poisoned malloc problem. */
+ #undef IN_GCC
+
+ #if 0
+ /* tree is defined as void* here to avoid any knowledge of tree stuff
in this file. */
+ typedef void *tree;
+ #endif
+ #include <stdio.h>
+ #if 0
+ #include <ctype.h>
+ #endif
+ #include <memory.h>
+ #include "ansidecl.h"
+ #include "config.h"
+ #include "system.h"
+ #include "diagnostic.h"
+
+ /* Token defs. */
+ #include "treelang.h"
+ #include "parse.h"
+
+ extern int option_lexer_trace;
+
+ int yylex (void);
+ void update_yylval (int a);
+
+ static int next_tree_lineno=1;
+ static int next_tree_charno=1;
+
+ static void update_lineno_charno (void);
+ static void dump_lex_value (int lexret);
+
+ #define SAVE_RETURN(a) {update_yylval (a); if (option_lexer_trace)\
+ {fprintf (stderr, "\nlexer returning"); dump_lex_value (a);} return
a;}
+ #define NOT_RETURN(a) {update_yylval (a); if (option_lexer_trace)\
+ {fprintf (stderr, "\nlexer swallowing"); dump_lex_value (a);}}
+
+ %}
+
+ %option nostack
+ %option nounput
+ %option noyywrap
+ %option pointer
+ %option nodefault
+
+ %%
+
+ {
+ yylval = my_malloc (sizeof (struct token));
+ ((struct token*)yylval)->lineno = next_tree_lineno;
+ ((struct token*)yylval)->charno = next_tree_charno;
+ }
+
+ [ \n]+ {
+ update_lineno_charno ();
+ NOT_RETURN (WHITESPACE);
+ }
+
+ "//".* {
+ /* Comment. */
+ update_lineno_charno ();
+ NOT_RETURN (COMMENT);
+ }
+
+ "{" {
+ update_lineno_charno ();
+ SAVE_RETURN (LEFT_BRACE);
+ }
+
+ "}" {
+ update_lineno_charno ();
+ SAVE_RETURN (RIGHT_BRACE);
+ }
+
+ "(" {
+ update_lineno_charno ();
+ SAVE_RETURN (LEFT_PARENTHESIS);
+ }
+
+ ")" {
+ update_lineno_charno ();
+ SAVE_RETURN (RIGHT_PARENTHESIS);
+ }
+
+ "," {
+ update_lineno_charno ();
+ SAVE_RETURN (COMMA);
+ }
+
+ ";" {
+ update_lineno_charno ();
+ SAVE_RETURN (SEMICOLON);
+ }
+
+ "+" {
+ update_lineno_charno ();
+ SAVE_RETURN (PLUS);
+ }
+
+ "-" {
+ update_lineno_charno ();
+ SAVE_RETURN (MINUS);
+ }
+
+ "=" {
+ update_lineno_charno ();
+ SAVE_RETURN (ASSIGN);
+ }
+
+ "==" {
+ update_lineno_charno ();
+ SAVE_RETURN (EQUALS);
+ }
+
+ [+-]?[0-9]+ {
+ update_lineno_charno ();
+ SAVE_RETURN (INTEGER);
+ }
+
+ "external_reference" {
+ update_lineno_charno ();
+ SAVE_RETURN (EXTERNAL_REFERENCE);
+ }
+
+ "external_definition" {
+ update_lineno_charno ();
+ SAVE_RETURN (EXTERNAL_DEFINITION);
+ }
+
+ "static" {
+ update_lineno_charno ();
+ SAVE_RETURN (STATIC);
+ }
+
+ "automatic" {
+ update_lineno_charno ();
+ SAVE_RETURN (STATIC);
+ }
+
+ "int" {
+ update_lineno_charno ();
+ SAVE_RETURN (INT);
+ }
+
+ "char" {
+ update_lineno_charno ();
+ SAVE_RETURN (CHAR);
+ }
+
+ "void" {
+ update_lineno_charno ();
+ SAVE_RETURN (VOID);
+ }
+
+ "unsigned" {
+ update_lineno_charno ();
+ SAVE_RETURN (UNSIGNED);
+ }
+
+ "return" {
+ update_lineno_charno ();
+ SAVE_RETURN (RETURN);
+ }
+
+ "if" {
+ update_lineno_charno ();
+ SAVE_RETURN (IF);
+ }
+
+ "else" {
+ update_lineno_charno ();
+ SAVE_RETURN (ELSE);
+ }
+
+ [A-Za-z_]+[A-Za-z_0-9]* {
+ update_lineno_charno ();
+ update_yylval (NAME);
+ if (option_lexer_trace)
+ {
+ fprintf (stderr, "\nlexer returning");
+ dump_lex_value (NAME);
+ }
+ return NAME;
+ }
+
+ [^\n] {
+ update_lineno_charno ();
+ fprintf (stderr, "%s:%i:%i: Unrecognized character %c\n", in_fname,
+ ((struct token*)yylval)->lineno,
+ ((struct token*)yylval)->charno, yytext[0]);
+ errorcount++;
+ }
+
+ %%
+
+ /*
+ Update line number (1-) and character number (1-). Call this
+ before processing the token. */
+
+ static void
+ update_lineno_charno (void)
+ {
+ /* Update the values we send to caller in case we sometimes don't
+ tell them about all the 'tokens' eg comments etc. */
+ int yyl;
+ ((struct token*)yylval)->lineno = next_tree_lineno;
+ ((struct token*)yylval)->charno = next_tree_charno;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ {
+ if ( yytext[yyl] == '\n' )
+ {
+ ++next_tree_lineno;
+ next_tree_charno = 1;
+ }
+ else
+ next_tree_charno++;
+ }
+ }
+
+ /* Fill in the fields of yylval - the value of the token. The token
+ type is A. */
+ void
+ update_yylval (int a)
+ {
+ struct token* tok;
+ tok=yylval;
+
+ tok->category = token_category;
+ tok->type = a;
+ tok->length = yyleng;
+ /* Have to copy yytext as it is just a ptr into the buffer at the
+ moment. */
+ tok->chars = my_malloc (yyleng + 1);
+ memcpy (tok->chars, yytext, yyleng);
+ }
+
+ /* Trace the value LEXRET and the position and token details being
+ returned by the lexical analyser. */
+
+ static void
+ dump_lex_value (int lexret)
+ {
+ int ix;
+ fprintf (stderr, " %d l:%d c:%d ln:%d text=", lexret,
+ ((struct token*) yylval)->lineno,
+ ((struct token*) yylval)->charno,
+ ((struct token*) yylval)->length);
+ for (ix = 0; ix < yyleng; ix++)
+ {
+ fprintf (stderr, "%c", yytext[ix]);
+ }
+ fprintf (stderr, " in hex:");
+ for (ix = 0; ix < yyleng; ix++)
+ {
+ fprintf (stderr, " %2.2x", yytext[ix]);
+ }
+ fprintf (stderr, "\n");
+ }
+
diff -c -r -p -N -X treelang.diff.excl cvs/gcc/gcc/treelang/parse.y
cvscopy/gcc/gcc/treelang/parse.y
*** cvs/gcc/gcc/treelang/parse.y Thu Jan 1 10:00:00 1970
--- cvscopy/gcc/gcc/treelang/parse.y Sat May 4 21:12:14 2002
***************
*** 0 ****
--- 1,1001 ----
+ %{ /* -*- c -*- emacs mode c */
+ /*
+
+ TREELANG Compiler parser.
+
+
---------------------------------------------------------------------
+
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation,
Inc.
+
+ 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
+ Free Software Foundation; either version 2, or (at your option)
any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ 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
+ what you give them. Help stamp out software-hoarding!
+
+
---------------------------------------------------------------------
+
+ Written by Tim Josling 1999-2001, based in part on other parts of
+ the GCC compiler.
+
+ */
+
+ /*
+
+ Grammar Conflicts
+ *****************
+
+ There are no conflicts in this grammar. Please keep it that way.
+
+ */
+
+ #undef IN_GCC
+
+ typedef void *tree;
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ #include "ansidecl.h"
+ #include "config.h"
+ #include "system.h"
+ #include "diagnostic.h"
+
+ #include "treelang.h"
+ #include "treetree.h"
+
+ #define YYDEBUG 1
+ #define YYPRINT(file, type, value) print_token (file, type, value)
+ #define YYERROR_VERBOSE YES
+
+
+ extern int option_parser_trace;
+
+ /* Local prototypes. */
+
+ static void yyerror (const char *error_message);
+ int yylex (void);
+ int yyparse (void);
+ void print_token (FILE * file, unsigned int type ATTRIBUTE_UNUSED,
YYSTYPE value);
+ static struct production *reverse_prod_list (struct production
*old_first);
+ static void ensure_not_void (unsigned int type, struct token* name);
+ static int check_type_match (int type_num, struct production *exp);
+ static int get_common_type (struct production *type1, struct
production *type2);
+ static struct production *make_integer_constant (struct token* value);
+ static void set_storage (struct production *prod);
+
+ /* File global variables. */
+
+ static struct production *current_function=NULL;
+
+ %}
+
+ /* Not %raw - seems to have bugs. */
+ %token_table
+
+ /* Punctuation. */
+ %token RIGHT_BRACE
+ %token LEFT_BRACE
+ %token RIGHT_SQUARE_BRACKET
+ %token LEFT_SQUARE_BRACKET
+ %token RIGHT_PARENTHESIS
+ %token LEFT_PARENTHESIS
+ %token SEMICOLON
+ %token ASTERISK
+ %token COMMA
+ %right EQUALS
+ %right ASSIGN
+ %left PLUS
+ %left MINUS
+
+ /* Literals. */
+ %token INTEGER
+
+ /* Keywords. */
+ %token IF
+ %token ELSE
+ %token RETURN
+ %token CHAR
+ %token INT
+ %token UNSIGNED
+ %token VOID
+ %token TYPEDEF
+ %token NAME
+ %token STATIC
+ %token AUTOMATIC
+ %token EXTERNAL_DEFINITION
+ %token EXTERNAL_REFERENCE
+
+ /* Tokens not passed to parser. */
+ %token WHITESPACE
+ %token COMMENT
+
+ /* Pseudo tokens - productions. */
+ %token PROD_VARIABLE_NAME
+ %token PROD_TYPE_NAME
+ %token PROD_FUNCTION_NAME
+ %token PROD_INTEGER_CONSTANT
+ %token PROD_PLUS_EXPRESSION
+ %token PROD_MINUS_EXPRESSION
+ %token PROD_ASSIGN_EXPRESSION
+ %token PROD_VARIABLE_REFERENCE_EXPRESSION
+ %token PROD_PARAMETER
+ %token PROD_FUNCTION_INVOCATION
+ %expect 0
+ %%
+
+ file:
+ /* Nil. */ {
+ /* Nothing to do. */
+ }
+ |declarations {
+ /* Nothing to do. */
+ }
+ ;
+
+
+ declarations:
+ declaration {
+ /* Nothing to do. */
+ }
+ | declarations declaration {
+ /* Nothing to do. */
+ }
+ ;
+
+ declaration:
+ variable_def {
+ /* Nothing to do. */
+ }
+ |function_prototype {
+ /* Nothing to do. */
+ }
+ |function {
+ /* Nothing to do. */
+ }
+ ;
+
+ variable_def:
+ storage typename NAME init_opt SEMICOLON {
+ struct token* tok;
+ struct production *prod;
+ tok = $3;
+ prod = make_production (PROD_VARIABLE_NAME, tok);
+ SYMBOL_TABLE_NAME (prod) = tok;
+ EXPRESSION_TYPE (prod) = $2;
+ VAR_INIT (prod) = $4;
+ NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct
production*)EXPRESSION_TYPE (prod)));
+ ensure_not_void (NUMERIC_TYPE (prod), tok);
+ if (insert_tree_name (prod))
+ {
+ YYERROR;
+ }
+ STORAGE_CLASS_TOKEN (prod) = $1;
+ set_storage (prod);
+
+ if (VAR_INIT (prod))
+ {
+ if (! ((struct production*)VAR_INIT (prod))->code)
+ abort ();
+ if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE)
+ {
+ fprintf (stderr, "%s:%i:%i: External reference variables may
not have initial value\n", in_fname,
+ tok->lineno, tok->charno);
+ print_token (stderr, 0, tok);
+ errorcount++;
+ YYERROR;
+ }
+ }
+ prod->code = tree_code_create_variable
+ (STORAGE_CLASS (prod),
+ ((struct token*)SYMBOL_TABLE_NAME (prod))->chars,
+ ((struct token*)SYMBOL_TABLE_NAME (prod))->length,
+ NUMERIC_TYPE (prod),
+ VAR_INIT (prod)? ((struct production*)VAR_INIT
(prod))->code:NULL,
+ in_fname,
+ tok->lineno);
+ if (!prod->code)
+ abort ();
+ }
+ ;
+
+ storage:
+ STATIC
+ |AUTOMATIC
+ |EXTERNAL_DEFINITION
+ |EXTERNAL_REFERENCE
+ ;
+
+ parameter:
+ typename NAME {
+ struct token* tok;
+ struct production *prod;
+ struct production *prod2;
+ tok = $2;
+ prod = make_production (PROD_VARIABLE_NAME, tok);
+ SYMBOL_TABLE_NAME (prod) = $2;
+ EXPRESSION_TYPE (prod) = $1;
+ NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct
production*)EXPRESSION_TYPE (prod)));
+ ensure_not_void (NUMERIC_TYPE (prod), tok);
+ if (insert_tree_name (prod))
+ {
+ YYERROR;
+ }
+ prod2 = make_production (PROD_PARAMETER, tok);
+ VARIABLE (prod2) = prod;
+ $$ = prod2;
+ }
+ ;
+
+ function_prototype:
+ storage typename NAME LEFT_PARENTHESIS parameters RIGHT_PARENTHESIS
SEMICOLON {
+ struct token* tok;
+ struct production *prod;
+ struct production *type;
+ struct tree_parameter_list* first_parms;
+ struct tree_parameter_list* last_parms;
+ struct tree_parameter_list* this_parms;
+ struct production *this_parm;
+ struct production *this_parm_var;
+ tok = $3;
+ prod = make_production (PROD_FUNCTION_NAME, $3);
+ SYMBOL_TABLE_NAME (prod) = $3;
+ EXPRESSION_TYPE (prod) = $2;
+ NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct
production*)EXPRESSION_TYPE (prod)));
+ PARAMETERS (prod) = reverse_prod_list ($5);
+ insert_tree_name (prod);
+ STORAGE_CLASS_TOKEN (prod) = $1;
+ set_storage (prod);
+ switch (STORAGE_CLASS (prod))
+ {
+ case STATIC_STORAGE:
+ case EXTERNAL_DEFINITION_STORAGE:
+ break;
+
+ case AUTOMATIC_STORAGE:
+ fprintf (stderr, "%s:%i:%i: A function cannot be automatic\n",
in_fname,
+ tok->lineno, tok->charno);
+ print_token (stderr, 0, tok);
+ errorcount++;
+ YYERROR;
+ break;
+
+ default:
+ abort ();
+ }
+ type = EXPRESSION_TYPE (prod);
+ /* Create a parameter list in a non-front end specific format. */
+ for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS
(prod);
+ this_parm;
+ this_parm = this_parm->next)
+ {
+ if (this_parm->category != production_category)
+ abort ();
+ this_parm_var = VARIABLE (this_parm);
+ if (!this_parm_var)
+ abort ();
+ if (this_parm_var->category != production_category)
+ abort ();
+ this_parms = my_malloc (sizeof (struct tree_parameter_list));
+ if (!this_parm_var->main_token)
+ abort ();
+ this_parms->variable_name = this_parm_var->main_token->chars;
+ this_parms->type = NUMERIC_TYPE (( (struct
production*)EXPRESSION_TYPE (this_parm_var)));
+ if (last_parms)
+ {
+ last_parms->next = this_parms;
+ last_parms = this_parms;
+ }
+ else
+ {
+ first_parms = this_parms;
+ last_parms = this_parms;
+ }
+ this_parms->where_to_put_var_tree = & (( (struct
production*)VARIABLE (this_parm))->code);
+ }
+ FIRST_PARMS (prod) = first_parms;
+
+ prod->code = tree_code_create_function_prototype
+ (tok->chars, STORAGE_CLASS (prod), NUMERIC_TYPE (type),
+ first_parms, in_fname, tok->lineno);
+
+ }
+ ;
+
+ function:
+ NAME LEFT_BRACE {
+ struct production *proto;
+ struct production search_prod;
+ struct token* tok;
+ struct production *this_parm;
+ tok = $1;
+ SYMBOL_TABLE_NAME ((&search_prod)) = tok;
+ current_function = proto = lookup_tree_name (&search_prod);
+ if (!proto)
+ {
+ fprintf (stderr, "%s:%i:%i: Function prototype not found\n",
in_fname,
+ tok->lineno, tok->charno);
+ print_token (stderr, 0, tok);
+ errorcount++;
+ YYERROR;
+ }
+ if (!proto->code)
+ abort ();
+ tree_code_create_function_initial
+ (proto->code, in_fname, tok->lineno,
+ FIRST_PARMS (current_function));
+
+ /* Check all the parameters have code. */
+ for (this_parm = PARAMETERS (proto);
+ this_parm;
+ this_parm = this_parm->next)
+ {
+ if (! (struct production*)VARIABLE (this_parm))
+ abort ();
+ if (! (( (struct production*)VARIABLE (this_parm))->code))
+ abort ();
+ }
+ }
+ variable_defs_opt statements_opt RIGHT_BRACE {
+ struct token* tok;
+ tok = $1;
+ tree_code_create_function_wrapup (in_fname, tok->lineno);
+ current_function = NULL;
+ }
+ ;
+
+ variable_defs_opt:
+ /* Nil. */ {
+ $$ = 0;
+ }
+ |variable_defs {
+ $$ = $1;
+ }
+ ;
+
+ statements_opt:
+ /* Nil. */ {
+ $$ = 0;
+ }
+ |statements {
+ $$ = $1;
+ }
+ ;
+
+ variable_defs:
+ variable_def {
+ /* Nothing to do. */
+ }
+ |variable_defs variable_def {
+ /* Nothing to do. */
+ }
+ ;
+
+ typename:
+ INT {
+ struct token* tok;
+ struct production *prod;
+ tok = $1;
+ prod = make_production (PROD_TYPE_NAME, tok);
+ NUMERIC_TYPE (prod) = SIGNED_INT;
+ prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+ $$ = prod;
+ }
+ |UNSIGNED INT {
+ struct token* tok;
+ struct production *prod;
+ tok = $1;
+ prod = make_production (PROD_TYPE_NAME, tok);
+ NUMERIC_TYPE (prod) = UNSIGNED_INT;
+ prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+ $$ = prod;
+ }
+ |CHAR {
+ struct token* tok;
+ struct production *prod;
+ tok = $1;
+ prod = make_production (PROD_TYPE_NAME, tok);
+ NUMERIC_TYPE (prod) = SIGNED_CHAR;
+ prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+ $$ = prod;
+ }
+ |UNSIGNED CHAR {
+ struct token* tok;
+ struct production *prod;
+ tok = $1;
+ prod = make_production (PROD_TYPE_NAME, tok);
+ NUMERIC_TYPE (prod) = UNSIGNED_CHAR;
+ prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+ $$ = prod;
+ }
+ |VOID {
+ struct token* tok;
+ struct production *prod;
+ tok = $1;
+ prod = make_production (PROD_TYPE_NAME, tok);
+ NUMERIC_TYPE (prod) = VOID_TYPE;
+ prod->code = tree_code_get_type (NUMERIC_TYPE (prod));
+ $$ = prod;
+ }
+ ;
+
+ parameters:
+ parameter {
+ /* Nothing to do. */
+ $$ = $1;
+ }
+ |parameters COMMA parameter {
+ struct production *prod1;
+ prod1 = $3;
+ prod1->next = $1; /* Insert in reverse order. */
+ $$ = prod1;
+ }
+ ;
+
+ statements:
+ statement {
+ /* Nothing to do. */
+ }
+ |statements statement {
+ /* Nothing to do. */
+ }
+ ;
+
+ statement:
+ expression SEMICOLON {
+ struct production *exp;
+ exp = $1;
+ tree_code_output_expression_statement (exp->code, in_fname,
exp->main_token->lineno);
+ }
+ |return SEMICOLON {
+ /* Nothing to do. */
+ }
+ |if_statement {
+ /* Nothing to do. */
+ }
+ ;
+
+ if_statement:
+ IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS {
+ struct token* tok;
+ struct production *exp;
+ tok = $1;
+ exp = $3;
+ ensure_not_void (NUMERIC_TYPE (exp), exp->main_token);
+ tree_code_if_start (exp->code, in_fname, tok->lineno);
+ }
+ LEFT_BRACE statements_opt RIGHT_BRACE {
+ /* Just let the statements flow. */
+ }
+ ELSE {
+ struct token* tok;
+ tok = $1;
+ tree_code_if_else (in_fname, tok->lineno);
+ }
+ LEFT_BRACE statements_opt RIGHT_BRACE {
+ struct token* tok;
+ tok = $12;
+ tree_code_if_end (in_fname, tok->lineno);
+ }
+ ;
+
+
+ return:
+ RETURN expression_opt {
+ struct production *type_prod;
+ struct token* ret_tok;
+ ret_tok = $1;
+ type_prod = EXPRESSION_TYPE (current_function);
+ if (NUMERIC_TYPE (type_prod) == VOID)
+ if ($2 == NULL)
+ tree_code_generate_return (type_prod->code, NULL);
+ else
+ {
+ fprintf (stderr, "%s:%i:%i: Redundant expression in return\n",
in_fname,
+ ret_tok->lineno, ret_tok->charno);
+ print_token (stderr, 0, ret_tok);
+ errorcount++;
+ tree_code_generate_return (type_prod->code, NULL);
+ }
+ else
+ if ($2 == NULL)
+ {
+ fprintf (stderr, "%s:%i:%i: Expression missing in return\n",
in_fname,
+ ret_tok->lineno, ret_tok->charno);
+ print_token (stderr, 0, ret_tok);
+ errorcount++;
+ }
+ else
+ {
+ struct production *exp;
+ exp = $2;
+ /* Check same type. */
+ if (check_type_match (NUMERIC_TYPE (type_prod), $2))
+ {
+ if (!type_prod->code)
+ abort ();
+ if (!exp->code)
+ abort ();
+ /* Generate the code. */
+ tree_code_generate_return (type_prod->code, exp->code);
+ }
+ }
+ }
+ ;
+
+ expression_opt:
+ /* Nil. */ {
+ $$ = 0;
+ }
+ |expression {
+ struct production *exp;
+ exp = $1;
+ if (!exp->code)
+ abort ();
+
+ $$ = $1;
+ }
+ ;
+
+ expression:
+ INTEGER {
+ $$ = make_integer_constant ($1);
+ }
+ |variable_ref {
+ $$ = $1;
+ }
+ |expression PLUS expression {
+ struct token* tok;
+ struct production *prod;
+ struct production *op1;
+ struct production *op2;
+ tree type;
+
+ op1 = $1;
+ op2 = $3;
+ tok = $2;
+ ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+ ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+ prod = make_production (PROD_PLUS_EXPRESSION, tok);
+ NUMERIC_TYPE (prod) = get_common_type (op1, op2);
+ if (!NUMERIC_TYPE (prod))
+ YYERROR;
+ else
+ {
+ type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+ if (!type)
+ abort ();
+ OP1 (prod) = $1;
+ OP2 (prod) = $3;
+
+ prod->code = tree_code_get_expression
+ (EXP_PLUS, type, op1->code, op2->code, NULL);
+ }
+ $$ = prod;
+ }
+ |expression MINUS expression %prec PLUS {
+ struct token* tok;
+ struct production *prod;
+ struct production *op1;
+ struct production *op2;
+ tree type;
+
+ op1 = $1;
+ op2 = $3;
+ ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+ ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+ tok = $2;
+ prod = make_production (PROD_PLUS_EXPRESSION, tok);
+ NUMERIC_TYPE (prod) = get_common_type (op1, op2);
+ if (!NUMERIC_TYPE (prod))
+ YYERROR;
+ else
+ {
+ type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+ if (!type)
+ abort ();
+ OP1 (prod) = $1;
+ OP2 (prod) = $3;
+
+ prod->code = tree_code_get_expression (EXP_MINUS,
+ type, op1->code, op2->code,
NULL);
+ }
+ $$ = prod;
+ }
+ |expression EQUALS expression {
+ struct token* tok;
+ struct production *prod;
+ struct production *op1;
+ struct production *op2;
+ tree type;
+
+ op1 = $1;
+ op2 = $3;
+ ensure_not_void (NUMERIC_TYPE (op1), op1->main_token);
+ ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+ tok = $2;
+ prod = make_production (PROD_PLUS_EXPRESSION, tok);
+ NUMERIC_TYPE (prod) = SIGNED_INT;
+ if (!NUMERIC_TYPE (prod))
+ YYERROR;
+ else
+ {
+ type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+ if (!type)
+ abort ();
+ OP1 (prod) = $1;
+ OP2 (prod) = $3;
+
+ prod->code = tree_code_get_expression (EXP_EQUALS,
+ type, op1->code, op2->code,
NULL);
+ }
+ $$ = prod;
+ }
+ |variable_ref ASSIGN expression {
+ struct token* tok;
+ struct production *prod;
+ struct production *op1;
+ struct production *op2;
+ tree type;
+
+ op1 = $1;
+ op2 = $3;
+ tok = $2;
+ ensure_not_void (NUMERIC_TYPE (op2), op2->main_token);
+ prod = make_production (PROD_ASSIGN_EXPRESSION, tok);
+ NUMERIC_TYPE (prod) = NUMERIC_TYPE (op1);
+ if (!NUMERIC_TYPE (prod))
+ YYERROR;
+ else
+ {
+ type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
+ if (!type)
+ abort ();
+ OP1 (prod) = $1;
+ OP2 (prod) = $3;
+ prod->code = tree_code_get_expression (EXP_ASSIGN,
+ type, op1->code, op2->code,
NULL);
+ }
+ $$ = prod;
+ }
+ |function_invocation {
+ $$ = $1;
+ }
+ ;
+
+ function_invocation:
+ NAME LEFT_PARENTHESIS expressions_with_commas RIGHT_PARENTHESIS {
+ struct production *prod;
+ struct token* tok;
+ struct production search_prod;
+ struct production *proto;
+ struct production *exp;
+ struct production *exp_proto;
+ struct production *var;
+ int exp_proto_count;
+ int exp_count;
+ tree parms;
+ tree type;
+
+ tok = $1;
+ prod = make_production (PROD_FUNCTION_INVOCATION, tok);
+ SYMBOL_TABLE_NAME (prod) = tok;
+ PARAMETERS (prod) = reverse_prod_list ($3);
+ SYMBOL_TABLE_NAME ((&search_prod)) = tok;
+ proto = lookup_tree_name (&search_prod);
+ if (!proto)
+ {
+ fprintf (stderr, "%s:%i:%i: Function prototype not found\n",
in_fname,
+ tok->lineno, tok->charno);
+ print_token (stderr, 0, tok);
+ errorcount++;
+ YYERROR;
+ }
+ EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto);
+ NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto);
+ /* Count the expressions and ensure they match the prototype. */
+ for (exp_proto_count = 0, exp_proto = PARAMETERS (proto);
+ exp_proto; exp_proto = exp_proto->next)
+ exp_proto_count++;
+
+ for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->next)
+ exp_count++;
+
+ if (exp_count != exp_proto_count)
+ {
+ fprintf (stderr, "%s:%i:%i: expression count mismatch with
prototype\n", in_fname,
+ tok->lineno, tok->charno);
+ print_token (stderr, 0, tok);
+ errorcount++;
+ YYERROR;
+ }
+ parms = tree_code_init_parameters ();
More information about the Gcc-patches
mailing list