%{ #include #include void yyerror(const char *s); extern int yylex(); extern char *yytext; extern FILE *yyin; bool debug = false; // debug mode %} %union { char *str; } %token IDENTIFIER NUMBER %token LBRACE RBRACE LPAREN RPAREN SEMICOLON ASSIGN PLUS MINUS MULT DIV MOD RET PRINT WHILE IF ELSE AND OR NOT %type expr program statement block %left OR %left AND %right NOT %left PLUS MINUS %left MULT DIV MOD %right UNARY %% // Program - последовательность утверждений program: | program statement ; // Утверждение - либо блок {...}, либо выражение с ; в конце, // либо цикл while, либо конструкиця if, либо конструкций if-else statement: { if (debug) printf("\033[93mANOTHER STATEMENT\n\033[0m"); } expr SEMICOLON | { if (debug) printf("\033[93mNEW BLOCK\n\033[0m"); } block | WHILE { if (debug) printf("\033[1;34mWHILE LOOP DETECTED\033[0m\n"); } LPAREN expr RPAREN { if (debug) printf("\033[1;34mWHILE BODY STARTS\033[0m\n"); } block { if (debug) printf("\033[1;34mWHILE LOOP ENDED\033[0m\n"); } | IF LPAREN expr RPAREN block { if (debug) printf("\033[1;34mIF BLOCK ENDED\033[0m\n"); } | IF LPAREN expr RPAREN block { if (debug) printf("\033[1;34mIF BLOCK ENDED\033[0m\n"); } ELSE { if (debug) printf("\033[1;34mELSE BLOCK STARTED\033[0m\n"); } block { if (debug) printf("\033[1;34mELSE BLOCK ENDED\033[0m\n"); } ; // Блок - { program }, т.е. это последовательность утверждений и она находится в скобках { } block: LBRACE program RBRACE ; // Возможные выражения expr: RET { if (debug) printf("RET\n") } expr // выражение вида return expr | PLUS { if (debug) printf("UNARY PLUS\n"); } expr %prec UNARY // выражение вида +expr | MINUS { if (debug) printf("UNARY MINUS\n"); } expr %prec UNARY // выражение вида -expr | PRINT { if (debug) printf("PRINT\n") } expr // выражение вида print expr | IDENTIFIER { if (debug) printf("IDENTIFIER(%s)\n", $1); free($1); } // выражения вида a=expr ASSIGN { if (debug) printf("ASSIGN\n"); } expr | expr PLUS { if (debug) printf("PLUS\n") } expr // выражения вида expr+expr | expr MINUS { if (debug) printf("MINUS\n") } expr // выражения вида expr-expr | expr MULT { if (debug) printf("MULT\n") } expr // выражения вида expr*expr | expr DIV { if (debug) printf("DIV\n") } expr // выражения вида expr/expr | expr MOD { if (debug) printf("MOD\n") } expr // выражения вида expr%expr | LPAREN { if (debug) printf("LPAREN\n") } expr RPAREN { if (debug) printf("RPAREN\n") } // выражения вида (expr) | expr OR expr | expr AND expr | NOT expr | IDENTIFIER { if (debug) printf("IDENTIFIER(%s)\n", $1); free($1); } | NUMBER { if (debug) printf("NUMBER(%s)\n", $1); free($1); } ; %% int main(int argc, char **argv) { if (argc > 1) { char* path; // debug mode if (argc > 2) { path = argv[2]; if (!strcmp(argv[1], "-d")) { debug = true; } } else { path = argv[1]; } // default mode FILE *f = fopen(path, "r"); if (!f) { perror("\033[91mFail open file\033[0m"); return 1; } yyin = f; } yyparse(); printf("\033[92m\nGood code\033[0m"); return 0; }