%{ #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 LBRACK RBRACK SEMICOLON ASSIGN LPAREN RPAREN COMMA COLON DOTS %token VAR FUNC RETURN STRING_LITERAL FLOAT_LITERAL COMPLEX_LITERAL NUMBER PACKAGE IMPORT %token INC DEC PLUS_EQ MINUS_EQ MUL_EQ DIV_EQ MOD_EQ %token AMPERSAND_EQ PIPE_EQ XOR_EQ LSHIFT_EQ RSHIFT_EQ AND_NOT_EQ %token FOR BREAK CONTINUE ARROW IF ELSE RANGE DEFER GO TYPE STRUCT MAP CHAN %token CHAN CONST CASE SWITCH MAKE %token PLUS MINUS MULT DIV MOD %token STRING %token UINT UINT8 UINT16 UINT32 UINT64 UINT_PTR %token INT INT8 INT16 INT32 INT64 %token RUNE BYTE BOOL_LITERAL BOOL %token FLOAT32 FLOAT64 %token COMPLEX64 COMPLEX128 %token IDENTIFIER WITH_DOT_IDENTIFIER %token AND OR NOT EQ NEQ LT GT LEQ GEQ %left PLUS_EQ MINUS_EQ MUL_EQ DIV_EQ MOD_EQ %left AMPERSAND_EQ PIPE_EQ XOR_EQ %left LSHIFT_EQ RSHIFT_EQ AND_NOT_EQ %left PLUS MINUS %left MULT DIV MOD %left OR %left AND %right INC DEC %right NOT %nonassoc EQ NEQ LT GT LEQ GEQ %left UMINUS %% // base program: package_declaration import_declaration | program statement ; statement: | GO func_call SEMICOLON | DEFER func_call SEMICOLON | func_call SEMICOLON { printf("\033[1;33mSTATEMENT: func_call\033[0m\n"); } | var_declaration SEMICOLON { printf("\033[1;33mSTATEMENT: variable declaration\033[0m\n"); } | var_multiple_short_declaration SEMICOLON { printf("\033[1;33mSTATEMENT: variable multiple declaration\033[0m\n"); } | any_identifier ASSIGN math_expr SEMICOLON | any_identifier ASSIGN literal SEMICOLON | var_multiple_short_assignment SEMICOLON | func_declaration { printf("\033[1;33mSTATEMENT: function declaration\033[0m\n"); } | type_delcaration SEMICOLON { printf("\033[1;33mSTATEMENT: type declaration\033[0m\n"); } | cicle { printf("\033[1;33mSTATEMENT: cicle\033[0m\n"); } | condition { printf("\033[1;33mSTATEMENT: condition\033[0m\n"); } | IDENTIFIER COLON { printf("\033[1;33mSTATEMENT: label definition '%s'\033[0m\n", $1); } | make SEMICOLON | any_identifier ARROW math_expr SEMICOLON | any_identifier ARROW literal SEMICOLON ; block: LBRACE statements_list RBRACE ; any_identifier: IDENTIFIER | WITH_DOT_IDENTIFIER | arr_element | map_element // // lists statements_list: | statements_list expr SEMICOLON | statements_list statement | statements_list block ; identifiers_list: | IDENTIFIER { } | identifiers_list COMMA IDENTIFIER { } any_identifiers_list: any_identifier { } | any_identifiers_list COMMA any_identifier { } math_expr_or_literals_list: literal { } | math_expr { } | func_call { } | math_expr_or_literals_list COMMA literal | math_expr_or_literals_list COMMA math_expr | math_expr_or_literals_list COMMA func_call ; math_expr_or_literals_list_or_empty: | math_expr_or_literals_list literals_list: literal | literals_list COMMA literal types_list: | type | types_list COMMA type // // condition condition: IF var_multiple_short_declaration SEMICOLON log_expr block else_part | IF identifiers_list ASSIGN math_expr_or_literals_list SEMICOLON log_expr block else_part | IF log_expr block else_part else_part: { printf("\033[1;33mSTATEMENT: if condition with block\033[0m\n"); } | ELSE IF log_expr block else_part { printf("\033[1;33mSTATEMENT: if condition with block else if block\033[0m\n"); } | ELSE block { printf("\033[1;33mSTATEMENT: if condition with block else block\033[0m\n"); } ; // // cicle cicle: FOR loop_block { printf("\033[1;34mLOOP: infinite for loop\033[0m\n"); } | FOR init_loop_statement SEMICOLON log_expr SEMICOLON post_statement loop_block { printf("\033[1;34mLOOP: full for loop with init, condition and post\033[0m\n"); } | FOR log_expr loop_block { printf("\033[1;34mLOOP: for loop with condition only\033[0m\n"); } | FOR identifiers_list SHORT_DECLARATION RANGE any_identifier loop_block { printf("\033[1;34mLOOP: range for loop\033[0m\n"); } ; post_statement: | identifiers_list ASSIGN math_expr_or_literals_list { } | IDENTIFIER INC { } | IDENTIFIER DEC { } | IDENTIFIER PLUS_EQ math_expr { } | IDENTIFIER MINUS_EQ math_expr { } | IDENTIFIER MUL_EQ math_expr { } | IDENTIFIER DIV_EQ math_expr { } | IDENTIFIER MOD_EQ math_expr { } | IDENTIFIER AMPERSAND_EQ math_expr { } | IDENTIFIER PIPE_EQ math_expr { } | IDENTIFIER XOR_EQ math_expr { } | IDENTIFIER LSHIFT_EQ math_expr { } | IDENTIFIER RSHIFT_EQ math_expr { } | IDENTIFIER AND_NOT_EQ math_expr { } loop_block: LBRACE loop_statements RBRACE ; init_loop_statement: | identifiers_list SHORT_DECLARATION math_expr_or_literals_list | identifiers_list ASSIGN math_expr_or_literals_list loop_statements: | loop_statements statement | loop_statements loop_block | loop_statements expr SEMICOLON | loop_statements break_statement | loop_statements continue_statement | loop_statements IF log_expr loop_block else_part_loop ; else_part_loop: { printf("\033[1;33mSTATEMENT: if condition with block\033[0m\n"); } | ELSE IF log_expr loop_block else_part_loop { printf("\033[1;33mSTATEMENT: if condition with block else if block\033[0m\n"); } | ELSE loop_block { printf("\033[1;33mSTATEMENT: if condition with block else block\033[0m\n"); } ; break_statement: BREAK SEMICOLON { printf("\033[1;31mBREAK\033[0m\n"); } | BREAK IDENTIFIER SEMICOLON { printf("\033[1;31mBREAK TO LABEL: %s\033[0m\n", $2); } ; continue_statement: CONTINUE SEMICOLON { printf("\033[1;31mCONTINUE\033[0m\n"); } | CONTINUE IDENTIFIER SEMICOLON { printf("\033[1;31mCONTINUE TO LABEL: %s\033[0m\n", $2); } ; // // expressions expr: RETURN math_expr_or_literals_list_or_empty { printf("\033[1;35mRETURN math expr\033[0m\n") } | RETURN literal { printf("\033[1;35mRETURN literal\033[0m\n") } | math_expr { } ; math_expr: any_identifier ASSIGN math_expr { } | any_identifier PLUS_EQ math_expr | any_identifier MINUS_EQ math_expr | any_identifier MUL_EQ math_expr | any_identifier DIV_EQ math_expr | any_identifier MOD_EQ math_expr | any_identifier AMPERSAND_EQ math_expr | any_identifier PIPE_EQ math_expr | any_identifier XOR_EQ math_expr | any_identifier LSHIFT_EQ math_expr | any_identifier RSHIFT_EQ math_expr | any_identifier AND_NOT_EQ math_expr | math_expr PLUS math_expr { printf("PLUS\n"); } | math_expr MINUS math_expr { printf("MINUS\n"); } | math_expr MULT math_expr { printf("MULT\n"); } | math_expr DIV math_expr { printf("DIV\n"); } | math_expr MOD math_expr { printf("MOD\n"); } | MINUS math_expr %prec UMINUS { printf("UMINUS\n"); } | LPAREN { printf("LPAREN\n"); } math_expr RPAREN { printf("RPAREN\n"); } | NUMBER { printf("NUMBER\n"); } | FLOAT_LITERAL { printf("FLOAT LITERAL\n"); } | COMPLEX_LITERAL { printf("COMPLEX LITERAL\n"); } | make { printf("make\n"); } | any_identifier { printf("IDENTIFIER\n"); } | any_identifier INC { printf("POST-INCREMENT: ++\n"); } | any_identifier DEC { printf("POST-DECREMENT: --\n"); } | func_call { printf("FUNCTION CALL IN EXPR\n"); } | ARROW any_identifier { printf("TAKE FROM CHAN\n"); } ; log_expr: | log_expr AND log_expr { } | log_expr OR log_expr { } | NOT log_expr %prec UMINUS { } | math_expr EQ math_expr { } | math_expr NEQ math_expr { } | math_expr LT math_expr { } | math_expr LEQ math_expr { } | math_expr GT math_expr { } | math_expr GEQ math_expr { } | LPAREN log_expr RPAREN { } | BOOL_LITERAL | func_call ; // // types struct_types: STRUCT LBRACE declarate_field_list RBRACE ; bool_types: BOOL int_types: UINT { } | UINT8 { } | UINT16 { } | UINT32 { } | UINT64 { } | INT { } | INT8 { } | INT16 { } | INT32 {} | INT64 { } ; float_types: FLOAT32 | FLOAT64 complex_types: COMPLEX64 | COMPLEX128 string_types: STRING { } ; func_types: FUNC LPAREN arg_list RPAREN return_type type: int_types { } | chan_types | map_types | slice_types | arr_types { } | struct_types { } | func_types { } | string_types { } | float_types { } | complex_types { } | bool_types { } ; // // literals literal: STRING_LITERAL { } | map_literal | slice_literal | arr_literal { } | struct_literal { } | func_literal { } | COMPLEX_LITERAL { } | BOOL_LITERAL { } | FLOAT_LITERAL { } | NUMBER { } ; // // Package & import blocks package_declaration: PACKAGE IDENTIFIER SEMICOLON { printf("\033[1;34mPACKAGE IDENTIFIER: %s\n\033[0m", $2); } ; import_declaration: | IMPORT { printf("\033[1;36mHELLO, IMPORT BLOCK\n\033[0m"); } import { printf("\033[1;36mBY, IMPORT BLOCK\n\n\033[0m"); } | IMPORT { printf("\033[1;36mHELLO, IMPORT BLOCK\n\033[0m"); } LPAREN import_list RPAREN { printf("\033[1;36mBY, IMPORT BLOCK\n\n\033[0m"); } ; import: IDENTIFIER STRING_LITERAL { printf("\033[1;36mIMPORTED PACKAGE\n\033[0m"); } SEMICOLON | STRING_LITERAL { printf("\033[1;36mIMPORTED PACKAGE\n\033[0m"); } SEMICOLON ; import_list: import | import_list import ; // // arrays // для случая arr5 := [4]int{1: 42, 3: 99}; с частичным указанием значений arr_field: NUMBER COLON math_expr | NUMBER COLON literal arr_field_list: | arr_field | arr_field_list COMMA arr_field arr_literal: LBRACK NUMBER RBRACK type LBRACE math_expr_or_literals_list_or_empty RBRACE | LBRACK DOTS RBRACK type LBRACE math_expr_or_literals_list_or_empty RBRACE | LBRACK NUMBER RBRACK type LBRACE arr_field_list RBRACE arr_types: LBRACK NUMBER RBRACK type arr_element: IDENTIFIER LBRACK NUMBER RBRACK // slices slice_literal: LBRACK RBRACK type LBRACE math_expr_or_literals_list_or_empty RBRACE slice_types: LBRACK RBRACK type // functions func_literal: FUNC { printf("\033[1;35mHELLO, ANON FUNC\n\033[0m"); } LPAREN arg_list RPAREN return_type block { printf("\033[1;35mBY, ANON FUNC\n\n\033[0m"); } func_call: any_identifier LPAREN math_expr_or_literals_list_or_empty RPAREN | func_literal LPAREN math_expr_or_literals_list_or_empty RPAREN arg_declaration: identifiers_list type { printf("\033[1;35mARG DECLARATIONS:\n\033[0m"); } ; arg_list: | arg_declaration | arg_list COMMA arg_declaration ; return_type: | type | LPAREN types_list RPAREN { } | LPAREN arg_list RPAREN { } ; func_declaration: FUNC IDENTIFIER { printf("\033[1;35mHELLO, FUNC: %s\n\033[0m", $2); } LPAREN arg_list RPAREN return_type block { printf("\033[1;35mBY, FUNC: %s\n\n\033[0m", $2); } ; // // map map_field: literal COLON literal { } | literal COLON math_expr { } | literal COLON func_call { } map_field_list: | map_field | map_field_list COMMA map_field map_types: MAP LBRACK type RBRACK type map_literal: map_types LBRACE map_field_list RBRACE map_element: IDENTIFIER LBRACK literal RBRACK | IDENTIFIER LBRACK any_identifier RBRACK // struct declarate_field_list: | arg_declaration | IDENTIFIER | declarate_field_list SEMICOLON arg_declaration | declarate_field_list SEMICOLON IDENTIFIER ; field: IDENTIFIER COLON literal { } | IDENTIFIER COLON math_expr { } | IDENTIFIER COLON func_call { } field_list: | field | field_list COMMA field struct_literal: any_identifier LBRACE field_list RBRACE { printf("STRUCT LITERAL\n"); } | any_identifier LBRACE math_expr_or_literals_list RBRACE { printf("STRUCT LITERAL\n"); } // chan chan_types: CHAN type // assignment var_multiple_short_assignment: identifiers_list ASSIGN math_expr_or_literals_list // vars decl var_multiple_short_declaration: identifiers_list SHORT_DECLARATION math_expr_or_literals_list var_declaration: VAR IDENTIFIER type | VAR IDENTIFIER any_identifier | VAR identifiers_list any_identifier { { printf("\033[1;33mVAR DECL without init value\n\033[0m"); } } | VAR identifiers_list type { { printf("\033[1;33mVAR DECL without init value\n\033[0m"); } } | VAR identifiers_list ASSIGN math_expr_or_literals_list { { printf("\033[1;33mVAR DECL with literal init value\n\033[0m"); } } | VAR identifiers_list type ASSIGN math_expr_or_literals_list { { printf("\033[1;33mVAR DECL with literal init value\n\033[0m"); } } | VAR identifiers_list any_identifier ASSIGN math_expr_or_literals_list { { printf("\033[1;33mVAR DECL with literal init value\n\033[0m"); } } | VAR IDENTIFIER any_identifier ASSIGN math_expr { { printf("\033[1;33mVAR DECL with type and math expr init value: %s\n\033[0m", $2); } } | VAR IDENTIFIER any_identifier ASSIGN literal { { printf("\033[1;33mVAR DECL with type and literal init value: %s\n\033[0m", $2); } } | VAR IDENTIFIER type ASSIGN math_expr { { printf("\033[1;33mVAR DECL with type and math expr init value: %s\n\033[0m", $2); } } | VAR IDENTIFIER type ASSIGN literal { { printf("\033[1;33mVAR DECL with type and literal init value: %s\n\033[0m", $2); } } ; // type decl type_delcaration: TYPE IDENTIFIER type { { printf("\033[1;33mTYPE DECL\n\033[0m"); } } // make make: MAKE LPAREN type RPAREN | MAKE LPAREN type COMMA math_expr RPAREN | MAKE LPAREN type COMMA math_expr COMMA math_expr RPAREN %% // int main(int argc, char **argv) { if (argc > 1) { FILE *f = fopen(argv[1], "r"); if (!f) { perror("\033[1;91mFailed to open file\033[0m"); return 1; } yyin = f; } yyparse(); printf("\033[1;92mGOOD CODE\033[0m\n"); return 0; }