initial commit
This commit is contained in:
commit
fedaac132d
|
|
@ -0,0 +1,21 @@
|
||||||
|
CC_BIN ?= gcc
|
||||||
|
LEX_BIN ?= flex
|
||||||
|
YACC_BIN ?= bison
|
||||||
|
|
||||||
|
GRAMMARS_DIR ?= ./grammars
|
||||||
|
GRAMMAR_ID ?= quut
|
||||||
|
output ?= $(GRAMMAR_ID)-cocc
|
||||||
|
|
||||||
|
all: $(output)
|
||||||
|
|
||||||
|
$(GRAMMAR_ID).tab.h: $(GRAMMARS_DIR)/$(GRAMMAR_ID).y
|
||||||
|
$(YACC_BIN) -d $?
|
||||||
|
|
||||||
|
lex.yy.c: $(GRAMMARS_DIR)/$(GRAMMAR_ID).l $(GRAMMAR_ID).tab.h
|
||||||
|
$(LEX_BIN) $<
|
||||||
|
|
||||||
|
$(output): lex.yy.c $(GRAMMAR_ID).tab.c $(GRAMMAR_ID).tab.h
|
||||||
|
$(CC_BIN) -o $@ lex.yy.c $(GRAMMAR_ID).tab.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f lex.yy.c *.tab.c *.tab.h *-cocc
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
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 "examp.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{D}+{IS}? { count(); return(CONSTANT); }
|
||||||
|
{D}+{IS}? { count(); return(CONSTANT); }
|
||||||
|
L?'(\\.|[^\\'])+' { count(); return(CONSTANT); }
|
||||||
|
|
||||||
|
{D}+{E}{FS}? { count(); return(CONSTANT); }
|
||||||
|
{D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); }
|
||||||
|
{D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); }
|
||||||
|
|
||||||
|
L?\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
|
||||||
|
|
||||||
|
"..." { count(); return(ELLIPSIS); }
|
||||||
|
">>=" { 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;
|
||||||
|
|
||||||
|
//p¼Æ¾¹
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,435 @@
|
||||||
|
%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 ELLIPSIS
|
||||||
|
|
||||||
|
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
||||||
|
|
||||||
|
%start translation_unit
|
||||||
|
%%
|
||||||
|
|
||||||
|
//語意規則
|
||||||
|
primary_expression
|
||||||
|
: IDENTIFIER
|
||||||
|
| CONSTANT
|
||||||
|
| STRING_LITERAL
|
||||||
|
| '(' expression ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
postfix_expression
|
||||||
|
: primary_expression
|
||||||
|
| postfix_expression '[' expression ']'
|
||||||
|
| postfix_expression '(' ')'
|
||||||
|
| postfix_expression '(' argument_expression_list ')'
|
||||||
|
| postfix_expression '.' IDENTIFIER
|
||||||
|
| postfix_expression PTR_OP IDENTIFIER
|
||||||
|
| postfix_expression INC_OP
|
||||||
|
| postfix_expression DEC_OP
|
||||||
|
;
|
||||||
|
|
||||||
|
argument_expression_list
|
||||||
|
: assignment_expression
|
||||||
|
| argument_expression_list ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_expression
|
||||||
|
: postfix_expression
|
||||||
|
| INC_OP unary_expression
|
||||||
|
| DEC_OP unary_expression
|
||||||
|
| unary_operator cast_expression
|
||||||
|
| SIZEOF unary_expression
|
||||||
|
| SIZEOF '(' type_name ')'
|
||||||
|
;
|
||||||
|
//unary語法
|
||||||
|
unary_operator
|
||||||
|
: '&'
|
||||||
|
| '*'
|
||||||
|
| '+'
|
||||||
|
| '-'
|
||||||
|
| '~'
|
||||||
|
| '!'
|
||||||
|
;
|
||||||
|
//形態轉換語法
|
||||||
|
cast_expression
|
||||||
|
: unary_expression
|
||||||
|
| '(' type_name ')' cast_expression
|
||||||
|
;
|
||||||
|
//* / %語法
|
||||||
|
multiplicative_expression
|
||||||
|
: cast_expression
|
||||||
|
| multiplicative_expression '*' cast_expression
|
||||||
|
| multiplicative_expression '/' cast_expression
|
||||||
|
| multiplicative_expression '%' cast_expression
|
||||||
|
;
|
||||||
|
//+ - 語法
|
||||||
|
additive_expression
|
||||||
|
: multiplicative_expression
|
||||||
|
| additive_expression '+' multiplicative_expression
|
||||||
|
| additive_expression '-' multiplicative_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
shift_expression
|
||||||
|
: additive_expression
|
||||||
|
| shift_expression LEFT_OP additive_expression
|
||||||
|
| shift_expression RIGHT_OP additive_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
relational_expression
|
||||||
|
: shift_expression
|
||||||
|
| relational_expression '<' shift_expression
|
||||||
|
| relational_expression '>' shift_expression
|
||||||
|
| relational_expression LE_OP shift_expression
|
||||||
|
| relational_expression GE_OP shift_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
equality_expression
|
||||||
|
: relational_expression
|
||||||
|
| equality_expression EQ_OP relational_expression
|
||||||
|
| equality_expression NE_OP relational_expression
|
||||||
|
;
|
||||||
|
//And語法
|
||||||
|
and_expression
|
||||||
|
: equality_expression
|
||||||
|
| and_expression '&' equality_expression
|
||||||
|
;
|
||||||
|
//XOR語法
|
||||||
|
exclusive_or_expression
|
||||||
|
: and_expression
|
||||||
|
| exclusive_or_expression '^' and_expression
|
||||||
|
;
|
||||||
|
//or 語法
|
||||||
|
inclusive_or_expression
|
||||||
|
: exclusive_or_expression
|
||||||
|
| inclusive_or_expression '|' exclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_and_expression
|
||||||
|
: inclusive_or_expression
|
||||||
|
| logical_and_expression AND_OP inclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_or_expression
|
||||||
|
: logical_and_expression
|
||||||
|
| logical_or_expression OR_OP logical_and_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
conditional_expression
|
||||||
|
: logical_or_expression
|
||||||
|
| logical_or_expression '?' expression ':' conditional_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
assignment_expression
|
||||||
|
: conditional_expression
|
||||||
|
| unary_expression assignment_operator assignment_expression
|
||||||
|
;
|
||||||
|
// = 語法
|
||||||
|
assignment_operator
|
||||||
|
: '='
|
||||||
|
| MUL_ASSIGN
|
||||||
|
| DIV_ASSIGN
|
||||||
|
| MOD_ASSIGN
|
||||||
|
| ADD_ASSIGN
|
||||||
|
| SUB_ASSIGN
|
||||||
|
| LEFT_ASSIGN
|
||||||
|
| RIGHT_ASSIGN
|
||||||
|
| AND_ASSIGN
|
||||||
|
| XOR_ASSIGN
|
||||||
|
| OR_ASSIGN
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: assignment_expression
|
||||||
|
| expression ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
constant_expression
|
||||||
|
: conditional_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration
|
||||||
|
: declaration_specifiers ';'
|
||||||
|
| declaration_specifiers init_declarator_list ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration_specifiers
|
||||||
|
: storage_class_specifier
|
||||||
|
| storage_class_specifier declaration_specifiers
|
||||||
|
| type_specifier
|
||||||
|
| type_specifier declaration_specifiers
|
||||||
|
| type_qualifier
|
||||||
|
| type_qualifier 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
|
||||||
|
: VOID
|
||||||
|
| CHAR
|
||||||
|
| SHORT
|
||||||
|
| INT
|
||||||
|
| LONG
|
||||||
|
| FLOAT
|
||||||
|
| DOUBLE
|
||||||
|
| SIGNED
|
||||||
|
| UNSIGNED
|
||||||
|
| 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
|
||||||
|
: specifier_qualifier_list struct_declarator_list ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
specifier_qualifier_list
|
||||||
|
: type_specifier specifier_qualifier_list
|
||||||
|
| type_specifier
|
||||||
|
| type_qualifier specifier_qualifier_list
|
||||||
|
| type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator_list
|
||||||
|
: struct_declarator
|
||||||
|
| struct_declarator_list ',' struct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator
|
||||||
|
: declarator
|
||||||
|
| ':' constant_expression
|
||||||
|
| declarator ':' constant_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_specifier
|
||||||
|
: ENUM '{' enumerator_list '}'
|
||||||
|
| ENUM IDENTIFIER '{' enumerator_list '}'
|
||||||
|
| ENUM IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator_list
|
||||||
|
: enumerator
|
||||||
|
| enumerator_list ',' enumerator
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator
|
||||||
|
: IDENTIFIER
|
||||||
|
| IDENTIFIER '=' constant_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier
|
||||||
|
: CONST
|
||||||
|
| VOLATILE
|
||||||
|
;
|
||||||
|
|
||||||
|
declarator
|
||||||
|
: pointer direct_declarator
|
||||||
|
| direct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_declarator
|
||||||
|
: IDENTIFIER
|
||||||
|
| '(' declarator ')'
|
||||||
|
| direct_declarator '[' constant_expression ']'
|
||||||
|
| direct_declarator '[' ']'
|
||||||
|
| direct_declarator '(' parameter_type_list ')'
|
||||||
|
| direct_declarator '(' identifier_list ')'
|
||||||
|
| direct_declarator '(' ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
pointer
|
||||||
|
: '*'
|
||||||
|
| '*' type_qualifier_list
|
||||||
|
| '*' pointer
|
||||||
|
| '*' type_qualifier_list pointer
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier_list
|
||||||
|
: type_qualifier
|
||||||
|
| type_qualifier_list type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
parameter_type_list
|
||||||
|
: parameter_list
|
||||||
|
| parameter_list ',' ELLIPSIS
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_list
|
||||||
|
: parameter_declaration
|
||||||
|
| parameter_list ',' parameter_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_declaration
|
||||||
|
: declaration_specifiers declarator
|
||||||
|
| declaration_specifiers abstract_declarator
|
||||||
|
| declaration_specifiers
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier_list
|
||||||
|
: IDENTIFIER
|
||||||
|
| identifier_list ',' IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
type_name
|
||||||
|
: specifier_qualifier_list
|
||||||
|
| specifier_qualifier_list abstract_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
abstract_declarator
|
||||||
|
: pointer
|
||||||
|
| direct_abstract_declarator
|
||||||
|
| pointer direct_abstract_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_abstract_declarator
|
||||||
|
: '(' abstract_declarator ')'
|
||||||
|
| '[' ']'
|
||||||
|
| '[' constant_expression ']'
|
||||||
|
| direct_abstract_declarator '[' ']'
|
||||||
|
| direct_abstract_declarator '[' constant_expression ']'
|
||||||
|
| '(' ')'
|
||||||
|
| '(' parameter_type_list ')'
|
||||||
|
| direct_abstract_declarator '(' ')'
|
||||||
|
| direct_abstract_declarator '(' parameter_type_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
initializer
|
||||||
|
: assignment_expression
|
||||||
|
| '{' 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_expression ':' 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
|
||||||
|
: ';'
|
||||||
|
| expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
selection_statement
|
||||||
|
: IF '(' expression ')' statement
|
||||||
|
| IF '(' expression ')' statement ELSE statement
|
||||||
|
| SWITCH '(' expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
iteration_statement
|
||||||
|
: WHILE '(' expression ')' statement
|
||||||
|
| DO statement WHILE '(' expression ')' ';'
|
||||||
|
| FOR '(' expression_statement expression_statement ')' statement
|
||||||
|
| FOR '(' expression_statement expression_statement expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
jump_statement
|
||||||
|
: GOTO IDENTIFIER ';'
|
||||||
|
| CONTINUE ';'
|
||||||
|
| BREAK ';'
|
||||||
|
| RETURN ';'
|
||||||
|
| RETURN expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
translation_unit
|
||||||
|
: external_declaration
|
||||||
|
| translation_unit external_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
external_declaration
|
||||||
|
: function_definition
|
||||||
|
| declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
function_definition
|
||||||
|
: declaration_specifiers declarator declaration_list compound_statement
|
||||||
|
| declaration_specifiers declarator compound_statement
|
||||||
|
| declarator declaration_list compound_statement
|
||||||
|
| declarator compound_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern char yytext[];
|
||||||
|
extern int column;
|
||||||
|
//錯誤時執行的方法
|
||||||
|
void yyerror(char *s)
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
printf("\n%*s\n%*s\n", column, "^", column, s); //輸出錯誤訊息
|
||||||
|
printf("***********ERROR OCCOUR*************\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
yyparse(); //開始檢查文法動作
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* source: https://www.lysator.liu.se/c/ANSI-C-grammar-l.html */
|
||||||
|
|
||||||
|
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 "lysator.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{D}+{IS}? { count(); return(CONSTANT); }
|
||||||
|
{D}+{IS}? { count(); return(CONSTANT); }
|
||||||
|
L?'(\\.|[^\\'])+' { count(); return(CONSTANT); }
|
||||||
|
|
||||||
|
{D}+{E}{FS}? { count(); return(CONSTANT); }
|
||||||
|
{D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); }
|
||||||
|
{D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); }
|
||||||
|
|
||||||
|
L?\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
|
||||||
|
|
||||||
|
"..." { count(); return(ELLIPSIS); }
|
||||||
|
">>=" { 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,435 @@
|
||||||
|
/* source: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html */
|
||||||
|
|
||||||
|
%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 ELLIPSIS
|
||||||
|
|
||||||
|
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
||||||
|
|
||||||
|
%start translation_unit
|
||||||
|
%%
|
||||||
|
|
||||||
|
primary_expression
|
||||||
|
: IDENTIFIER
|
||||||
|
| CONSTANT
|
||||||
|
| STRING_LITERAL
|
||||||
|
| '(' expression ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
postfix_expression
|
||||||
|
: primary_expression
|
||||||
|
| postfix_expression '[' expression ']'
|
||||||
|
| postfix_expression '(' ')'
|
||||||
|
| postfix_expression '(' argument_expression_list ')'
|
||||||
|
| postfix_expression '.' IDENTIFIER
|
||||||
|
| postfix_expression PTR_OP IDENTIFIER
|
||||||
|
| postfix_expression INC_OP
|
||||||
|
| postfix_expression DEC_OP
|
||||||
|
;
|
||||||
|
|
||||||
|
argument_expression_list
|
||||||
|
: assignment_expression
|
||||||
|
| argument_expression_list ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_expression
|
||||||
|
: postfix_expression
|
||||||
|
| INC_OP unary_expression
|
||||||
|
| DEC_OP unary_expression
|
||||||
|
| unary_operator cast_expression
|
||||||
|
| SIZEOF unary_expression
|
||||||
|
| SIZEOF '(' type_name ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_operator
|
||||||
|
: '&'
|
||||||
|
| '*'
|
||||||
|
| '+'
|
||||||
|
| '-'
|
||||||
|
| '~'
|
||||||
|
| '!'
|
||||||
|
;
|
||||||
|
|
||||||
|
cast_expression
|
||||||
|
: unary_expression
|
||||||
|
| '(' type_name ')' cast_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
multiplicative_expression
|
||||||
|
: cast_expression
|
||||||
|
| multiplicative_expression '*' cast_expression
|
||||||
|
| multiplicative_expression '/' cast_expression
|
||||||
|
| multiplicative_expression '%' cast_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
additive_expression
|
||||||
|
: multiplicative_expression
|
||||||
|
| additive_expression '+' multiplicative_expression
|
||||||
|
| additive_expression '-' multiplicative_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
shift_expression
|
||||||
|
: additive_expression
|
||||||
|
| shift_expression LEFT_OP additive_expression
|
||||||
|
| shift_expression RIGHT_OP additive_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
relational_expression
|
||||||
|
: shift_expression
|
||||||
|
| relational_expression '<' shift_expression
|
||||||
|
| relational_expression '>' shift_expression
|
||||||
|
| relational_expression LE_OP shift_expression
|
||||||
|
| relational_expression GE_OP shift_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
equality_expression
|
||||||
|
: relational_expression
|
||||||
|
| equality_expression EQ_OP relational_expression
|
||||||
|
| equality_expression NE_OP relational_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
and_expression
|
||||||
|
: equality_expression
|
||||||
|
| and_expression '&' equality_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
exclusive_or_expression
|
||||||
|
: and_expression
|
||||||
|
| exclusive_or_expression '^' and_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
inclusive_or_expression
|
||||||
|
: exclusive_or_expression
|
||||||
|
| inclusive_or_expression '|' exclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_and_expression
|
||||||
|
: inclusive_or_expression
|
||||||
|
| logical_and_expression AND_OP inclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_or_expression
|
||||||
|
: logical_and_expression
|
||||||
|
| logical_or_expression OR_OP logical_and_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
conditional_expression
|
||||||
|
: logical_or_expression
|
||||||
|
| logical_or_expression '?' expression ':' conditional_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
assignment_expression
|
||||||
|
: conditional_expression
|
||||||
|
| unary_expression assignment_operator assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
assignment_operator
|
||||||
|
: '='
|
||||||
|
| MUL_ASSIGN
|
||||||
|
| DIV_ASSIGN
|
||||||
|
| MOD_ASSIGN
|
||||||
|
| ADD_ASSIGN
|
||||||
|
| SUB_ASSIGN
|
||||||
|
| LEFT_ASSIGN
|
||||||
|
| RIGHT_ASSIGN
|
||||||
|
| AND_ASSIGN
|
||||||
|
| XOR_ASSIGN
|
||||||
|
| OR_ASSIGN
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: assignment_expression
|
||||||
|
| expression ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
constant_expression
|
||||||
|
: conditional_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration
|
||||||
|
: declaration_specifiers ';'
|
||||||
|
| declaration_specifiers init_declarator_list ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration_specifiers
|
||||||
|
: storage_class_specifier
|
||||||
|
| storage_class_specifier declaration_specifiers
|
||||||
|
| type_specifier
|
||||||
|
| type_specifier declaration_specifiers
|
||||||
|
| type_qualifier
|
||||||
|
| type_qualifier 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
|
||||||
|
: VOID
|
||||||
|
| CHAR
|
||||||
|
| SHORT
|
||||||
|
| INT
|
||||||
|
| LONG
|
||||||
|
| FLOAT
|
||||||
|
| DOUBLE
|
||||||
|
| SIGNED
|
||||||
|
| UNSIGNED
|
||||||
|
| 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
|
||||||
|
: specifier_qualifier_list struct_declarator_list ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
specifier_qualifier_list
|
||||||
|
: type_specifier specifier_qualifier_list
|
||||||
|
| type_specifier
|
||||||
|
| type_qualifier specifier_qualifier_list
|
||||||
|
| type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator_list
|
||||||
|
: struct_declarator
|
||||||
|
| struct_declarator_list ',' struct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator
|
||||||
|
: declarator
|
||||||
|
| ':' constant_expression
|
||||||
|
| declarator ':' constant_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_specifier
|
||||||
|
: ENUM '{' enumerator_list '}'
|
||||||
|
| ENUM IDENTIFIER '{' enumerator_list '}'
|
||||||
|
| ENUM IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator_list
|
||||||
|
: enumerator
|
||||||
|
| enumerator_list ',' enumerator
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator
|
||||||
|
: IDENTIFIER
|
||||||
|
| IDENTIFIER '=' constant_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier
|
||||||
|
: CONST
|
||||||
|
| VOLATILE
|
||||||
|
;
|
||||||
|
|
||||||
|
declarator
|
||||||
|
: pointer direct_declarator
|
||||||
|
| direct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_declarator
|
||||||
|
: IDENTIFIER
|
||||||
|
| '(' declarator ')'
|
||||||
|
| direct_declarator '[' constant_expression ']'
|
||||||
|
| direct_declarator '[' ']'
|
||||||
|
| direct_declarator '(' parameter_type_list ')'
|
||||||
|
| direct_declarator '(' identifier_list ')'
|
||||||
|
| direct_declarator '(' ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
pointer
|
||||||
|
: '*'
|
||||||
|
| '*' type_qualifier_list
|
||||||
|
| '*' pointer
|
||||||
|
| '*' type_qualifier_list pointer
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier_list
|
||||||
|
: type_qualifier
|
||||||
|
| type_qualifier_list type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
parameter_type_list
|
||||||
|
: parameter_list
|
||||||
|
| parameter_list ',' ELLIPSIS
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_list
|
||||||
|
: parameter_declaration
|
||||||
|
| parameter_list ',' parameter_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_declaration
|
||||||
|
: declaration_specifiers declarator
|
||||||
|
| declaration_specifiers abstract_declarator
|
||||||
|
| declaration_specifiers
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier_list
|
||||||
|
: IDENTIFIER
|
||||||
|
| identifier_list ',' IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
type_name
|
||||||
|
: specifier_qualifier_list
|
||||||
|
| specifier_qualifier_list abstract_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
abstract_declarator
|
||||||
|
: pointer
|
||||||
|
| direct_abstract_declarator
|
||||||
|
| pointer direct_abstract_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_abstract_declarator
|
||||||
|
: '(' abstract_declarator ')'
|
||||||
|
| '[' ']'
|
||||||
|
| '[' constant_expression ']'
|
||||||
|
| direct_abstract_declarator '[' ']'
|
||||||
|
| direct_abstract_declarator '[' constant_expression ']'
|
||||||
|
| '(' ')'
|
||||||
|
| '(' parameter_type_list ')'
|
||||||
|
| direct_abstract_declarator '(' ')'
|
||||||
|
| direct_abstract_declarator '(' parameter_type_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
initializer
|
||||||
|
: assignment_expression
|
||||||
|
| '{' 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_expression ':' 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
|
||||||
|
: ';'
|
||||||
|
| expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
selection_statement
|
||||||
|
: IF '(' expression ')' statement
|
||||||
|
| IF '(' expression ')' statement ELSE statement
|
||||||
|
| SWITCH '(' expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
iteration_statement
|
||||||
|
: WHILE '(' expression ')' statement
|
||||||
|
| DO statement WHILE '(' expression ')' ';'
|
||||||
|
| FOR '(' expression_statement expression_statement ')' statement
|
||||||
|
| FOR '(' expression_statement expression_statement expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
jump_statement
|
||||||
|
: GOTO IDENTIFIER ';'
|
||||||
|
| CONTINUE ';'
|
||||||
|
| BREAK ';'
|
||||||
|
| RETURN ';'
|
||||||
|
| RETURN expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
translation_unit
|
||||||
|
: external_declaration
|
||||||
|
| translation_unit external_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
external_declaration
|
||||||
|
: function_definition
|
||||||
|
| declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
function_definition
|
||||||
|
: declaration_specifiers declarator declaration_list compound_statement
|
||||||
|
| declaration_specifiers declarator compound_statement
|
||||||
|
| declarator declaration_list compound_statement
|
||||||
|
| declarator compound_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern char yytext[];
|
||||||
|
extern int column;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return yyparse();
|
||||||
|
}
|
||||||
|
|
||||||
|
yyerror(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
printf("\n%*s\n%*s\n", column, "^", column, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
/* source: https://www.quut.com/c/ANSI-C-grammar-l-2011.html */
|
||||||
|
|
||||||
|
%e 1019
|
||||||
|
%p 2807
|
||||||
|
%n 371
|
||||||
|
%k 284
|
||||||
|
%a 1213
|
||||||
|
%o 1117
|
||||||
|
|
||||||
|
O [0-7]
|
||||||
|
D [0-9]
|
||||||
|
NZ [1-9]
|
||||||
|
L [a-zA-Z_]
|
||||||
|
A [a-zA-Z_0-9]
|
||||||
|
H [a-fA-F0-9]
|
||||||
|
HP (0[xX])
|
||||||
|
E ([Ee][+-]?{D}+)
|
||||||
|
P ([Pp][+-]?{D}+)
|
||||||
|
FS (f|F|l|L)
|
||||||
|
IS (((u|U)(l|L|ll|LL)?)|((l|L|ll|LL)(u|U)?))
|
||||||
|
CP (u|U|L)
|
||||||
|
SP (u8|u|U|L)
|
||||||
|
ES (\\(['"\?\\abfnrtv]|[0-7]{1,3}|x[a-fA-F0-9]+))
|
||||||
|
WS [ \t\v\n\f]
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ansi_c.tab.h"
|
||||||
|
|
||||||
|
extern void yyerror(const char *); /* prints grammar violation message */
|
||||||
|
|
||||||
|
extern int sym_type(const char *); /* returns type from symbol table */
|
||||||
|
|
||||||
|
#define sym_type(identifier) IDENTIFIER /* with no symbol table, fake it */
|
||||||
|
|
||||||
|
static void comment(void);
|
||||||
|
static int check_type(void);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
"/*" { comment(); }
|
||||||
|
"//".* { /* consume //-comment */ }
|
||||||
|
|
||||||
|
"auto" { return(AUTO); }
|
||||||
|
"break" { return(BREAK); }
|
||||||
|
"case" { return(CASE); }
|
||||||
|
"char" { return(CHAR); }
|
||||||
|
"const" { return(CONST); }
|
||||||
|
"continue" { return(CONTINUE); }
|
||||||
|
"default" { return(DEFAULT); }
|
||||||
|
"do" { return(DO); }
|
||||||
|
"double" { return(DOUBLE); }
|
||||||
|
"else" { return(ELSE); }
|
||||||
|
"enum" { return(ENUM); }
|
||||||
|
"extern" { return(EXTERN); }
|
||||||
|
"float" { return(FLOAT); }
|
||||||
|
"for" { return(FOR); }
|
||||||
|
"goto" { return(GOTO); }
|
||||||
|
"if" { return(IF); }
|
||||||
|
"inline" { return(INLINE); }
|
||||||
|
"int" { return(INT); }
|
||||||
|
"long" { return(LONG); }
|
||||||
|
"register" { return(REGISTER); }
|
||||||
|
"restrict" { return(RESTRICT); }
|
||||||
|
"return" { return(RETURN); }
|
||||||
|
"short" { return(SHORT); }
|
||||||
|
"signed" { return(SIGNED); }
|
||||||
|
"sizeof" { return(SIZEOF); }
|
||||||
|
"static" { return(STATIC); }
|
||||||
|
"struct" { return(STRUCT); }
|
||||||
|
"switch" { return(SWITCH); }
|
||||||
|
"typedef" { return(TYPEDEF); }
|
||||||
|
"union" { return(UNION); }
|
||||||
|
"unsigned" { return(UNSIGNED); }
|
||||||
|
"void" { return(VOID); }
|
||||||
|
"volatile" { return(VOLATILE); }
|
||||||
|
"while" { return(WHILE); }
|
||||||
|
"_Alignas" { return ALIGNAS; }
|
||||||
|
"_Alignof" { return ALIGNOF; }
|
||||||
|
"_Atomic" { return ATOMIC; }
|
||||||
|
"_Bool" { return BOOL; }
|
||||||
|
"_Complex" { return COMPLEX; }
|
||||||
|
"_Generic" { return GENERIC; }
|
||||||
|
"_Imaginary" { return IMAGINARY; }
|
||||||
|
"_Noreturn" { return NORETURN; }
|
||||||
|
"_Static_assert" { return STATIC_ASSERT; }
|
||||||
|
"_Thread_local" { return THREAD_LOCAL; }
|
||||||
|
"__func__" { return FUNC_NAME; }
|
||||||
|
|
||||||
|
{L}{A}* { return check_type(); }
|
||||||
|
|
||||||
|
{HP}{H}+{IS}? { return I_CONSTANT; }
|
||||||
|
{NZ}{D}*{IS}? { return I_CONSTANT; }
|
||||||
|
"0"{O}*{IS}? { return I_CONSTANT; }
|
||||||
|
{CP}?"'"([^'\\\n]|{ES})+"'" { return I_CONSTANT; }
|
||||||
|
|
||||||
|
{D}+{E}{FS}? { return F_CONSTANT; }
|
||||||
|
{D}*"."{D}+{E}?{FS}? { return F_CONSTANT; }
|
||||||
|
{D}+"."{E}?{FS}? { return F_CONSTANT; }
|
||||||
|
{HP}{H}+{P}{FS}? { return F_CONSTANT; }
|
||||||
|
{HP}{H}*"."{H}+{P}{FS}? { return F_CONSTANT; }
|
||||||
|
{HP}{H}+"."{P}{FS}? { return F_CONSTANT; }
|
||||||
|
|
||||||
|
({SP}?\"([^"\\\n]|{ES})*\"{WS}*)+ { return STRING_LITERAL; }
|
||||||
|
|
||||||
|
"..." { return ELLIPSIS; }
|
||||||
|
">>=" { return RIGHT_ASSIGN; }
|
||||||
|
"<<=" { return LEFT_ASSIGN; }
|
||||||
|
"+=" { return ADD_ASSIGN; }
|
||||||
|
"-=" { return SUB_ASSIGN; }
|
||||||
|
"*=" { return MUL_ASSIGN; }
|
||||||
|
"/=" { return DIV_ASSIGN; }
|
||||||
|
"%=" { return MOD_ASSIGN; }
|
||||||
|
"&=" { return AND_ASSIGN; }
|
||||||
|
"^=" { return XOR_ASSIGN; }
|
||||||
|
"|=" { return OR_ASSIGN; }
|
||||||
|
">>" { return RIGHT_OP; }
|
||||||
|
"<<" { return LEFT_OP; }
|
||||||
|
"++" { return INC_OP; }
|
||||||
|
"--" { return DEC_OP; }
|
||||||
|
"->" { return PTR_OP; }
|
||||||
|
"&&" { return AND_OP; }
|
||||||
|
"||" { return OR_OP; }
|
||||||
|
"<=" { return LE_OP; }
|
||||||
|
">=" { return GE_OP; }
|
||||||
|
"==" { return EQ_OP; }
|
||||||
|
"!=" { return NE_OP; }
|
||||||
|
";" { return ';'; }
|
||||||
|
("{"|"<%") { return '{'; }
|
||||||
|
("}"|"%>") { return '}'; }
|
||||||
|
"," { return ','; }
|
||||||
|
":" { return ':'; }
|
||||||
|
"=" { return '='; }
|
||||||
|
"(" { return '('; }
|
||||||
|
")" { return ')'; }
|
||||||
|
("["|"<:") { return '['; }
|
||||||
|
("]"|":>") { return ']'; }
|
||||||
|
"." { return '.'; }
|
||||||
|
"&" { return '&'; }
|
||||||
|
"!" { return '!'; }
|
||||||
|
"~" { return '~'; }
|
||||||
|
"-" { return '-'; }
|
||||||
|
"+" { return '+'; }
|
||||||
|
"*" { return '*'; }
|
||||||
|
"/" { return '/'; }
|
||||||
|
"%" { return '%'; }
|
||||||
|
"<" { return '<'; }
|
||||||
|
">" { return '>'; }
|
||||||
|
"^" { return '^'; }
|
||||||
|
"|" { return '|'; }
|
||||||
|
"?" { return '?'; }
|
||||||
|
|
||||||
|
{WS}+ { /* whitespace separates tokens */ }
|
||||||
|
. { /* discard bad characters */ }
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yywrap(void) /* called at end of input */
|
||||||
|
{
|
||||||
|
return 1; /* terminate now */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void comment(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = input()) != 0)
|
||||||
|
if (c == '*')
|
||||||
|
{
|
||||||
|
while ((c = input()) == '*')
|
||||||
|
;
|
||||||
|
|
||||||
|
if (c == '/')
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yyerror("unterminated comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_type(void)
|
||||||
|
{
|
||||||
|
switch (sym_type(yytext))
|
||||||
|
{
|
||||||
|
case TYPEDEF_NAME: /* previously defined */
|
||||||
|
return TYPEDEF_NAME;
|
||||||
|
case ENUMERATION_CONSTANT: /* previously defined */
|
||||||
|
return ENUMERATION_CONSTANT;
|
||||||
|
default: /* includes undefined */
|
||||||
|
return IDENTIFIER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,541 @@
|
||||||
|
/* source: https://www.quut.com/c/ANSI-C-grammar-y-2011.html */
|
||||||
|
|
||||||
|
%token IDENTIFIER I_CONSTANT F_CONSTANT STRING_LITERAL FUNC_NAME 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
|
||||||
|
%token TYPEDEF_NAME ENUMERATION_CONSTANT
|
||||||
|
|
||||||
|
%token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE
|
||||||
|
%token CONST RESTRICT VOLATILE
|
||||||
|
%token BOOL CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE VOID
|
||||||
|
%token COMPLEX IMAGINARY
|
||||||
|
%token STRUCT UNION ENUM ELLIPSIS
|
||||||
|
|
||||||
|
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
|
||||||
|
|
||||||
|
%token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATIC_ASSERT THREAD_LOCAL
|
||||||
|
|
||||||
|
%start translation_unit
|
||||||
|
%%
|
||||||
|
|
||||||
|
primary_expression
|
||||||
|
: IDENTIFIER
|
||||||
|
| constant
|
||||||
|
| string
|
||||||
|
| '(' expression ')'
|
||||||
|
| generic_selection
|
||||||
|
;
|
||||||
|
|
||||||
|
constant
|
||||||
|
: I_CONSTANT /* includes character_constant */
|
||||||
|
| F_CONSTANT
|
||||||
|
| ENUMERATION_CONSTANT /* after it has been defined as such */
|
||||||
|
;
|
||||||
|
|
||||||
|
enumeration_constant /* before it has been defined as such */
|
||||||
|
: IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
string
|
||||||
|
: STRING_LITERAL
|
||||||
|
| FUNC_NAME
|
||||||
|
;
|
||||||
|
|
||||||
|
generic_selection
|
||||||
|
: GENERIC '(' assignment_expression ',' generic_assoc_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
generic_assoc_list
|
||||||
|
: generic_association
|
||||||
|
| generic_assoc_list ',' generic_association
|
||||||
|
;
|
||||||
|
|
||||||
|
generic_association
|
||||||
|
: type_name ':' assignment_expression
|
||||||
|
| DEFAULT ':' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
postfix_expression
|
||||||
|
: primary_expression
|
||||||
|
| postfix_expression '[' expression ']'
|
||||||
|
| postfix_expression '(' ')'
|
||||||
|
| postfix_expression '(' argument_expression_list ')'
|
||||||
|
| postfix_expression '.' IDENTIFIER
|
||||||
|
| postfix_expression PTR_OP IDENTIFIER
|
||||||
|
| postfix_expression INC_OP
|
||||||
|
| postfix_expression DEC_OP
|
||||||
|
| '(' type_name ')' '{' initializer_list '}'
|
||||||
|
| '(' type_name ')' '{' initializer_list ',' '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
argument_expression_list
|
||||||
|
: assignment_expression
|
||||||
|
| argument_expression_list ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_expression
|
||||||
|
: postfix_expression
|
||||||
|
| INC_OP unary_expression
|
||||||
|
| DEC_OP unary_expression
|
||||||
|
| unary_operator cast_expression
|
||||||
|
| SIZEOF unary_expression
|
||||||
|
| SIZEOF '(' type_name ')'
|
||||||
|
| ALIGNOF '(' type_name ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_operator
|
||||||
|
: '&'
|
||||||
|
| '*'
|
||||||
|
| '+'
|
||||||
|
| '-'
|
||||||
|
| '~'
|
||||||
|
| '!'
|
||||||
|
;
|
||||||
|
|
||||||
|
cast_expression
|
||||||
|
: unary_expression
|
||||||
|
| '(' type_name ')' cast_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
multiplicative_expression
|
||||||
|
: cast_expression
|
||||||
|
| multiplicative_expression '*' cast_expression
|
||||||
|
| multiplicative_expression '/' cast_expression
|
||||||
|
| multiplicative_expression '%' cast_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
additive_expression
|
||||||
|
: multiplicative_expression
|
||||||
|
| additive_expression '+' multiplicative_expression
|
||||||
|
| additive_expression '-' multiplicative_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
shift_expression
|
||||||
|
: additive_expression
|
||||||
|
| shift_expression LEFT_OP additive_expression
|
||||||
|
| shift_expression RIGHT_OP additive_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
relational_expression
|
||||||
|
: shift_expression
|
||||||
|
| relational_expression '<' shift_expression
|
||||||
|
| relational_expression '>' shift_expression
|
||||||
|
| relational_expression LE_OP shift_expression
|
||||||
|
| relational_expression GE_OP shift_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
equality_expression
|
||||||
|
: relational_expression
|
||||||
|
| equality_expression EQ_OP relational_expression
|
||||||
|
| equality_expression NE_OP relational_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
and_expression
|
||||||
|
: equality_expression
|
||||||
|
| and_expression '&' equality_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
exclusive_or_expression
|
||||||
|
: and_expression
|
||||||
|
| exclusive_or_expression '^' and_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
inclusive_or_expression
|
||||||
|
: exclusive_or_expression
|
||||||
|
| inclusive_or_expression '|' exclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_and_expression
|
||||||
|
: inclusive_or_expression
|
||||||
|
| logical_and_expression AND_OP inclusive_or_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
logical_or_expression
|
||||||
|
: logical_and_expression
|
||||||
|
| logical_or_expression OR_OP logical_and_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
conditional_expression
|
||||||
|
: logical_or_expression
|
||||||
|
| logical_or_expression '?' expression ':' conditional_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
assignment_expression
|
||||||
|
: conditional_expression
|
||||||
|
| unary_expression assignment_operator assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
assignment_operator
|
||||||
|
: '='
|
||||||
|
| MUL_ASSIGN
|
||||||
|
| DIV_ASSIGN
|
||||||
|
| MOD_ASSIGN
|
||||||
|
| ADD_ASSIGN
|
||||||
|
| SUB_ASSIGN
|
||||||
|
| LEFT_ASSIGN
|
||||||
|
| RIGHT_ASSIGN
|
||||||
|
| AND_ASSIGN
|
||||||
|
| XOR_ASSIGN
|
||||||
|
| OR_ASSIGN
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: assignment_expression
|
||||||
|
| expression ',' assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
constant_expression
|
||||||
|
: conditional_expression /* with constraints */
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration
|
||||||
|
: declaration_specifiers ';'
|
||||||
|
| declaration_specifiers init_declarator_list ';'
|
||||||
|
| static_assert_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration_specifiers
|
||||||
|
: storage_class_specifier declaration_specifiers
|
||||||
|
| storage_class_specifier
|
||||||
|
| type_specifier declaration_specifiers
|
||||||
|
| type_specifier
|
||||||
|
| type_qualifier declaration_specifiers
|
||||||
|
| type_qualifier
|
||||||
|
| function_specifier declaration_specifiers
|
||||||
|
| function_specifier
|
||||||
|
| alignment_specifier declaration_specifiers
|
||||||
|
| alignment_specifier
|
||||||
|
;
|
||||||
|
|
||||||
|
init_declarator_list
|
||||||
|
: init_declarator
|
||||||
|
| init_declarator_list ',' init_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
init_declarator
|
||||||
|
: declarator '=' initializer
|
||||||
|
| declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
storage_class_specifier
|
||||||
|
: TYPEDEF /* identifiers must be flagged as TYPEDEF_NAME */
|
||||||
|
| EXTERN
|
||||||
|
| STATIC
|
||||||
|
| THREAD_LOCAL
|
||||||
|
| AUTO
|
||||||
|
| REGISTER
|
||||||
|
;
|
||||||
|
|
||||||
|
type_specifier
|
||||||
|
: VOID
|
||||||
|
| CHAR
|
||||||
|
| SHORT
|
||||||
|
| INT
|
||||||
|
| LONG
|
||||||
|
| FLOAT
|
||||||
|
| DOUBLE
|
||||||
|
| SIGNED
|
||||||
|
| UNSIGNED
|
||||||
|
| BOOL
|
||||||
|
| COMPLEX
|
||||||
|
| IMAGINARY /* non-mandated extension */
|
||||||
|
| atomic_type_specifier
|
||||||
|
| struct_or_union_specifier
|
||||||
|
| enum_specifier
|
||||||
|
| TYPEDEF_NAME /* after it has been defined as such */
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_or_union_specifier
|
||||||
|
: struct_or_union '{' struct_declaration_list '}'
|
||||||
|
| struct_or_union IDENTIFIER '{' struct_declaration_list '}'
|
||||||
|
| struct_or_union IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_or_union
|
||||||
|
: STRUCT
|
||||||
|
| UNION
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declaration_list
|
||||||
|
: struct_declaration
|
||||||
|
| struct_declaration_list struct_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declaration
|
||||||
|
: specifier_qualifier_list ';' /* for anonymous struct/union */
|
||||||
|
| specifier_qualifier_list struct_declarator_list ';'
|
||||||
|
| static_assert_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
specifier_qualifier_list
|
||||||
|
: type_specifier specifier_qualifier_list
|
||||||
|
| type_specifier
|
||||||
|
| type_qualifier specifier_qualifier_list
|
||||||
|
| type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator_list
|
||||||
|
: struct_declarator
|
||||||
|
| struct_declarator_list ',' struct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_declarator
|
||||||
|
: ':' constant_expression
|
||||||
|
| declarator ':' constant_expression
|
||||||
|
| declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_specifier
|
||||||
|
: ENUM '{' enumerator_list '}'
|
||||||
|
| ENUM '{' enumerator_list ',' '}'
|
||||||
|
| ENUM IDENTIFIER '{' enumerator_list '}'
|
||||||
|
| ENUM IDENTIFIER '{' enumerator_list ',' '}'
|
||||||
|
| ENUM IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator_list
|
||||||
|
: enumerator
|
||||||
|
| enumerator_list ',' enumerator
|
||||||
|
;
|
||||||
|
|
||||||
|
enumerator /* identifiers must be flagged as ENUMERATION_CONSTANT */
|
||||||
|
: enumeration_constant '=' constant_expression
|
||||||
|
| enumeration_constant
|
||||||
|
;
|
||||||
|
|
||||||
|
atomic_type_specifier
|
||||||
|
: ATOMIC '(' type_name ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier
|
||||||
|
: CONST
|
||||||
|
| RESTRICT
|
||||||
|
| VOLATILE
|
||||||
|
| ATOMIC
|
||||||
|
;
|
||||||
|
|
||||||
|
function_specifier
|
||||||
|
: INLINE
|
||||||
|
| NORETURN
|
||||||
|
;
|
||||||
|
|
||||||
|
alignment_specifier
|
||||||
|
: ALIGNAS '(' type_name ')'
|
||||||
|
| ALIGNAS '(' constant_expression ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
declarator
|
||||||
|
: pointer direct_declarator
|
||||||
|
| direct_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_declarator
|
||||||
|
: IDENTIFIER
|
||||||
|
| '(' declarator ')'
|
||||||
|
| direct_declarator '[' ']'
|
||||||
|
| direct_declarator '[' '*' ']'
|
||||||
|
| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
|
||||||
|
| direct_declarator '[' STATIC assignment_expression ']'
|
||||||
|
| direct_declarator '[' type_qualifier_list '*' ']'
|
||||||
|
| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
|
||||||
|
| direct_declarator '[' type_qualifier_list assignment_expression ']'
|
||||||
|
| direct_declarator '[' type_qualifier_list ']'
|
||||||
|
| direct_declarator '[' assignment_expression ']'
|
||||||
|
| direct_declarator '(' parameter_type_list ')'
|
||||||
|
| direct_declarator '(' ')'
|
||||||
|
| direct_declarator '(' identifier_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
pointer
|
||||||
|
: '*' type_qualifier_list pointer
|
||||||
|
| '*' type_qualifier_list
|
||||||
|
| '*' pointer
|
||||||
|
| '*'
|
||||||
|
;
|
||||||
|
|
||||||
|
type_qualifier_list
|
||||||
|
: type_qualifier
|
||||||
|
| type_qualifier_list type_qualifier
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
parameter_type_list
|
||||||
|
: parameter_list ',' ELLIPSIS
|
||||||
|
| parameter_list
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_list
|
||||||
|
: parameter_declaration
|
||||||
|
| parameter_list ',' parameter_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_declaration
|
||||||
|
: declaration_specifiers declarator
|
||||||
|
| declaration_specifiers abstract_declarator
|
||||||
|
| declaration_specifiers
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier_list
|
||||||
|
: IDENTIFIER
|
||||||
|
| identifier_list ',' IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
type_name
|
||||||
|
: specifier_qualifier_list abstract_declarator
|
||||||
|
| specifier_qualifier_list
|
||||||
|
;
|
||||||
|
|
||||||
|
abstract_declarator
|
||||||
|
: pointer direct_abstract_declarator
|
||||||
|
| pointer
|
||||||
|
| direct_abstract_declarator
|
||||||
|
;
|
||||||
|
|
||||||
|
direct_abstract_declarator
|
||||||
|
: '(' abstract_declarator ')'
|
||||||
|
| '[' ']'
|
||||||
|
| '[' '*' ']'
|
||||||
|
| '[' STATIC type_qualifier_list assignment_expression ']'
|
||||||
|
| '[' STATIC assignment_expression ']'
|
||||||
|
| '[' type_qualifier_list STATIC assignment_expression ']'
|
||||||
|
| '[' type_qualifier_list assignment_expression ']'
|
||||||
|
| '[' type_qualifier_list ']'
|
||||||
|
| '[' assignment_expression ']'
|
||||||
|
| direct_abstract_declarator '[' ']'
|
||||||
|
| direct_abstract_declarator '[' '*' ']'
|
||||||
|
| direct_abstract_declarator '[' STATIC type_qualifier_list assignment_expression ']'
|
||||||
|
| direct_abstract_declarator '[' STATIC assignment_expression ']'
|
||||||
|
| direct_abstract_declarator '[' type_qualifier_list assignment_expression ']'
|
||||||
|
| direct_abstract_declarator '[' type_qualifier_list STATIC assignment_expression ']'
|
||||||
|
| direct_abstract_declarator '[' type_qualifier_list ']'
|
||||||
|
| direct_abstract_declarator '[' assignment_expression ']'
|
||||||
|
| '(' ')'
|
||||||
|
| '(' parameter_type_list ')'
|
||||||
|
| direct_abstract_declarator '(' ')'
|
||||||
|
| direct_abstract_declarator '(' parameter_type_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
initializer
|
||||||
|
: '{' initializer_list '}'
|
||||||
|
| '{' initializer_list ',' '}'
|
||||||
|
| assignment_expression
|
||||||
|
;
|
||||||
|
|
||||||
|
initializer_list
|
||||||
|
: designation initializer
|
||||||
|
| initializer
|
||||||
|
| initializer_list ',' designation initializer
|
||||||
|
| initializer_list ',' initializer
|
||||||
|
;
|
||||||
|
|
||||||
|
designation
|
||||||
|
: designator_list '='
|
||||||
|
;
|
||||||
|
|
||||||
|
designator_list
|
||||||
|
: designator
|
||||||
|
| designator_list designator
|
||||||
|
;
|
||||||
|
|
||||||
|
designator
|
||||||
|
: '[' constant_expression ']'
|
||||||
|
| '.' IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
static_assert_declaration
|
||||||
|
: STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
statement
|
||||||
|
: labeled_statement
|
||||||
|
| compound_statement
|
||||||
|
| expression_statement
|
||||||
|
| selection_statement
|
||||||
|
| iteration_statement
|
||||||
|
| jump_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
labeled_statement
|
||||||
|
: IDENTIFIER ':' statement
|
||||||
|
| CASE constant_expression ':' statement
|
||||||
|
| DEFAULT ':' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
compound_statement
|
||||||
|
: '{' '}'
|
||||||
|
| '{' block_item_list '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
block_item_list
|
||||||
|
: block_item
|
||||||
|
| block_item_list block_item
|
||||||
|
;
|
||||||
|
|
||||||
|
block_item
|
||||||
|
: declaration
|
||||||
|
| statement
|
||||||
|
;
|
||||||
|
|
||||||
|
expression_statement
|
||||||
|
: ';'
|
||||||
|
| expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
selection_statement
|
||||||
|
: IF '(' expression ')' statement ELSE statement
|
||||||
|
| IF '(' expression ')' statement
|
||||||
|
| SWITCH '(' expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
iteration_statement
|
||||||
|
: WHILE '(' expression ')' statement
|
||||||
|
| DO statement WHILE '(' expression ')' ';'
|
||||||
|
| FOR '(' expression_statement expression_statement ')' statement
|
||||||
|
| FOR '(' expression_statement expression_statement expression ')' statement
|
||||||
|
| FOR '(' declaration expression_statement ')' statement
|
||||||
|
| FOR '(' declaration expression_statement expression ')' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
jump_statement
|
||||||
|
: GOTO IDENTIFIER ';'
|
||||||
|
| CONTINUE ';'
|
||||||
|
| BREAK ';'
|
||||||
|
| RETURN ';'
|
||||||
|
| RETURN expression ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
translation_unit
|
||||||
|
: external_declaration
|
||||||
|
| translation_unit external_declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
external_declaration
|
||||||
|
: function_definition
|
||||||
|
| declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
function_definition
|
||||||
|
: declaration_specifiers declarator declaration_list compound_statement
|
||||||
|
| declaration_specifiers declarator compound_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration_list
|
||||||
|
: declaration
|
||||||
|
| declaration_list declaration
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return yyparse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void yyerror(const char *s)
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr, "*** %s\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue