home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
CPROTOS.ZIP
/
GRAM.Y
next >
Wrap
Text File
|
1991-02-19
|
18KB
|
885 lines
/*
This is a grammar for parsing ANSI C. Its not in a finished
state, but its pretty close. This is all covered under the
GNU Public lic. -- that means its free software, period.
mtr (mtr@ai.mit.edu)
*/
/* Tokens for C. */
%token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN TYPE_NAME
%token TYPEDEF EXTERN STATIC AUTO REGISTER
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
%token STRUCT UNION ENUM ELIPSIS
/* Reserved words. */
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%start translation_unit
%%
primary_expr
: identifier
| CONSTANT
| STRING_LITERAL
| '(' expr ')'
;
postfix_expr
: primary_expr
| postfix_expr '[' expr ']'
| postfix_expr '(' ')'
| postfix_expr '(' argument_expr_list ')'
| postfix_expr '.' identifier
| postfix_expr PTR_OP identifier
| postfix_expr INC_OP
| postfix_expr DEC_OP
;
argument_expr_list
: assignment_expr
| argument_expr_list ',' assignment_expr
;
unary_expr
: postfix_expr
| INC_OP unary_expr
| DEC_OP unary_expr
| unary_operator cast_expr
| SIZEOF unary_expr
| SIZEOF '(' type_name ')'
;
unary_operator
: '&' | '*' | '+' | '-' | '~' | '!'
;
cast_expr
: unary_expr
| '(' type_name ')' cast_expr
;
multiplicative_expr
: cast_expr
| multiplicative_expr '*' cast_expr
| multiplicative_expr '/' cast_expr
| multiplicative_expr '%' cast_expr
;
additive_expr
: multiplicative_expr
| additive_expr '+' multiplicative_expr
| additive_expr '-' multiplicative_expr
;
shift_expr
: additive_expr
| shift_expr LEFT_OP additive_expr
| shift_expr RIGHT_OP additive_expr
;
relational_expr
: shift_expr
| relational_expr '<' shift_expr
| relational_expr '>' shift_expr
| relational_expr LE_OP shift_expr
| relational_expr GE_OP shift_expr
;
equality_expr
: relational_expr
| equality_expr EQ_OP relational_expr
| equality_expr NE_OP relational_expr
;
and_expr
: equality_expr
| and_expr '&' equality_expr
;
exclusive_or_expr
: and_expr
| exclusive_or_expr '^' and_expr
;
inclusive_or_expr
: exclusive_or_expr
| inclusive_or_expr '|' exclusive_or_expr
;
logical_and_expr
: inclusive_or_expr
| logical_and_expr AND_OP inclusive_or_expr
;
logical_or_expr
: logical_and_expr
| logical_or_expr OR_OP logical_and_expr
;
conditional_expr
: logical_or_expr
| logical_or_expr '?' expr ':' conditional_expr
;
assignment_expr
: conditional_expr
| unary_expr assignment_operator assignment_expr
;
assignment_operator
: '=' | MUL_ASSIGN | DIV_ASSIGN | MOD_ASSIGN | ADD_ASSIGN | SUB_ASSIGN
| LEFT_ASSIGN | RIGHT_ASSIGN | AND_ASSIGN | XOR_ASSIGN | OR_ASSIGN
;
expr
: assignment_expr
| expr ',' assignment_expr
;
constant_expr
: conditional_expr
;
declaration
: declaration_specifiers ';'
{
$$ = $1;
}
| declaration_specifiers /* { reset_is_a_type = is_a_type; } */ init_declarator_list ';'
{
reset_is_a_type = 0;
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
/* This is such a hack. In the case for a list of
typedefs (eg "typedef int i, j, k; ") or a list of
structure tags (eg "struct { int i; } node, *ptr; "). */
if (0 == strcmp (((TRnode *) $$)->left->pc, "struct") ||
(0 == strcmp (((TRnode *) $$)->left->pc, "typedef")))
make_types ($2);
}
;
declaration_specifiers
: storage_class_specifier
{
$$ = $1;
}
| storage_class_specifier declaration_specifiers
{
$$ = $1;
if ($1 != 0)
((TRnode *) $1)->right = $2;
}
| type_specifier
{
$$ = $1;
}
| type_specifier declaration_specifiers
{
$$ = $1;
if ($1 != 0)
((TRnode *) $1)->right = $2;
}
| type_qualifier
{
$$ = $1;
}
| type_qualifier declaration_specifiers
{
$$ = $1;
if ($1 != 0)
((TRnode *) $1)->right = $2;
}
;
init_declarator_list
: init_declarator
{
$$ = $1;
}
| init_declarator_list ',' init_declarator
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $3;
}
;
init_declarator
: declarator
{
$$ = $1;
}
| declarator '=' initializer
{
$$ = make_root ("=", OP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $3;
}
;
storage_class_specifier
: TYPEDEF
{
set_type ();
$$ = make_root ("typedef", STORAGE_CLASS);
}
| EXTERN
{
$$ = make_root ("extern", STORAGE_CLASS);
}
| STATIC
{
$$ = make_root ("static", STORAGE_CLASS);
}
| AUTO
{
$$ = make_root ("auto", STORAGE_CLASS);
}
| REGISTER
{
$$ = make_root ("register", STORAGE_CLASS);
}
;
type_specifier
: VOID
{
$$ = make_root ("void", TYPE);
}
| CHAR
{
$$ = make_root ("char", TYPE);
}
| SHORT
{
$$ = make_root ("short", TYPE);
}
| INT
{
$$ = make_root ("int", TYPE);
}
| LONG
{
$$ = make_root ("long", TYPE);
}
| FLOAT
{
$$ = make_root ("float", TYPE);
}
| DOUBLE
{
$$ = make_root ("double", TYPE);
}
| SIGNED
{
$$ = make_root ("signed", TYPE);
}
| UNSIGNED
{
$$ = make_root ("unsigned", TYPE);
}
| struct_or_union_specifier
{
$$ = $1;
}
| enum_specifier
{
$$ = $1;
set_type ();
}
| TYPE_NAME
{
$$ = make_root (yytext, TYPE);
}
;
struct_or_union_specifier
: struct_or_union
{
/* unset_type (); */
reset_is_a_type = is_a_type;
unset_type ();
}
'{' { ++in_struct; } struct_declaration_list { --in_struct; } '}'
{
if (reset_is_a_type)
set_type ();
}
| struct_or_union identifier
{
/* add_type (((TRnode *) $2)->pc); */
reset_is_a_type = is_a_type;
unset_type ();
}
'{' { ++in_struct; } struct_declaration_list { --in_struct; } '}'
{
if (reset_is_a_type)
set_type ();
}
| struct_or_union identifier
{
/* POSSIBLY... */
/* set_type (); */
$$ = $2;
if (0 != $$)
((TRnode *) $$)->left = $1;
}
;
struct_or_union
: STRUCT
{
$$ = make_root ("struct", LABEL);
}
| UNION
{
$$ = make_root ("union", LABEL);
}
;
struct_declaration_list
: struct_declaration
| struct_declaration_list struct_declaration
;
struct_declaration
: specifier_qualifier_list struct_declarator_list ';'
;
specifier_qualifier_list
: type_specifier
| type_specifier specifier_qualifier_list
| type_qualifier
| type_qualifier specifier_qualifier_list
;
struct_declarator_list
: struct_declarator
| struct_declarator_list ',' struct_declarator
;
struct_declarator
: declarator
| ':' constant_expr
| declarator ':' constant_expr
;
enum_specifier
: ENUM '{' enumerator_list '}'
| ENUM '{' enumerator_list ',' '}'
| ENUM identifier '{' enumerator_list '}'
| ENUM identifier '{' enumerator_list ',' '}'
| ENUM identifier
;
enumerator_list
: enumerator
/* | enumerator ',' */
| enumerator_list ',' enumerator
;
enumerator
: identifier
| identifier '=' constant_expr
;
type_qualifier
: CONST
{
$$ = make_root ("const", LABEL);
}
| VOLATILE
{
$$ = make_root ("volatile", LABEL);
}
;
declarator
: direct_declarator
{
$$ = $1;
}
| pointer direct_declarator
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
}
;
direct_declarator
: identifier
{
$$ = make_root (yytext, IDENT);
add_type_maybe (yytext);
}
| '(' declarator ')'
| direct_declarator '[' ']'
| direct_declarator '[' constant_expr ']'
| direct_declarator '(' parameter_type_list ')'
{
$$ = $1;
if ($$ != 0)
((TRnode *) $$)->right = $3;
}
| direct_declarator '(' ')'
{
$$ = $1;
}
| direct_declarator '(' identifier_list ')'
{
$$ = $1;
if ($$ != 0)
((TRnode *) $$)->right = $3;
}
;
pointer
: '*'
{
$$ = make_root ("*", PTR);
}
/* FIX */
| '*' specifier_qualifier_list
| '*' pointer
{
$$ = make_root ("*", PTR);
((TRnode *) $$)->left = $2;
}
/* FIX */
| '*' specifier_qualifier_list pointer
;
parameter_type_list
: parameter_list
{
$$ = $1;
}
| parameter_list ',' ELIPSIS
;
parameter_list
: parameter_declaration
{
$$ = $1;
}
| parameter_list ',' parameter_declaration
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $3;
}
;
parameter_declaration
: declaration_specifiers declarator
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
}
| declaration_specifiers
{
$$ = $1;
}
| declaration_specifiers abstract_declarator
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
}
;
identifier_list
: identifier
{
$$ = $1;
}
| identifier_list ',' identifier
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $3;
}
;
type_name
: specifier_qualifier_list
| specifier_qualifier_list abstract_declarator
;
abstract_declarator
: pointer
{
$$ = $1;
}
| direct_abstract_declarator
{
$$ = $1;
}
| pointer direct_abstract_declarator
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
}
;
/* STOPED HERE */
direct_abstract_declarator
: '(' abstract_declarator ')'
| '[' ']'
| '[' constant_expr ']'
| direct_abstract_declarator '[' ']'
| direct_abstract_declarator '[' constant_expr ']'
| '(' ')'
| '(' parameter_type_list ')'
| direct_abstract_declarator '(' ')'
| direct_abstract_declarator '(' parameter_type_list ')'
;
initializer
: assignment_expr
| '{' initializer_list '}'
| '{' initializer_list ',' '}'
;
initializer_list
: initializer
| initializer_list ',' initializer
;
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
/* | ';' */
;
labeled_statement
: identifier ':' statement
| CASE constant_expr ':' statement
| DEFAULT ':' statement
;
compound_statement
: '{' '}'
| '{' statement_list '}'
| '{' declaration_list '}'
| '{' declaration_list statement_list '}'
;
declaration_list
: declaration
{
$$ = $1;
}
| declaration_list declaration
{
$$ = make_root ("nop", NOP);
((TRnode *) $$)->left = $1;
((TRnode *) $$)->right = $2;
}
;
statement_list
: statement
| statement_list statement
;
expression_statement
: ';'
| expr ';'
;
selection_statement
: IF '(' expr ')' statement
| IF '(' expr ')' statement ELSE statement
| SWITCH '(' expr ')' statement
;
iteration_statement
: WHILE '(' expr ')' statement
| DO statement WHILE '(' expr ')' ';'
| FOR '(' ';' ';' ')' statement
| FOR '(' ';' ';' expr ')' statement
| FOR '(' ';' expr ';' ')' statement
| FOR '(' ';' expr ';' expr ')' statement
| FOR '(' expr ';' ';' ')' statement
| FOR '(' expr ';' ';' expr ')' statement
| FOR '(' expr ';' expr ';' ')' statement
| FOR '(' expr ';' expr ';' expr ')' statement
;
jump_statement
: GOTO identifier ';'
| CONTINUE ';'
| BREAK ';'
| RETURN ';'
| RETURN expr ';'
;
translation_unit
: external_declaration
{ is_a_type = in_struct = 0; }
| translation_unit external_declaration
{ is_a_type = in_struct = 0; }
;
external_declaration
: function_definition
{
comment_counter = 0;
}
| declaration
{
comment_counter = 0;
}
;
function_definition
: declarator
{
LIadd (0, $1, 0);;
}
compound_statement
| declarator declaration_list
{
LIadd (0, $1, $2);
}
compound_statement
| declaration_specifiers declarator
{
LIadd ($1, $2, 0);
}
compound_statement
| declaration_specifiers declarator declaration_list
{
LIadd ($1, $2, $3);
}
compound_statement
;
identifier
: IDENTIFIER
{
$$ = make_root (yytext, IDENT);
}
;
%%
#include <stdio.h>
#include "tr.h"
int xxxx;
int is_a_type = 0;
int reset_is_a_type = 0;
int number_user_defined_types;
int type_list_size;
char **user_defined_types;
int in_struct = 0;
extern char yytext[];
extern int comment_counter;
int print_level;
int stop_level;
dump_types ()
{
int i;
printf ("TYPES\n");
for (i = 0; i < number_user_defined_types; i++)
printf ("%s\n", user_defined_types[i]);
printf ("\n\n");
}
char *
make_string (pc)
char *pc;
{
char *new_pc;
new_pc = (char *) malloc (strlen (pc) + 1);
if (0 == new_pc)
{
fprintf (stderr, "Memory error in make_string\n");
exit (2);
}
strcpy (new_pc, pc);
return new_pc;
}
set_type ()
{
is_a_type = 1;
reset_is_a_type = 0;
}
unset_type ()
{
is_a_type = 0;
}
add_type (type)
char *type;
{
is_a_type = 1;
add_type_maybe (type);
}
add_type_maybe (type)
char *type;
{
static int init = 0;
char *pc;
if (!is_a_type || in_struct)
return;
if (!init)
{
init = 1;
type_list_size = 1024;
number_user_defined_types = 0;
user_defined_types = (char **) malloc (sizeof (char *) * type_list_size);
if (0 == user_defined_types)
{
fprintf (stderr, "Memory error\n");
exit (2);
}
}
if (type_list_size == number_user_defined_types)
{
type_list_size *= 2;
user_defined_types = (char **) realloc (user_defined_types, type_list_size);
if (0 == user_defined_types)
{
fprintf (stderr, "Memory error\n");
exit (2);
}
}
/* printf ("\nADD TYPE <%s>\n", type);*/
user_defined_types[number_user_defined_types++] = make_string (type);
reset_is_a_type = is_a_type = 0;
}
int
output_tree (node, mode)
TRnode *node;
int mode;
{
if (0 == node )
return;
/* Inorder: Left-Root-Right. */
if (0 != node->left)
output_tree (node->left, mode);
/* if (NOP != node->type) */
{
char *lc;
switch (node->type) {
case NOP: lc = "NOP"; break;
case LABEL:lc = "LABEL"; break;
case IDENT:lc = "IDENT"; break;
case PTR: lc = "PTR"; break;
case STORAGE_CLASS: lc = "STORAGE_CLASS"; break;
case TYPE: lc = "TYPE"; break;
default: lc = "UNKNOWN"; break;
}
printf (" %s (%s)", node->pc, lc);
/* tladd (node);*/
}
if (0 != node->right)
output_tree (node->right, mode);
}
int
output_param_tree (node)
TRnode *node;
{
if (0 != node->left)
output_param_tree (node->left);
if (NOP != node->type)
{
printf (" %s", node->pc);
if (node->type == IDENT)
printf (";\n\t");
else
printf (" ");
}
if (0 != node->right)
output_param_tree (node->right);
}
TRnode *
make_root (pc, type)
char *pc;
int type;
{
TRnode *node;
node = malloc (sizeof (TRnode));
if (0 == node)
{
fprintf (stderr, "Memory problems with syntax tree\n");
exit (2);
}
node->left = 0;
node->right = 0;
node->pc = make_string (pc);
node->type = type;
return node;
}
make_types (node)
TRnode *node;
{
if (0 == node)
return;
if (0 != node->left)
make_types (node->left);
if (IDENT == node->type && TYPE_NAME != check_type (node->pc))
{
add_type (node->pc);
}
if (0 != node->right)
make_types (node->right);
}