home *** CD-ROM | disk | FTP | other *** search
- From tps@sdchemf.UUCP Tue Mar 3 16:31:17 1987
- Path: beno!seismo!lll-lcc!ames!ucbcad!ucbvax!sdcsvax!sdchem!tps
- From: tps@sdchem.UUCP (Tom Stockfisch)
- Newsgroups: net.sources
- Subject: ANSI C draft yacc grammar
- Message-ID: <645@sdchema.sdchem.UUCP>
- Date: 3 Mar 87 21:31:17 GMT
- References: <403@ubc-vision.UUCP>
- Sender: news@sdchem.UUCP
- Reply-To: tps@sdchemf.UUCP (Tom Stockfisch)
- Organization: UC San Diego
- Lines: 775
-
- People keep asking me for a copy, so I am reposting a yacc grammar (actually,
- a complete program) for the April 1985 draft of the ANSI C standard. It
- finds syntax errors in its input.
-
- Oh yeah, this was originally posted by Jeff Lee.
-
- || Tom Stockfisch, UCSD Chemistry tps%chem@sdcsvax.UCSD
-
- #!/bin/sh
- # to extract, remove the header and type "sh filename"
- if `test ! -s ./Makefile`
- then
- echo "writting ./Makefile"
- cat > ./Makefile << '\Rogue\Monster\'
- YFLAGS = -dv
- CFLAGS = -O
- LFLAGS =
-
- SRC = gram.y scan.l main.c
- OBJ = gram.o scan.o main.o
-
- $(BIN)/ansi_c : $(OBJ)
- cc $(CFLAGS) $(OBJ)/ansi_c
-
- scan.o : y.tab.h
-
- clean :
- rm -f y.tab.h y.output *.o
- \Rogue\Monster\
- else
- echo "will not over write ./Makefile"
- fi
- if `test ! -s ./README`
- then
- echo "writting ./README"
- cat > ./README << '\Rogue\Monster\'
- The files in this directory contain the ANSI C grammar from the April 30, 1985
- draft of the proposed standard. This copy also incorporates all bug fixes I
- have seen since the last two postings. With a little work this grammar can
- be made to parse the C that most of us know and love (sort of).
-
- There is one bug fix to the grammar that is in this posting. On line 295
- of gram.y it previously read declaration_specifiers instead of
- type_specifier_list as it does now. I believe the folks at the ANSI committee
- made a mistake since if you replace the line with what the original read
- you will end up with 16 shift/reduce errors and 2 reduce/reduce errors
- (the good ones). As it is, it only has 1 shift/reduce error that occurs
- on the if/else construct. YACC creates the correct parser and I don't want
- to ugly my grammar up.
-
- Anyway, all cumquats unite and generate this sucker. Then just sit and play
- with it. Remember, the grammar accepts things like
-
- "Hello, world"++;
- --1.23456;
- *'a'
-
- but this is not a bug, but simply a shuffling of the checking into the
- semantic analysis. If you want to hack it up to do lvalue and rvalue
- checking, I'm sure the ANSI committee would be glad to have your changes.
- Don't send'em to me though. I don't want'em. Wear this in good health.
-
- Jeff Lee
- gatech!jeff jeff@gatech jeff%gatech.CSNet@CSNet-Relay.ARPA
- \Rogue\Monster\
- else
- echo "will not over write ./README"
- fi
- if `test ! -s ./gram.y`
- then
- echo "writting ./gram.y"
- cat > ./gram.y << '\Rogue\Monster\'
- %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 RANGE
-
- %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
-
- %start file
- %%
-
- 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 '?' logical_or_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 ';'
- | declaration_specifiers init_declarator_list ';'
- ;
-
- declaration_specifiers
- : storage_class_specifier
- | storage_class_specifier declaration_specifiers
- | type_specifier
- | type_specifier declaration_specifiers
- ;
-
- init_declarator_list
- : init_declarator
- | init_declarator_list ',' init_declarator
- ;
-
- init_declarator
- : declarator
- | declarator '=' initializer
- ;
-
- storage_class_specifier
- : TYPEDEF
- | EXTERN
- | STATIC
- | AUTO
- | REGISTER
- ;
-
- type_specifier
- : CHAR
- | SHORT
- | INT
- | LONG
- | SIGNED
- | UNSIGNED
- | FLOAT
- | DOUBLE
- | CONST
- | VOLATILE
- | VOID
- | struct_or_union_specifier
- | enum_specifier
- | TYPE_NAME
- ;
-
- struct_or_union_specifier
- : struct_or_union identifier '{' struct_declaration_list '}'
- | struct_or_union '{' struct_declaration_list '}'
- | struct_or_union identifier
- ;
-
- struct_or_union
- : STRUCT
- | UNION
- ;
-
- struct_declaration_list
- : struct_declaration
- | struct_declaration_list struct_declaration
- ;
-
- struct_declaration
- : type_specifier_list struct_declarator_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 identifier '{' enumerator_list '}'
- | ENUM identifier
- ;
-
- enumerator_list
- : enumerator
- | enumerator_list ',' enumerator
- ;
-
- enumerator
- : identifier
- | identifier '=' constant_expr
- ;
-
- declarator
- : declarator2
- | pointer declarator2
- ;
-
- declarator2
- : identifier
- | '(' declarator ')'
- | declarator2 '[' ']'
- | declarator2 '[' constant_expr ']'
- | declarator2 '(' ')'
- | declarator2 '(' parameter_type_list ')'
- | declarator2 '(' parameter_identifier_list ')'
- ;
-
- pointer
- : '*'
- | '*' type_specifier_list
- | '*' pointer
- | '*' type_specifier_list pointer
- ;
-
- type_specifier_list
- : type_specifier
- | type_specifier_list type_specifier
- ;
-
- parameter_identifier_list
- : identifier_list
- | identifier_list ',' ELIPSIS
- ;
-
- identifier_list
- : identifier
- | identifier_list ',' identifier
- ;
-
- parameter_type_list
- : parameter_list
- | parameter_list ',' ELIPSIS
- ;
-
- parameter_list
- : parameter_declaration
- | parameter_list ',' parameter_declaration
- ;
-
- parameter_declaration
- : type_specifier_list declarator
- | type_name
- ;
-
- type_name
- : type_specifier_list
- | type_specifier_list abstract_declarator
- ;
-
- abstract_declarator
- : pointer
- | abstract_declarator2
- | pointer abstract_declarator2
- ;
-
- abstract_declarator2
- : '(' abstract_declarator ')'
- | '[' ']'
- | '[' constant_expr ']'
- | abstract_declarator2 '[' ']'
- | abstract_declarator2 '[' constant_expr ']'
- | '(' ')'
- | '(' parameter_type_list ')'
- | abstract_declarator2 '(' ')'
- | abstract_declarator2 '(' 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
- | declaration_list declaration
- ;
-
- 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 ';'
- ;
-
- file
- : external_definition
- | file external_definition
- ;
-
- external_definition
- : function_definition
- | declaration
- ;
-
- function_definition
- : declarator function_body
- | declaration_specifiers declarator function_body
- ;
-
- function_body
- : compound_statement
- | declaration_list compound_statement
- ;
-
- identifier
- : IDENTIFIER
- ;
- %%
-
- #include <stdio.h>
-
- extern char yytext[];
- extern int column;
-
- yyerror(s)
- char *s;
- {
- fflush(stdout);
- printf("\n%*s\n%*s\n", column, "^", column, s);
- }
- \Rogue\Monster\
- else
- echo "will not over write ./gram.y"
- fi
- if `test ! -s ./main.c`
- then
- echo "writting ./main.c"
- cat > ./main.c << '\Rogue\Monster\'
- main()
- {
- int yyparse();
-
- return(yyparse());
- }
- \Rogue\Monster\
- else
- echo "will not over write ./main.c"
- fi
- if `test ! -s ./scan.l`
- then
- echo "writting ./scan.l"
- cat > ./scan.l << '\Rogue\Monster\'
- D [0-9]
- L [a-zA-Z_]
- H [a-fA-F0-9]
- E [Ee][+-]?{D}+
- FS (f|F|l|L)
- IS (u|U|l|L)*
-
- %{
- #include <stdio.h>
- #include "y.tab.h"
-
- void count();
- %}
-
- %%
- "/*" { comment(); }
-
- "auto" { count(); return(AUTO); }
- "break" { count(); return(BREAK); }
- "case" { count(); return(CASE); }
- "char" { count(); return(CHAR); }
- "const" { count(); return(CONST); }
- "continue" { count(); return(CONTINUE); }
- "default" { count(); return(DEFAULT); }
- "do" { count(); return(DO); }
- "double" { count(); return(DOUBLE); }
- "else" { count(); return(ELSE); }
- "enum" { count(); return(ENUM); }
- "extern" { count(); return(EXTERN); }
- "float" { count(); return(FLOAT); }
- "for" { count(); return(FOR); }
- "goto" { count(); return(GOTO); }
- "if" { count(); return(IF); }
- "int" { count(); return(INT); }
- "long" { count(); return(LONG); }
- "register" { count(); return(REGISTER); }
- "return" { count(); return(RETURN); }
- "short" { count(); return(SHORT); }
- "signed" { count(); return(SIGNED); }
- "sizeof" { count(); return(SIZEOF); }
- "static" { count(); return(STATIC); }
- "struct" { count(); return(STRUCT); }
- "switch" { count(); return(SWITCH); }
- "typedef" { count(); return(TYPEDEF); }
- "union" { count(); return(UNION); }
- "unsigned" { count(); return(UNSIGNED); }
- "void" { count(); return(VOID); }
- "volatile" { count(); return(VOLATILE); }
- "while" { count(); return(WHILE); }
-
- {L}({L}|{D})* { count(); return(check_type()); }
-
- 0[xX]{H}+{IS}? { count(); return(CONSTANT); }
- 0[xX]{H}+{IS}? { count(); return(CONSTANT); }
- 0{D}+{IS}? { count(); return(CONSTANT); }
- 0{D}+{IS}? { count(); return(CONSTANT); }
- {D}+{IS}? { count(); return(CONSTANT); }
- {D}+{IS}? { count(); return(CONSTANT); }
- '(\\.|[^\\'])+' { count(); return(CONSTANT); }
-
- {D}+{E}{FS}? { count(); return(CONSTANT); }
- {D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); }
- {D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); }
-
- \"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
-
- ">>=" { count(); return(RIGHT_ASSIGN); }
- "<<=" { count(); return(LEFT_ASSIGN); }
- "+=" { count(); return(ADD_ASSIGN); }
- "-=" { count(); return(SUB_ASSIGN); }
- "*=" { count(); return(MUL_ASSIGN); }
- "/=" { count(); return(DIV_ASSIGN); }
- "%=" { count(); return(MOD_ASSIGN); }
- "&=" { count(); return(AND_ASSIGN); }
- "^=" { count(); return(XOR_ASSIGN); }
- "|=" { count(); return(OR_ASSIGN); }
- ">>" { count(); return(RIGHT_OP); }
- "<<" { count(); return(LEFT_OP); }
- "++" { count(); return(INC_OP); }
- "--" { count(); return(DEC_OP); }
- "->" { count(); return(PTR_OP); }
- "&&" { count(); return(AND_OP); }
- "||" { count(); return(OR_OP); }
- "<=" { count(); return(LE_OP); }
- ">=" { count(); return(GE_OP); }
- "==" { count(); return(EQ_OP); }
- "!=" { count(); return(NE_OP); }
- ";" { count(); return(';'); }
- "{" { count(); return('{'); }
- "}" { count(); return('}'); }
- "," { count(); return(','); }
- ":" { count(); return(':'); }
- "=" { count(); return('='); }
- "(" { count(); return('('); }
- ")" { count(); return(')'); }
- "[" { count(); return('['); }
- "]" { count(); return(']'); }
- "." { count(); return('.'); }
- "&" { count(); return('&'); }
- "!" { count(); return('!'); }
- "~" { count(); return('~'); }
- "-" { count(); return('-'); }
- "+" { count(); return('+'); }
- "*" { count(); return('*'); }
- "/" { count(); return('/'); }
- "%" { count(); return('%'); }
- "<" { count(); return('<'); }
- ">" { count(); return('>'); }
- "^" { count(); return('^'); }
- "|" { count(); return('|'); }
- "?" { count(); return('?'); }
-
- [ \t\v\n\f] { count(); }
- . { /* ignore bad characters */ }
-
- %%
-
- yywrap()
- {
- return(1);
- }
-
- comment()
- {
- char c, c1;
-
- loop:
- while ((c = input()) != '*' && c != 0)
- putchar(c);
-
- if ((c1 = input()) != '/' && c != 0)
- {
- unput(c1);
- goto loop;
- }
-
- if (c != 0)
- putchar(c1);
- }
-
- int column = 0;
-
- void count()
- {
- int i;
-
- for (i = 0; yytext[i] != '\0'; i++)
- if (yytext[i] == '\n')
- column = 0;
- else if (yytext[i] == '\t')
- column += 8 - (column % 8);
- else
- column++;
-
- ECHO;
- }
-
- int check_type()
- {
- /*
- * pseudo code --- this is what it should check
- *
- * if (yytext == type_name)
- * return(TYPE_NAME);
- *
- * return(IDENTIFIER);
- */
-
- /*
- * it actually will only return IDENTIFIER
- */
-
- return(IDENTIFIER);
- }
- \Rogue\Monster\
- else
- echo "will not over write ./scan.l"
- fi
- if `test ! -s ./y.tab.h`
- then
- echo "writting ./y.tab.h"
- cat > ./y.tab.h << '\Rogue\Monster\'
- # define IDENTIFIER 257
- # define CONSTANT 258
- # define STRING_LITERAL 259
- # define SIZEOF 260
- # define PTR_OP 261
- # define INC_OP 262
- # define DEC_OP 263
- # define LEFT_OP 264
- # define RIGHT_OP 265
- # define LE_OP 266
- # define GE_OP 267
- # define EQ_OP 268
- # define NE_OP 269
- # define AND_OP 270
- # define OR_OP 271
- # define MUL_ASSIGN 272
- # define DIV_ASSIGN 273
- # define MOD_ASSIGN 274
- # define ADD_ASSIGN 275
- # define SUB_ASSIGN 276
- # define LEFT_ASSIGN 277
- # define RIGHT_ASSIGN 278
- # define AND_ASSIGN 279
- # define XOR_ASSIGN 280
- # define OR_ASSIGN 281
- # define TYPE_NAME 282
- # define TYPEDEF 283
- # define EXTERN 284
- # define STATIC 285
- # define AUTO 286
- # define REGISTER 287
- # define CHAR 288
- # define SHORT 289
- # define INT 290
- # define LONG 291
- # define SIGNED 292
- # define UNSIGNED 293
- # define FLOAT 294
- # define DOUBLE 295
- # define CONST 296
- # define VOLATILE 297
- # define VOID 298
- # define STRUCT 299
- # define UNION 300
- # define ENUM 301
- # define ELIPSIS 302
- # define RANGE 303
- # define CASE 304
- # define DEFAULT 305
- # define IF 306
- # define ELSE 307
- # define SWITCH 308
- # define WHILE 309
- # define DO 310
- # define FOR 311
- # define GOTO 312
- # define CONTINUE 313
- # define BREAK 314
- # define RETURN 315
- \Rogue\Monster\
- else
- echo "will not over write ./y.tab.h"
- fi
- echo "Finished archive 1 of 1"
- exit
-
- || Tom Stockfisch, UCSD Chemistry tps%chem@sdcsvax.UCSD
-
-
-