%{ #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 COLON DOTS %token VAR FUNC RETURN STRING_LITERAL FLOAT_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 %token CHAN CONST CASE SWITCH %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 %token FLOAT32 FLOAT64 %token COMPLEX64 COMPLEX128 %token 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: | var_declaration SEMICOLON { printf("\033[1;33mSTATEMENT: variable declaration\033[0m\n"); } | func_declaration { printf("\033[1;33mSTATEMENT: function 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); } ; statements_list: | statements_list statement | statements_list block | statements_list expr SEMICOLON ; block: LBRACE statements_list RBRACE ; // // condition condition: 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"); } ; post_statement: | IDENTIFIER ASSIGN math_expr { } | 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: | IDENTIFIER SHORT_DECLARATION math_expr | IDENTIFIER ASSIGN math_expr 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 { printf("\033[1;35mRETURN math expr\033[0m\n") } | RETURN literal { printf("\033[1;35mRETURN literal\033[0m\n") } | IDENTIFIER ASSIGN math_expr { } | math_expr { } ; 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"); } | IDENTIFIER { printf("IDENTIFIER: %s\n", $1); } | IDENTIFIER INC { printf("POST-INCREMENT: %s++\n", $1); } | IDENTIFIER DEC { printf("POST-DECREMENT: %s--\n", $1); } ; 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 ; // // types int_types: UINT { } | UINT8 { } | UINT16 { } | UINT32 { } | UINT64 { } | INT { } | INT8 { } | INT16 { } | INT32 {} | INT64 { } ; float_types: FLOAT32 | FLOAT64 complex_types: COMPLEX64 | COMPLEX128 string_types: STRING { } ; type: int_types { } | string_types { } | float_types { } | complex_types { } ; // // literals literal: STRING_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 ; // // functions decl arg_declaration: IDENTIFIER type { printf("\033[1;35mARG: %s\n\033[0m", $1); } ; arg_list: | arg_declaration | arg_list COMMA arg_declaration ; return_type: | type { } ; 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); } ; // // vars decl var_declaration: IDENTIFIER SHORT_DECLARATION math_expr { printf("\033[1;33mSHORT DECL with math expr: %s\n\033[0m", $1); } | IDENTIFIER SHORT_DECLARATION literal { printf("\033[1;33mSHORT DECL with literal: %s\n\033[0m", $1); } | VAR IDENTIFIER type { { printf("\033[1;33mVAR DECL without init value: %s\n\033[0m", $2); } } | VAR IDENTIFIER type ASSIGN math_expr { { printf("\033[1;33mVAR DECL with math expr init value: %s\n\033[0m", $2); } } | VAR IDENTIFIER type ASSIGN literal { { printf("\033[1;33mVAR DECL with literal init value: %s\n\033[0m", $2); } } ; %% // 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; }