Files for ANSI C Compiler using Lex and Yacc

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

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


#include 
#include 

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;
}