%{ #include #include #include #include extern int yylineno; extern char *yytext; extern void yyerror(const char *s); extern int yylex(); extern FILE *yyin; void free_node(char *str) { if (str) free(str); } %} %union { char *str; double num; } %token SHORT_DECLARATION LBRACE RBRACE SEMICOLON ASSIGN LPAREN RPAREN COMMA %token VAR FUNC RETURN %token PLUS MINUS MULT DIV MOD EXP %token STRING %token UINT UINT8 UINT16 UINT32 UINT64 %token INT INT8 INT16 INT32 INT64 %token IDENTIFIER STRING_LITERAL FLOAT_LITERAL %type var_declaration type int_types string_types %type arg_declaration return_type %type expr literal math_expr %token NUMBER %left PLUS MINUS %left MULT DIV MOD %left EXP %left UMINUS %% program: | program statement ; statement: expr SEMICOLON | var_declaration SEMICOLON | func_declaration | block ; block: LBRACE statements_list RBRACE ; statements_list: | statements_list statement ; expr: RETURN math_expr { printf("Return: %g\n", $2); } | IDENTIFIER ASSIGN math_expr { printf("Assignment: %s = %g\n", $1, $3); free_node($1); } | math_expr { $$ = $1; } ; math_expr: math_expr PLUS math_expr { $$ = $1 + $3; } | math_expr MINUS math_expr { $$ = $1 - $3; } | math_expr MULT math_expr { $$ = $1 * $3; } | math_expr DIV math_expr { $$ = $1 / $3; } | math_expr MOD math_expr { $$ = fmod($1, $3); } | math_expr EXP math_expr { $$ = pow($1, $3); } | MINUS math_expr %prec UMINUS { $$ = -$2; } | LPAREN math_expr RPAREN { $$ = $2; } | NUMBER { $$ = $1; } | FLOAT_LITERAL { $$ = atof($1); free_node($1); } | IDENTIFIER { $$ = 0; free_node($1); } ; /* Остальные правила остаются без изменений */ int_types: UINT { $$ = strdup("uint"); } | UINT8 { $$ = strdup("uint8"); } | UINT16 { $$ = strdup("uint16"); } | UINT32 { $$ = strdup("uint32"); } | UINT64 { $$ = strdup("uint64"); } | INT { $$ = strdup("int"); } | INT8 { $$ = strdup("int8"); } | INT16 { $$ = strdup("int16"); } | INT32 { $$ = strdup("int32"); } | INT64 { $$ = strdup("int64"); } ; string_types: STRING { $$ = strdup("string"); } ; type: int_types { $$ = $1; } | string_types { $$ = $1; } ; literal: STRING_LITERAL { $$ = 0; /* Для строк возвращаем 0 */ free_node($1); } | FLOAT_LITERAL { $$ = atof($1); free_node($1); } | NUMBER { $$ = $1; } ; arg_declaration: IDENTIFIER type { $$ = $2; printf("Argument: %s %s\n", $1, $2); free_node($1); } ; arg_list: | arg_declaration | arg_list COMMA arg_declaration ; return_type: /* empty */ { $$ = NULL; } | type { $$ = $1; } ; func_declaration: FUNC IDENTIFIER LPAREN arg_list RPAREN return_type block { printf("Function declaration: %s with return type %s\n", $2, $6 ? $6 : "void"); free_node($2); if ($6) free_node($6); } ; var_declaration: IDENTIFIER SHORT_DECLARATION math_expr { printf("Short declaration: %s := %g\n", $1, $3); free_node($1); } | IDENTIFIER SHORT_DECLARATION literal { printf("Short declaration: %s := %s\n", $1, $3); free_node($1); free_node($3); } | VAR IDENTIFIER type { printf("Variable declaration: var %s %s\n", $2, $3); free_node($2); free_node($3); } | VAR IDENTIFIER type ASSIGN math_expr { printf("Var with assign declaration: var %s %s = %g\n", $2, $3, $5); free_node($2); free_node($3); } | VAR IDENTIFIER type ASSIGN literal { printf("Var with assign declaration: var %s %s = %s\n", $2, $3, $5); free_node($2); free_node($3); free_node($5); } ; %% int main(int argc, char **argv) { if (argc > 1) { FILE *f = fopen(argv[1], "r"); if (!f) { perror("\033[91mFailed to open file\033[0m"); return 1; } yyin = f; } yyparse(); return 0; }