From b73d25de5011022df8d6d86433380621e2a46aa2 Mon Sep 17 00:00:00 2001 From: melentev_i Date: Sat, 17 May 2025 19:02:17 +0300 Subject: [PATCH] =?UTF-8?q?if=20=D0=B8=20loop=20=D1=81=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=D1=8B,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=B8=D1=85=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B,=20=D0=BD=D1=83=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=B1=D1=83=D0=B4=D0=B5=D1=82=20=D0=B4=D0=BE=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D1=82=D1=8C=20=D0=B2=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=86=D0=B5=D1=81=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- analyzers/test/test.l | 48 ++++++++++++- analyzers/test/test.y | 154 +++++++++++++++++++++++++++++++++++++++--- main.py | 6 +- tests/test_blocks.txt | 38 +++++++++-- tests/test_cicle.txt | 67 ++++++++++++++++++ tests/test_if.txt | 57 ++++++++++++++++ 6 files changed, 349 insertions(+), 21 deletions(-) create mode 100644 tests/test_cicle.txt create mode 100644 tests/test_if.txt diff --git a/analyzers/test/test.l b/analyzers/test/test.l index 1411236..d27443b 100644 --- a/analyzers/test/test.l +++ b/analyzers/test/test.l @@ -7,7 +7,7 @@ extern int yylineno; void yyerror(const char *s) { - fprintf(stderr, "\033[91mError at line %i: %s\033[0m\n", yylineno, s); + fprintf(stderr, "\033[1;91mError at line %i: %s\033[0m\n", yylineno, s); exit(1); } @@ -31,7 +31,51 @@ LETTER_OR_DIGIT [a-zA-Z0-9_] "int16" { return INT16; } "int32" { return INT32; } "int64" { return INT64; } +"complex64" { return COMPLEX64; } +"complex128" { return COMPLEX128; } +"byte" { return BYTE; } +"rune" { return RUNE; } +"float32" { return FLOAT32; } +"float64" { return FLOAT64; } +"uintptr" { return UINT_PTR; } +"true" { return BOOL_LIT; } +"false" { return BOOL_LIT; } +"if" { return IF; } +"else" { return ELSE; } +"<-" { return ARROW; } +"==" { return EQ; } +"&&" { return AND; } +"||" { return OR; } +"!" { return NOT; } +"!=" { return NEQ; } +"<" { return LT; } +">" { return GT; } +"<=" { return LEQ; } +">=" { return GEQ; } + +"+=" { return PLUS_EQ; } +"-=" { return MINUS_EQ; } +"*=" { return MUL_EQ; } +"/=" { return DIV_EQ; } +"%=" { return MOD_EQ; } +"&=" { return AMPERSAND_EQ; } +"|=" { return PIPE_EQ; } +"^=" { return XOR_EQ; } +"<<=" { return LSHIFT_EQ; } +">>=" { return RSHIFT_EQ; } +"&^=" { return AND_NOT_EQ; } + +"++" { return INC; } +"--" { return DEC; } + +"for" { return FOR; } +"break" { return BREAK; } +"switch" { return SWITCH; } +"case" { return CASE; } +"chan" { return CHAN; } +"const" { return CONST; } +"continue" { return CONTINUE; } "package" { return PACKAGE; } "import" { return IMPORT; } "var" { return VAR; } @@ -50,6 +94,8 @@ LETTER_OR_DIGIT [a-zA-Z0-9_] ")" { return RPAREN; } "," { return COMMA; } ";" { return SEMICOLON; } +"..." { return DOTS; } +":" { return COLON; } \"([^"\\]|\\.)*\" { // правило для строк с возможность экранирования через \спецсимвол return STRING_LITERAL; diff --git a/analyzers/test/test.y b/analyzers/test/test.y index 8a61aa2..26efd99 100644 --- a/analyzers/test/test.y +++ b/analyzers/test/test.y @@ -21,17 +21,32 @@ void free_node(char *str) { double num; } -%token SHORT_DECLARATION LBRACE RBRACE SEMICOLON ASSIGN LPAREN RPAREN COMMA +%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 +%token UINT UINT8 UINT16 UINT32 UINT64 UINT_PTR %token INT INT8 INT16 INT32 INT64 - +%token RUNE BYTE BOOL_LIT +%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 %% @@ -41,21 +56,103 @@ program: | program statement ; + statement: - expr SEMICOLON | var_declaration SEMICOLON + { printf("\033[1;33mSTATEMENT: variable declaration\033[0m\n"); } | func_declaration - | block + { printf("\033[1;33mSTATEMENT: function declaration\033[0m\n"); } + | cicle + { printf("\033[1;33mSTATEMENT: loop construct\033[0m\n"); } + | IF log_expr block else_part + | IDENTIFIER COLON + { printf("\033[1;33mSTATEMENT: label definition '%s'\033[0m\n", $1); } ; + +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: + 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 { } + | INC IDENTIFIER { } + | DEC IDENTIFIER { } + | 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 { } + block: LBRACE statements_list RBRACE ; - + statements_list: | statements_list statement + | statements_list block + | statements_list expr SEMICOLON ; +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); } + ; + + + expr: RETURN math_expr { printf("\033[1;35mRETURN math expr\033[0m\n") } | RETURN literal { printf("\033[1;35mRETURN literal\033[0m\n") } @@ -74,9 +171,28 @@ math_expr: | 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 { } + | comparison_expr { } + | LPAREN log_expr RPAREN { } + | BOOL_LIT + ; + +comparison_expr: + | 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 { } ; -/* Остальные правила остаются без изменений */ int_types: UINT { } | UINT8 { } @@ -90,6 +206,14 @@ int_types: | INT64 { } ; +float_types: + FLOAT32 + | FLOAT64 + +complex_types: + COMPLEX64 + | COMPLEX128 + string_types: STRING { } ; @@ -97,10 +221,13 @@ string_types: type: int_types { } | string_types { } + | float_types { } + | complex_types { } ; literal: STRING_LITERAL { } + | BOOL_LIT { } | FLOAT_LITERAL { } | NUMBER { } ; @@ -112,12 +239,13 @@ package_declaration: ; 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"); } 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: - STRING_LITERAL { printf("\033[1;36mIMPORTED PACKAGE\n\033[0m"); } SEMICOLON + 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: @@ -126,6 +254,7 @@ import_list: ; // +// functions decl arg_declaration: IDENTIFIER type { printf("\033[1;35mARG: %s\n\033[0m", $1); } @@ -146,7 +275,9 @@ func_declaration: 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); } @@ -156,17 +287,18 @@ var_declaration: ; %% +// 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"); + perror("\033[1;91mFailed to open file\033[0m"); return 1; } yyin = f; } yyparse(); - printf("\033[92mGOOD CODE\033[0m"); + printf("\033[1;92mGOOD CODE\033[0m\n"); return 0; } \ No newline at end of file diff --git a/main.py b/main.py index 08aba1c..74c2d1d 100644 --- a/main.py +++ b/main.py @@ -3,9 +3,9 @@ import subprocess # ЭТИ ПУТИ НАДО ЗАДАТЬ ВРУЧНУЮ # *.l и *.y файлы из директории ANALYZERS_DIR ДОЛЖНЫ НАЗЫВАТЬСЯ как basename этой директории!!! -ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\go-analyzer\analyzers\test' -FLEX_EXE_PATH = r"C:\tools\win_flex_bison\win_flex.exe" -BISON_EXE_PATH = r"C:\tools\win_flex_bison\win_bison.exe" +ANALYZERS_DIR = r'C:\Users\Илья\Desktop\6sem\Компиляторы\Курсач\2\go-analyzer\analyzers\test' +FLEX_EXE_PATH = r"C:\Users\Илья\Desktop\win_flex_bison-latest\win_flex.exe" +BISON_EXE_PATH = r"C:\Users\Илья\Desktop\win_flex_bison-latest\win_bison.exe" def main(): # Подготовка путей diff --git a/tests/test_blocks.txt b/tests/test_blocks.txt index f4da731..7a78185 100644 --- a/tests/test_blocks.txt +++ b/tests/test_blocks.txt @@ -1,3 +1,9 @@ +package main; + +import ( + "fmt"; + "log"; +) func test_func(a string, b int, c uint16) int { var x int = 42; @@ -11,12 +17,29 @@ func func_without_args() int { func func_without_return_type(a string) { return a; } - -a := 1 + 2; -{ - +func main() { a := 229.162613; - + if (a > 300) { + s := "test string"; + } + for i := 5; i < 10; i &^= 1 { + i++; + break; + } + for i := 0; i < 10 && j > 5; i++ { + } + for { + var d complex128; + a := 229.162613; + break gotocheck; + s := "test string"; + b := 2 - 1; + } + for i := 0; i < 10; i += 2 { } + for i := 0; i < 10; i = i * 2 { + break; + } + for i := 10; i > 0; i-- { } a = 1; a = s; @@ -31,7 +54,10 @@ a := 1 + 2; var a uint16; var a uint32; var a uint64; - + var b float32; + var c float64; + var d complex128; + var e complex64; var a string = "123123"; { diff --git a/tests/test_cicle.txt b/tests/test_cicle.txt new file mode 100644 index 0000000..8896941 --- /dev/null +++ b/tests/test_cicle.txt @@ -0,0 +1,67 @@ +package main; + +func main() { + for { + break; + } + + i := 0; + for i < 5 { + i++; + } + + for j := 0; j < 10; j++ { + } + + for o := 0; o < 10; o++ { + if o%2 == 0 { + continue; + } + } + + for n := 0; ; n++ { + if n > 5 { + break; + } + } + +outer: + + + for p := 0; p < 3; p++ { + for q := 0; q < 3; q++ { + if p*q > 2 { + break outer; + } + } + } + +outer2: + for r := 0; r < 3; r++ { + for s := 0; s < 3; s++ { + if r*s > 1 { + continue outer2; + } + } + } + + for t := 10; t > 0; t-- { + } + + u := 0; + for u < 5 { + u++; + } + + for k, l := 0, 10; k < l; k, l = k+1, l-1 { + } + + arr := []int{1, 2, 3} + for idx, val := range arr { + } + + m := map[string]int{"a": 1, "b": 2} + for key, value := range m { + } + +} \ No newline at end of file diff --git a/tests/test_if.txt b/tests/test_if.txt new file mode 100644 index 0000000..2440dce --- /dev/null +++ b/tests/test_if.txt @@ -0,0 +1,57 @@ +package main; + +import "fmt"; + +func main() { + if true { + } + + if false { + } else { + } + + x := 10; + if x < 5 { + } else if x < 15 { + } else { + } + + + + + if true { + if false { + } else { + } + } + if (x > 5 || x < 15) && x != 10 { + } + + if z := x * 2; z > 15 && z < 25 { + } + + if false { + } + + + if isValid() { + } + + + + if shouldReturn() { + return; + } +} + +func isValid() bool { + return true +} + +func shouldReturn() bool { + return false +} +if a, b := 1, 2; a < b && b < 3 { +} +if y := 20; y > 15 { + } \ No newline at end of file