%{
#include "parser.tab.h" // Include header for token definitions
#include <stdlib.h>
#include <stdio.h>
%}
%%
[ \t\n]+ ; // Ignore whitespace
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"return" { return RETURN; }
"for" { return FOR; }
"int" { return INT; }
"float" { return FLOAT; }
"double" { return DOUBLE; }
"char" { return CHAR; }
"void" { return VOID; }
"public" { return PUBLIC; }
"class" { return CLASS; }
"private" { return PRIVATE; }
"protected" { return PROTECTED; }
"==" { return EQ; }
"!=" { return NEQ; }
"&" { return AND; }
"|" { return OR; }
"&&" { return ANDAND; }
"||" { return OROR; }
"++" { return INCREMENT; }
"--" { return DECREMENT; }
"=" { return ASSIGN; }
"+"|"-"|"*"|"/" { return yytext[0]; }
[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 LPAREN; }
")" { return RPAREN; }
"{" { return LBRACE; }
"}" { return RBRACE; }
"[" { return LBRACKET; }
"]" { return RBRACKET; }
";" { return SEMICOLON; }
"," { return COMMA; }
%%
int yywrap() {
return 1;
}
%{
#include <stdio.h>
#include <stdlib.h>
void yyerror(const char *s);
int yylex();
%}
%token IF ELSE WHILE RETURN FOR INT FLOAT DOUBLE CHAR VOID
%token PUBLIC CLASS PRIVATE PROTECTED
%token NUMBER IDENTIFIER STRING_LITERAL CHAR_LITERAL
%left '='
%left "==" "!="
%left '&'
%left '|'
%left "&&" "||"
%left '+' '-'
%left '*' '/'
%left INCREMENT DECREMENT
%token LPAREN RPAREN LBRACE RBRACE SEMICOLON COMMA LBRACKET RBRACKET
%%
program:
/* Empty */
| program external_declaration
;
external_declaration:
function_definition
| class_definition
| declaration
;
function_definition:
type_specifier declarator compound_statement
;
class_definition:
CLASS IDENTIFIER '{' class_body '}'
;
class_body:
/* Empty */
| class_body class_member
;
class_member:
declaration
| function_definition
;
declaration:
type_specifier declarator_list SEMICOLON
;
type_specifier:
INT
| FLOAT
| DOUBLE
| CHAR
| VOID
;
declarator_list:
declarator
| declarator_list ',' declarator
;
declarator:
IDENTIFIER
| IDENTIFIER '[' NUMBER ']'
| IDENTIFIER '(' parameter_list_opt ')'
;
parameter_list_opt:
/* Empty */
| parameter_list
;
parameter_list:
parameter_declaration
| parameter_list ',' parameter_declaration
;
parameter_declaration:
type_specifier declarator
;
compound_statement:
'{' statement_list_opt '}'
;
statement_list_opt:
/* Empty */
| statement_list
;
statement_list:
statement
| statement_list 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
| RETURN expression_opt SEMICOLON
;
iteration_statement:
WHILE '(' expression ')' statement
| FOR '(' expression_opt SEMICOLON expression_opt SEMICOLON expression_opt ')' statement
;
jump_statement:
RETURN expression_opt SEMICOLON
;
expression:
IDENTIFIER '=' expression
| expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression
| NUMBER
| STRING_LITERAL
| CHAR_LITERAL
| IDENTIFIER
| '(' expression ')'
;
expression_opt:
/* Empty */
| expression
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
yyparse();
return 0;
}
#ifndef PARSER_TAB_H
#define PARSER_TAB_H
/* Tokens */
enum yytokentype {
IF = 258,
ELSE,
WHILE,
RETURN,
FOR,
INT,
FLOAT,
DOUBLE,
CHAR,
VOID,
PUBLIC,
CLASS,
PRIVATE,
PROTECTED,
NUMBER,
IDENTIFIER,
STRING_LITERAL,
CHAR_LITERAL,
LPAREN = 274,
RPAREN,
LBRACE,
RBRACE,
SEMICOLON,
COMMA,
LBRACKET,
RBRACKET,
INCREMENT,
DECREMENT,
ASSIGN,
EQ,
NEQ,
AND,
OR,
ANDAND,
OROR
};
/* Value type */
typedef union {
int num;
char *str;
} YYSTYPE;
extern YYSTYPE yylval;
#endif /* PARSER_TAB_H */
#include <stdio.h>
#include <stdlib.h>
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
#include "parser.tab.h"
int main() {
yyparse();
return 0;
}
To compile the C++ compiler using Lex and Yacc, follow these steps:
flex lexer.l
bison -d parser.y
gcc lex.yy.c parser.tab.c error.c main.c -o compiler -lfl
./compiler input_file.c