From fedaac132d9a8255ef8bb38acad0db900b5e0bcc Mon Sep 17 00:00:00 2001 From: Ian Griffin Date: Sun, 28 May 2023 15:13:07 +0800 Subject: [PATCH] initial commit --- .gitignore | 0 Makefile | 21 ++ grammars/examp.l | 173 +++++++++++++++ grammars/examp.y | 435 ++++++++++++++++++++++++++++++++++++ grammars/lysator.l | 178 +++++++++++++++ grammars/lysator.y | 435 ++++++++++++++++++++++++++++++++++++ grammars/quut.l | 194 ++++++++++++++++ grammars/quut.y | 541 +++++++++++++++++++++++++++++++++++++++++++++ hello.c | 3 + 9 files changed, 1980 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 grammars/examp.l create mode 100644 grammars/examp.y create mode 100644 grammars/lysator.l create mode 100644 grammars/lysator.y create mode 100644 grammars/quut.l create mode 100644 grammars/quut.y create mode 100644 hello.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a281e1 --- /dev/null +++ b/Makefile @@ -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 diff --git a/grammars/examp.l b/grammars/examp.l new file mode 100644 index 0000000..b5315a2 --- /dev/null +++ b/grammars/examp.l @@ -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 +#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; + +//計數器 +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); +} diff --git a/grammars/examp.y b/grammars/examp.y new file mode 100644 index 0000000..c869146 --- /dev/null +++ b/grammars/examp.y @@ -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 + +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; +} diff --git a/grammars/lysator.l b/grammars/lysator.l new file mode 100644 index 0000000..0cb9b8b --- /dev/null +++ b/grammars/lysator.l @@ -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 +#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); +} + diff --git a/grammars/lysator.y b/grammars/lysator.y new file mode 100644 index 0000000..b606bc3 --- /dev/null +++ b/grammars/lysator.y @@ -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 + +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); +} + diff --git a/grammars/quut.l b/grammars/quut.l new file mode 100644 index 0000000..11d602d --- /dev/null +++ b/grammars/quut.l @@ -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 +#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; + } +} + diff --git a/grammars/quut.y b/grammars/quut.y new file mode 100644 index 0000000..36e6e8e --- /dev/null +++ b/grammars/quut.y @@ -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 + +int main() { + return yyparse(); +} + +void yyerror(const char *s) +{ + fflush(stdout); + fprintf(stderr, "*** %s\n", s); +} + diff --git a/hello.c b/hello.c new file mode 100644 index 0000000..874f1b2 --- /dev/null +++ b/hello.c @@ -0,0 +1,3 @@ +void main() { + printf("hello, world\n"); +}