C++ Compiler Files and Compilation Instructions

1. Lexer Specification File (`lexer.l`)


%{
#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;
}
            

2. Parser Specification File (`parser.y`)


%{
#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;
}
            

3. Header File (`parser.tab.h`)


#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 */
            

4. Error Handling File (`error.c`)


#include <stdio.h>
#include <stdlib.h>

void yyerror(const char *s) {
    fprintf(stderr, "Error: %s\n", s);
}
            

5. Main File (`main.c`)


#include "parser.tab.h"

int main() {
    yyparse();
    return 0;
}
            

6. Compiling the Compiler

To compile the C++ compiler using Lex and Yacc, follow these steps: