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