mirror of
https://github.com/PDP-10/PCC20.git
synced 2026-05-01 14:16:13 +00:00
397 lines
11 KiB
Plaintext
397 lines
11 KiB
Plaintext
|
||
# C GRAMMAR #
|
||
# 28 May 1978 #
|
||
# Alan Snyder #
|
||
|
||
|
||
# 26 acceptable conflicts:
|
||
|
||
2 S/R conflicts for (parsing) ambiguity between
|
||
declarators and function_declarators
|
||
1 S/R conflict for the C ELSE ambiguity
|
||
4 R/R conflicts for the (parsing) problem with regard
|
||
to integer constants as initial_values
|
||
12 R/R conflicts for the (parsing) problem with regard
|
||
to identifiers in function calls
|
||
1 R/R conflict for the (parsing) problem with regard
|
||
to identifiers in goto statements
|
||
4 R/R conflicts and 1 S/R conflict for TYPEDEFs
|
||
1 S/R conflict for ambiguous cast types
|
||
(int ()) = (int x()) not (int (x))
|
||
|
||
Approximate description:
|
||
|
||
18 S/R ( shift 37 reduce 141
|
||
50 S/R ( shift 37 reduce 71
|
||
81 S/R ( shift 37 reduce 71
|
||
113 R/R ( reduce 141 reduce 140
|
||
113 R/R ( reduce 159 reduce 140
|
||
113 R/R * reduce 159 reduce 141
|
||
113 S/R : shift 199 reduce 141
|
||
183 R/R , reduce 203 reduce 24
|
||
183 R/R } reduce 203 reduce 24
|
||
204 R/R ( reduce 159 reduce 140
|
||
206 R/R ( reduce 148 reduce 139
|
||
207 R/R ( reduce 147 reduce 139
|
||
208 R/R ( reduce 145 reduce 139
|
||
209 R/R ( reduce 144 reduce 139
|
||
210 R/R ( reduce 146 reduce 139
|
||
211 R/R ( reduce 149 reduce 139
|
||
212 R/R ( reduce 150 reduce 139
|
||
215 R/R ( reduce 159 reduce 140
|
||
215 R/R ; reduce 159 reduce 138
|
||
225 R/R ( reduce 151 reduce 139
|
||
228 R/R ( reduce 159 reduce 140
|
||
284 R/R , reduce 203 reduce 25
|
||
284 R/R } reduce 203 reduce 25
|
||
291 S/R ) shift 339 reduce 165
|
||
343 R/R ( reduce 153 reduce 139
|
||
360 S/R ELSE shift 369 reduce 94
|
||
|
||
#
|
||
|
||
# terminal symbols #
|
||
|
||
';' '}' '{' ']' '[' ')' '(' ':'
|
||
',' '.' '?' '~' '!' '&' '|' '^'
|
||
'%' '/' '*' '-' '+' '=' '<' '>'
|
||
'++' '--' '==' '!=' '<=' '>=' '<<' '>>'
|
||
'->' '=op' '&&' '||' 'c'
|
||
INT CHAR FLOAT DOUBLE STRUCT AUTO STATIC
|
||
EXTERN RETURN GOTO IF ELSE SWITCH
|
||
BREAK CONTINUE WHILE DO FOR DEFAULT CASE
|
||
ENTRY REGISTER SIZEOF LONG SHORT UNSIGNED TYPEDEF 'l'
|
||
'm' 'n' 'o' 'p' 'q' 'r' 's'
|
||
identifier integer floatcon string
|
||
|
||
# precedence information #
|
||
|
||
\< ','
|
||
\> '=' '=op'
|
||
\> '?' ':'
|
||
\< '||'
|
||
\< '&&'
|
||
\< '|'
|
||
\< '^'
|
||
\< '&'
|
||
\< '==' '!='
|
||
\< '<' '>' '<=' '>='
|
||
\< '<<' '>>'
|
||
\< '+' '-'
|
||
\< '*' '/' '%'
|
||
\> '!' '~'
|
||
\> '++' '--' SIZEOF
|
||
\< '[' '(' '.' '->'
|
||
|
||
\\
|
||
|
||
# external definitions #
|
||
|
||
program:
|
||
program external_definition
|
||
|
|
||
|
||
external_definition:
|
||
declaration
|
||
| function_definition
|
||
|
||
function_definition:
|
||
function_specification function_body {afdef(#1,#2);}
|
||
|
||
function_specification:
|
||
decl_specifiers function_declarator {val=afdcl(1);}
|
||
| function_declarator {val=afdcl(0);}
|
||
|
||
function_body:
|
||
formal_declarations compound_statement {val=#2;}
|
||
|
||
formal_declarations:
|
||
formal_decl_list {afpdcl();}
|
||
| {afpdcl();}
|
||
|
||
compound_statement:
|
||
begin declaration_list statement_list end {val=#3;}
|
||
| begin statement_list end {val=#2;}
|
||
|
||
init_declarator_list:
|
||
init_declarator
|
||
| init_declarator_list ',' init_declarator
|
||
|
||
init_declarator:
|
||
$declarator initializer {aidecl();}
|
||
| declarator {aidecl();}
|
||
| function_declarator {adeclr(maktyp());}
|
||
|
||
initializer:
|
||
initial_value
|
||
| '{' initial_value_expression_list '}'
|
||
| '{' initial_value_expression_list ',' '}'
|
||
|
||
initial_value_expression_list:
|
||
initial_value_expression
|
||
| initial_value_expression_list ',' initial_value_expression
|
||
|
||
initial_value:
|
||
integer {inz(i_int,#1);}
|
||
| '-' integer {inz(i_int,-#2);}
|
||
| floatcon {inz(i_float,#1);}
|
||
| '-' floatcon {inz(i_negfloat,#2);}
|
||
| identifier {inz(i_idn,#1);}
|
||
| '&' identifier {inz(i_idn,#2);}
|
||
| string {inz(i_string,#1);}
|
||
|
||
initial_value_expression:
|
||
constant {inz(i_int,#1);}
|
||
| initial_value
|
||
|
||
# declarations #
|
||
|
||
declaration_list:
|
||
declaration
|
||
| declaration_list declaration
|
||
|
||
declaration:
|
||
decl_specifiers init_declarator_list ';'
|
||
| literal_type_specifier ';'
|
||
|
||
decl_specifiers:
|
||
type_specifier {attrib(-1,#1);}
|
||
| sc_specifier type_specifier {attrib(#1,#2);}
|
||
| type_specifier sc_specifier {attrib(#2,#1);}
|
||
|
||
type_specifier:
|
||
type_identifier
|
||
| literal_type_specifier
|
||
|
||
literal_type_specifier:
|
||
INT {val=TINT;}
|
||
| CHAR {val=TCHAR;}
|
||
| FLOAT {val=TFLOAT;}
|
||
| DOUBLE {val=TDOUBLE;}
|
||
| LONG {val=TINT;}
|
||
| LONG INT {val=TINT;}
|
||
| SHORT {val=TINT;}
|
||
| SHORT INT {val=TINT;}
|
||
| LONG FLOAT {val=TDOUBLE;}
|
||
| UNSIGNED {val=TINT;}
|
||
| UNSIGNED INT {val=TINT;}
|
||
| struct '{' type_decl_list '}' {val=astruct(NULL,#3);}
|
||
| struct $identifier '{' type_decl_list '}' {val=astruct(#2,#4);}
|
||
| struct identifier {val=aostruct(#2);}
|
||
|
||
sc_specifier:
|
||
AUTO {val=c_auto;}
|
||
| STATIC {val=c_static;}
|
||
| EXTERN {val=c_extern;}
|
||
| REGISTER {val=c_auto;}
|
||
| TYPEDEF {val=c_typedef;}
|
||
|
||
declarator_list:
|
||
declarator
|
||
| declarator_list ',' declarator
|
||
|
||
declarator:
|
||
dclr {val=adeclr(maktyp());}
|
||
| identifier ':' constant {val=adeclr(afield(#1,#3));}
|
||
| ':' constant {val=adeclr(afield(-1,#2));}
|
||
|
||
$declarator:
|
||
dclr {aiinz(adeclr(maktyp()));}
|
||
|
||
dclr:
|
||
'*' dclr {val=adclr(#2,MPTR);}
|
||
| dclr '(' ')' {val=adclr(#1,MFUNC);}
|
||
| dclr '[' ']' {val=adclr(#1,MARRAY,1);}
|
||
| dclr '[' constant ']' {val=adclr(#1,MARRAY,#3);}
|
||
| identifier {val=adclr(0,0);}
|
||
| '(' dclr ')' {val=#2;}
|
||
|
||
function_declarator:
|
||
'*' function_declarator {val=adclr(#2,MPTR);}
|
||
| function_declarator '(' ')' {val=adclr(#1,MFUNC);}
|
||
| function_declarator '[' ']' {val=adclr(#1,MARRAY,1);}
|
||
| function_declarator '[' constant ']' {val=adclr(#1,MARRAY,#3);}
|
||
| identifier '(' ')' {val=adclr(adclr(0,0),MFUNC);
|
||
parml=0;}
|
||
| identifier '(' parameter_list ')' {val=adclr(adclr(0,0),MFUNC);
|
||
parml=#3;}
|
||
| '(' function_declarator ')' {val=#2;}
|
||
|
||
parameter_list:
|
||
identifier {val=push(#1);}
|
||
| parameter_list ',' identifier {push(#3);}
|
||
|
||
formal_decl_list:
|
||
formal_declaration
|
||
| formal_decl_list formal_declaration
|
||
|
||
formal_declaration:
|
||
type_declaration
|
||
| REGISTER type_declaration
|
||
|
||
type_decl_list:
|
||
type_declaration
|
||
| type_decl_list type_declaration
|
||
|
||
type_declaration:
|
||
$type_specifier declarator_list ';' {in_type_def=0;
|
||
val=#2;}
|
||
|
||
$type_specifier:
|
||
type_specifier {in_type_def=1;
|
||
attrib(-1,#1);}
|
||
|
||
# statements #
|
||
|
||
statement_list:
|
||
statement
|
||
| statement_list statement {val=astmtl(#1,#2);}
|
||
|
||
statement:
|
||
expression ';' {val=aexprstmt(#1);}
|
||
| compound_statement
|
||
| IF '(' expression ')' statement {val=aif(#3,#5,0);}
|
||
| IF '(' expression ')' statement ELSE statement {val=aif(#3,#5,#7);}
|
||
| while '(' expression ')' statement {val=awhile(#3,#5);}
|
||
| for '(' .expression ';' .expression ';' .expression ')' statement
|
||
{val=afor(#3,#5,#7,#9);}
|
||
| do statement WHILE '(' expression ')' ';' {val=ado(#2,#5);}
|
||
| switch '(' expression ')' statement {val=aswitch(#3,#5);}
|
||
| CASE constant ':' statement {val=acase(#2,#4);}
|
||
| DEFAULT ':' statement {val=adefault(#3);}
|
||
| BREAK ';' {val=abreak();}
|
||
| CONTINUE ';' {val=acontinue();}
|
||
| RETURN ';' {val=areturn(0);}
|
||
| RETURN expression ';' {val=areturn(#2);}
|
||
| GOTO lexpression ';' {val=agoto(#2);}
|
||
| identifier ':' statement {val=alabel(#1,#3);}
|
||
| ENTRY identifier ':' statement {val=aentry(#2,#4);}
|
||
| ';' {val=anull();}
|
||
|
||
|
||
# expressions #
|
||
|
||
.expression:
|
||
expression
|
||
| {val=0;}
|
||
|
||
expression_list:
|
||
expression \= '='
|
||
| expression_list ',' expression {val=aelist(#1,#3);}
|
||
|
||
expression:
|
||
expression '*' expression {val=node(n_times,#1,#3);}
|
||
| expression '/' expression {val=node(n_div,#1,#3);}
|
||
| expression '%' expression {val=node(n_mod,#1,#3);}
|
||
| expression '+' expression {val=node(n_plus,#1,#3);}
|
||
| expression '-' expression {val=node(n_minus,#1,#3);}
|
||
| expression '<<' expression {val=node(n_ls,#1,#3);}
|
||
| expression '>>' expression {val=node(n_rs,#1,#3);}
|
||
| expression '<' expression {val=node(n_lt,#1,#3);}
|
||
| expression '>' expression {val=node(n_gt,#1,#3);}
|
||
| expression '<=' expression {val=node(n_le,#1,#3);}
|
||
| expression '>=' expression {val=node(n_ge,#1,#3);}
|
||
| expression '==' expression {val=node(n_eq,#1,#3);}
|
||
| expression '!=' expression {val=node(n_ne,#1,#3);}
|
||
| expression '&' expression {val=node(n_band,#1,#3);}
|
||
| expression '^' expression {val=node(n_bxor,#1,#3);}
|
||
| expression '|' expression {val=node(n_bior,#1,#3);}
|
||
| expression '&&' expression {val=node(n_tv_and,#1,#3);}
|
||
| expression '||' expression {val=node(n_tv_or,#1,#3);}
|
||
| expression '?' expression ':' expression
|
||
{val=node(n_qmark,#1,node(n_colon,#3,#5));}
|
||
| expression '=' expression {val=node(n_assign,#1,#3);}
|
||
| expression '=op' expression {val=node(n_ars+#2,#1,#3);}
|
||
| expression ',' expression {val=node(n_comma,#1,#3);}
|
||
| term
|
||
|
||
# the following productions are ordered very carefully so that the
|
||
desired thing is done in the case of a R/R conflict #
|
||
|
||
lexpression:
|
||
expression
|
||
| identifier {val=aidn(alidn(#1));}
|
||
|
||
fterm:
|
||
term
|
||
| identifier {val=aidn(afidn(#1));}
|
||
|
||
type_identifier:
|
||
identifier {val=atidn(#1);}
|
||
|
||
term:
|
||
term '++' {val=node(n_inca,#1);}
|
||
| term '--' {val=node(n_deca,#1);}
|
||
| '*' term {val=node(n_star,#2);}
|
||
| '&' term {val=node(n_addr,#2);}
|
||
| '-' term {val=node(n_uminus,#2);}
|
||
| '!' term {val=node(n_tvnot,#2);}
|
||
| '~' term {val=node(n_bnot,#2);}
|
||
| '++' term {val=node(n_incb,#2);}
|
||
| '--' term {val=node(n_decb,#2);}
|
||
| SIZEOF term {val=node(n_sizeof,#2);}
|
||
| SIZEOF '(' cast_type ')' \= SIZEOF
|
||
{val=node(n_int,1);} # hack #
|
||
| '(' cast_type ')' term \= '++'
|
||
{val=#4;} # hack #
|
||
| term '[' expression ']' {val=asubscript(#1,#3);}
|
||
| fterm '(' expression_list ')' {val=acall(#1,#3);}
|
||
| fterm '(' ')' {val=acall(#1,0);}
|
||
| term '.' identifier {val=adot(#1,#3);}
|
||
| term '->' identifier {val=aptr(#1,#3);}
|
||
| identifier {val=aidn(aeidn(#1));}
|
||
| integer {val=node(n_int,#1);}
|
||
| floatcon {val=node(n_float,#1);}
|
||
| string {val=node(n_string,#1);}
|
||
| '(' expression ')' {val=#2;}
|
||
|
||
cast_type: literal_type_specifier null_decl
|
||
|
||
null_decl: # empty #
|
||
| '(' ')'
|
||
| '(' null_decl ')' '(' ')'
|
||
| '*' null_decl
|
||
| null_decl '[' ']'
|
||
| null_decl '[' constant ']'
|
||
| '(' null_decl ')'
|
||
|
||
while: WHILE {apshw();}
|
||
do: DO {apshd();}
|
||
for: FOR {apshf();}
|
||
switch: SWITCH {apshs();}
|
||
struct: STRUCT {strlev++;}
|
||
$identifier: identifier {val=astridn(#1);}
|
||
begin: '{' {abegin();}
|
||
end: '}' {aend();}
|
||
|
||
constant:
|
||
constant '*' constant {val=#1*#3;}
|
||
| constant '/' constant {val=#1/#3;}
|
||
| constant '%' constant {val=#1%#3;}
|
||
| constant '+' constant {val=#1+#3;}
|
||
| constant '-' constant {val=#1-#3;}
|
||
| constant '<<' constant {val=#1<<#3;}
|
||
| constant '>>' constant {val=#1>>#3;}
|
||
| constant '<' constant {val=#1<#3;}
|
||
| constant '>' constant {val=#1>#3;}
|
||
| constant '<=' constant {val=#1<=#3;}
|
||
| constant '>=' constant {val=#1>=#3;}
|
||
| constant '==' constant {val=#1==#3;}
|
||
| constant '!=' constant {val=#1!=#3;}
|
||
| constant '&' constant {val=#1}
|
||
| constant '^' constant {val=#1^#3;}
|
||
| constant '|' constant {val=#1|#3;}
|
||
| constant '&&' constant {val=#1&}
|
||
| constant '||' constant {val=#1||#3;}
|
||
| constant '?' constant ':' constant
|
||
{val=(#1?#3:#5);}
|
||
| c_term
|
||
|
||
c_term:
|
||
'-' c_term {val= -#2;}
|
||
| '!' c_term {val= !#2;}
|
||
| '~' c_term {val= ~#2;}
|
||
| integer
|
||
| '(' constant ')' {val=#2;}
|
||
|
||
|