Created
June 14, 2012 23:49
-
Star
(142)
You must be signed in to star a gist -
Fork
(46)
You must be signed in to fork a gist
-
-
Save codebrainz/2933703 to your computer and use it in GitHub Desktop.
C99 Lex/Flex & YACC/Bison Grammars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
D [0-9] | |
L [a-zA-Z_] | |
H [a-fA-F0-9] | |
E ([Ee][+-]?{D}+) | |
P ([Pp][+-]?{D}+) | |
FS (f|F|l|L) | |
IS ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U)) | |
%{ | |
#include <stdio.h> | |
#include "y.tab.h" | |
void count(void); | |
%} | |
%% | |
"/*" { comment(); } | |
"//"[^\n]* { /* consume //-comment */ } | |
"auto" { count(); return(AUTO); } | |
"_Bool" { count(); return(BOOL); } | |
"break" { count(); return(BREAK); } | |
"case" { count(); return(CASE); } | |
"char" { count(); return(CHAR); } | |
"_Complex" { count(); return(COMPLEX); } | |
"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); } | |
"_Imaginary" { count(); return(IMAGINARY); } | |
"inline" { count(); return(INLINE); } | |
"int" { count(); return(INT); } | |
"long" { count(); return(LONG); } | |
"register" { count(); return(REGISTER); } | |
"restrict" { count(); return(RESTRICT); } | |
"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[0-7]*{IS}? { count(); return(CONSTANT); } | |
[1-9]{D}*{IS}? { count(); return(CONSTANT); } | |
L?'(\\.|[^\\'\n])+' { count(); return(CONSTANT); } | |
{D}+{E}{FS}? { count(); return(CONSTANT); } | |
{D}*"."{D}+{E}?{FS}? { count(); return(CONSTANT); } | |
{D}+"."{D}*{E}?{FS}? { count(); return(CONSTANT); } | |
0[xX]{H}+{P}{FS}? { count(); return(CONSTANT); } | |
0[xX]{H}*"."{H}+{P}?{FS}? { count(); return(CONSTANT); } | |
0[xX]{H}+"."{H}*{P}?{FS}? { count(); return(CONSTANT); } | |
L?\"(\\.|[^\\"\n])*\" { 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(); } | |
. { /* Add code to complain about unmatched characters */ } | |
%% | |
int yywrap(void) | |
{ | |
return 1; | |
} | |
void comment(void) | |
{ | |
char c, prev = 0; | |
while ((c = input()) != 0) /* (EOF maps to 0) */ | |
{ | |
if (c == '/' && prev == '*') | |
return; | |
prev = c; | |
} | |
error("unterminated comment"); | |
} | |
int column = 0; | |
void count(void) | |
{ | |
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(void) | |
{ | |
/* | |
* 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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%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 INLINE RESTRICT | |
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID | |
%token BOOL COMPLEX IMAGINARY | |
%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 | |
| '(' 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 ')' | |
; | |
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 | |
| function_specifier | |
| function_specifier declaration_specifiers | |
; | |
init_declarator_list | |
: init_declarator | |
| init_declarator_list ',' init_declarator | |
; | |
init_declarator | |
: declarator | |
| declarator '=' initializer | |
; | |
storage_class_specifier | |
: TYPEDEF | |
| EXTERN | |
| STATIC | |
| AUTO | |
| REGISTER | |
; | |
type_specifier | |
: VOID | |
| CHAR | |
| SHORT | |
| INT | |
| LONG | |
| FLOAT | |
| DOUBLE | |
| SIGNED | |
| UNSIGNED | |
| BOOL | |
| COMPLEX | |
| IMAGINARY | |
| 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 '{' enumerator_list ',' '}' | |
| ENUM IDENTIFIER '{' enumerator_list ',' '}' | |
| ENUM IDENTIFIER | |
; | |
enumerator_list | |
: enumerator | |
| enumerator_list ',' enumerator | |
; | |
enumerator | |
: IDENTIFIER | |
| IDENTIFIER '=' constant_expression | |
; | |
type_qualifier | |
: CONST | |
| RESTRICT | |
| VOLATILE | |
; | |
function_specifier | |
: INLINE | |
; | |
declarator | |
: pointer direct_declarator | |
| direct_declarator | |
; | |
direct_declarator | |
: IDENTIFIER | |
| '(' declarator ')' | |
| direct_declarator '[' type_qualifier_list assignment_expression ']' | |
| direct_declarator '[' type_qualifier_list ']' | |
| direct_declarator '[' assignment_expression ']' | |
| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']' | |
| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']' | |
| direct_declarator '[' type_qualifier_list '*' ']' | |
| direct_declarator '[' '*' ']' | |
| 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 ')' | |
| '[' ']' | |
| '[' assignment_expression ']' | |
| direct_abstract_declarator '[' ']' | |
| direct_abstract_declarator '[' assignment_expression ']' | |
| '[' '*' ']' | |
| direct_abstract_declarator '[' '*' ']' | |
| '(' ')' | |
| '(' parameter_type_list ')' | |
| direct_abstract_declarator '(' ')' | |
| direct_abstract_declarator '(' parameter_type_list ')' | |
; | |
initializer | |
: assignment_expression | |
| '{' initializer_list '}' | |
| '{' initializer_list ',' '}' | |
; | |
initializer_list | |
: initializer | |
| designation initializer | |
| initializer_list ',' initializer | |
| initializer_list ',' designation initializer | |
; | |
designation | |
: designator_list '=' | |
; | |
designator_list | |
: designator | |
| designator_list designator | |
; | |
designator | |
: '[' constant_expression ']' | |
| '.' IDENTIFIER | |
; | |
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 | |
| 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 | |
| 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> | |
extern char yytext[]; | |
extern int column; | |
void yyerror(char const *s) | |
{ | |
fflush(stdout); | |
printf("\n%*s\n%*s\n", column, "^", column, s); | |
} |
it cannot handle string literals in multiple quotes, like this: "multiple""quote""string""literal""
Your example case is too easy. I think about this case:
char const *m = "Thi" "s should wo"
"rk" " t"
"oo";
I fixed it by using ([LUu]?\"(\\.|[^\\\"\n])*\"[ \f\v\t\r\n]*)*
Then you have to parse the string with a state machine, but you already needed to do that to implement \x61
and \n
, \r
, \t
, etc. This just adds one more bit of state - whether you are in a double-quote or not. Just enforce that the input is only whitespace when not inside a doublequote, and only emit to the resulting string buffer when inside a double-quote. Flex should only give you valid input with my regex fix.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@AngheloAlf
It is the C99 syntax for a VLA in a function prototype.