1. Lexer Specification File (`scanner.l`)
%{
#include "parser.tab.h" // Include header for token definitions
#include
#include
%}
%%
[ \t\n]+ ; // Ignore whitespace
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"return" { return RETURN; }
"for" { return FOR; }
"switch" { return SWITCH; }
"case" { return CASE; }
"default" { return DEFAULT; }
"break" { return BREAK; }
"continue" { return CONTINUE; }
"goto" { return GOTO; }
"sizeof" { return SIZEOF; }
"++" { return INCREMENT; }
"--" { return DECREMENT; }
[0-9]+ { yylval.num = atoi(yytext); return NUMBER; }
[a-zA-Z_][a-zA-Z0-9_]* { return IDENTIFIER; }
"\"[^\"]*\"" { yylval.str = strdup(yytext); return STRING_LITERAL; }
"\'[^\']\'" { return CHAR_LITERAL; }
"+"|"-"|"*"|"/" { return yytext[0]; }
"=" { return ASSIGN; }
"==" { return EQ; }
"!=" { return NEQ; }
"&" { return AND; }
"|" { return OR; }
"(" { return LPAREN; }
")" { return RPAREN; }
";" { return SEMICOLON; }
"{" { return LBRACE; }
"}" { return RBRACE; }
"[" { return LBRACKET; }
"]" { return RBRACKET; }
%%
int yywrap() {
return 1;
}
2. Parser Specification File (`parser.y`)
%{
#include
#include
void yyerror(const char *s);
int yylex();
%}
%token IF ELSE WHILE RETURN FOR SWITCH CASE DEFAULT BREAK CONTINUE GOTO SIZEOF
%token NUMBER IDENTIFIER STRING_LITERAL CHAR_LITERAL
%left '='
%left "==" "!="
%left '&'
%left '|'
%left '+' '-'
%left '*' '/'
%left INCREMENT DECREMENT
%token LPAREN RPAREN LBRACE RBRACE SEMICOLON LBRACKET RBRACKET
%%
program:
/* Empty */
| program external_declaration
;
external_declaration:
function_definition
| declaration
;
function_definition:
declaration_specifiers declarator compound_statement
;
declaration:
declaration_specifiers init_declarator_list_opt SEMICOLON
;
declaration_specifiers:
storage_class_specifier_opt type_specifier type_qualifier_opt function_specifier_opt
| storage_class_specifier_opt type_specifier type_qualifier_opt
| storage_class_specifier_opt type_specifier
| type_specifier type_qualifier_opt function_specifier_opt
| type_specifier type_qualifier_opt
| type_specifier
;
storage_class_specifier_opt:
/* Empty */
| STORAGE_CLASS_SPECIFIER
;
type_specifier:
VOID
| CHAR
| SHORT
| INT
| LONG
| FLOAT
| DOUBLE
| SIGNED
| UNSIGNED
| struct_or_union_specifier
| enum_specifier
;
type_qualifier_opt:
/* Empty */
| TYPE_QUALIFIER
;
function_specifier_opt:
/* Empty */
| FUNCTION_SPECIFIER
;
struct_or_union_specifier:
STRUCT IDENTIFIER '{' struct_declaration_list '}'
| UNION IDENTIFIER '{' struct_declaration_list '}'
| STRUCT '{' struct_declaration_list '}'
| UNION '{' struct_declaration_list '}'
;
enum_specifier:
ENUM IDENTIFIER '{' enumerator_list '}'
| ENUM '{' enumerator_list '}'
;
enumerator_list:
enumerator
| enumerator_list ',' enumerator
;
enumerator:
IDENTIFIER
| IDENTIFIER '=' constant_expression
;
init_declarator_list_opt:
/* Empty */
| init_declarator_list
;
init_declarator_list:
init_declarator
| init_declarator_list ',' init_declarator
;
init_declarator:
declarator
| declarator '=' initializer
;
declarator:
pointer_opt direct_declarator
;
pointer_opt:
/* Empty */
| '*' pointer_opt
;
direct_declarator:
IDENTIFIER
| direct_declarator LBRACKET constant_expression_opt RBRACKET
| direct_declarator LPAREN parameter_type_list RPAREN
| LPAREN direct_declarator RPAREN
;
compound_statement:
'{' block_item_list_opt '}'
;
block_item_list_opt:
/* Empty */
| block_item_list
;
block_item_list:
block_item
| block_item_list block_item
;
block_item:
declaration
| statement
;
statement:
expression_statement
| compound_statement
| selection_statement
| iteration_statement
| jump_statement
;
expression_statement:
expression_opt SEMICOLON
;
selection_statement:
IF '(' expression ')' statement
| IF '(' expression ')' statement ELSE statement
| WHILE '(' expression ')' statement
| SWITCH '(' expression ')' statement
;
iteration_statement:
WHILE '(' expression ')' statement
| DO statement WHILE '(' expression ')' SEMICOLON
| FOR '(' expression_opt SEMICOLON expression_opt SEMICOLON expression_opt ')' statement
;
jump_statement:
GOTO IDENTIFIER SEMICOLON
| CONTINUE SEMICOLON
| BREAK SEMICOLON
| RETURN expression_opt SEMICOLON
;
expression:
IDENTIFIER '=' expression
| expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression
| NUMBER
| STRING_LITERAL
| CHAR_LITERAL
| IDENTIFIER
| '(' expression ')'
;
constant_expression_opt:
/* Empty */
| constant_expression
;
constant_expression:
expression
;
parameter_type_list:
parameter_list
| parameter_list ',' ELLIPSIS
;
parameter_list:
parameter_declaration
| parameter_list ',' parameter_declaration
;
parameter_declaration:
declaration_specifiers declarator_opt
| declaration_specifiers
;
declarator_opt:
/* Empty */
| declarator
;
initializer:
assignment_expression
| '{' initializer_list_opt '}'
;
initializer_list_opt:
/* Empty */
| initializer_list
;
initializer_list:
initializer
| initializer_list ',' initializer
;
assignment_expression:
/* Definition for assignment expressions */
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
yyparse();
return 0;
}
3. Header File (`parser.tab.h`)
#ifndef PARSER_TAB_H
#define PARSER_TAB_H
/* Tokens */
enum yytokentype {
IF = 258,
ELSE,
WHILE,
RETURN,
FOR,
SWITCH,
CASE,
DEFAULT,
BREAK,
CONTINUE,
GOTO,
SIZEOF,
NUMBER,
IDENTIFIER,
STRING_LITERAL,
CHAR_LITERAL,
LPAREN = 274,
RPAREN,
LBRACE,
RBRACE,
SEMICOLON,
LBRACKET,
RBRACKET,
INCREMENT,
DECREMENT,
ASSIGN,
EQ,
NEQ,
AND,
OR
};
/* Value type */
typedef union {
int num;
char *str;
} YYSTYPE;
extern YYSTYPE yylval;
#endif /* PARSER_TAB_H */