mirror of
https://github.com/PDP-10/its.git
synced 2026-03-25 17:58:40 +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;}
|
|
|