%{ #include #include #include extern int yylineno; extern char *last_lexeme; void yyerror(const char *s); int yylex(); extern FILE *yyin; %} %union { int num; char *str; } %token NUMBER %token IDENTIFIER %token IF ELSE WHILE RETURN PRINT %token AND OR NOT GE LE EQ NE %right '=' %left OR %left AND %left EQ NE %left '<' '>' GE LE %left '+' '-' %left '*' '/' '%' %right NOT UMINUS %% program: | program statement ; statement: expr ';' semicolons | IF '(' expr ')' statement ELSE statement | IF '(' expr ')' statement | WHILE '(' expr ')' statement | RETURN expr ';' semicolons | PRINT expr ';' semicolons | '{' program '}' ; semicolons: /* empty */ | semicolons ';' ; expr: NUMBER | IDENTIFIER | IDENTIFIER '=' expr | expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '%' expr | expr AND expr | expr OR expr | NOT expr | '-' expr %prec UMINUS | '+' expr | expr '>' expr | expr '<' expr | expr GE expr | expr LE expr | expr EQ expr | expr NE expr | '(' expr ')' ; %% void yyerror(const char *s) { if (last_lexeme) { fprintf(stderr, "\033[91mError at line %d: %s (near '%s')\n\033[0m", yylineno, s, last_lexeme); } else { fprintf(stderr, "\033[91mError at line %d: %s\n\033[0m", yylineno, s); } exit(1); } int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "\033[91mUsage: %s \n\033[0m", argv[0]); return 1; } FILE *input = fopen(argv[1], "r"); if (!input) { perror("\033[91mError opening file"); printf("\033[0m"); return 1; } yyin = input; yyparse(); fclose(input); printf("\033[92mParsing completed successfully!\033[0m\n"); return 0; }