%{ #include #include #include #include extern int yylineno; extern char *yytext; void yyerror(const char *s) { fprintf(stderr, "\033[91mError at line %d: %s\033[0m\n", yylineno, s); exit(1); } extern int yylex(); extern FILE *yyin; %} %union { char *str_val; int int_val; float float_val; char rune_val; bool bool_val; } %token BREAK CASE CHAN CONST CONTINUE DEFAULT DEFER ELSE FALLTHROUGH FOR FUNC %token GO GOTO IF IMPORT INTERFACE MAP PACKAGE RANGE RETURN SELECT STRUCT %token SWITCH TYPE VAR %token BOOL_LIT %token NIL %token IDENT %token INT_LIT %token FLOAT_LIT %token STRING_LIT %token RAW_STRING_LIT %token RUNE_LIT %token PLUS MINUS STAR SLASH PERCENT %token AMPERSAND PIPE CARET LSHIFT RSHIFT AMPERSAND_CARET %token PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ %token AMPERSAND_EQ PIPE_EQ CARET_EQ LSHIFT_EQ RSHIFT_EQ AMPERSAND_CARET_EQ %token LAND LOR ARROW INC DEC %token EQ NEQ LT GT LEQ GEQ %token NOT ASSIGN DECLARE_ASSIGN ELLIPSIS %token COLON SEMICOLON COMMA DOT %token LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE %right INC DEC %right ARROW %right NOT %left STAR SLASH PERCENT %left PLUS MINUS %left LSHIFT RSHIFT AMPERSAND_CARET %left AMPERSAND PIPE CARET %left EQ NEQ LT GT LEQ GEQ %left LAND %left LOR %right ASSIGN DECLARE_ASSIGN %right PLUS_EQ MINUS_EQ STAR_EQ SLASH_EQ PERCENT_EQ %right AMPERSAND_EQ PIPE_EQ CARET_EQ LSHIFT_EQ RSHIFT_EQ AMPERSAND_CARET_EQ %left DOT ELLIPSIS %left COLON SEMICOLON COMMA %% program: | program top_level_stmt ; top_level_stmt: decl_stmt | func_decl | block ; decl_stmt: VAR IDENT type ASSIGN expr | CONST IDENT type ASSIGN expr ; func_decl: FUNC IDENT LPAREN params RPAREN block ; params: | param_list ; param_list: IDENT type | param_list COMMA IDENT type ; type: IDENT | LBRACK RBRACK type | STAR type ; expr: literal | IDENT | expr PLUS expr | expr MINUS expr | expr STAR expr | expr SLASH expr | expr PERCENT expr | expr LSHIFT expr | expr RSHIFT expr | expr AMPERSAND expr | expr PIPE expr | expr CARET expr | expr AMPERSAND_CARET expr | expr LAND expr | expr LOR expr | expr EQ expr | expr NEQ expr | expr LT expr | expr GT expr | expr LEQ expr | expr GEQ expr | NOT expr | MINUS expr %prec NOT | LPAREN expr RPAREN | expr DOT IDENT | IDENT LPAREN args RPAREN ; args: | expr | args COMMA expr ; type: basic_type | array | slice | pointer | struct_type | interface | function | map | channel basic_type: uint8 | uint16 | uint32 | uint64 | int8 | "int16" | "int32" | "int64" | "float32" | "float64" | "complex64" | "complex128" | "uint" | "int" | "uintptr" | "bool" | "string" array: LBRACK INT RBRACK type slice: LBRACK RBRACK type pointer: STAR type struct_type: STRUCT "{" (field_decl ";")* "}" interface: INTERFACE "{" (method_spec ";")* "}" function_type: FUNC signature map: MAP "[" key_type "]" type channel: CHAN type | CHAN ARROW type | ARROW CHAN type field_decl: identifier_list type method_spec: method_name signature signature: parameters [ result ] parameters: "(" [ parameter_list ] ")" result: type | "(" type_list ")" key_type: type // для map ключом может быть только comparable тип literal: INT_LIT | FLOAT_LIT | STRING_LIT | RAW_STRING_LIT | RUNE_LIT | BOOL_LIT | NIL ; block: LBRACE stmt_list RBRACE ; stmt_list: | stmt_list stmt ; stmt: expr SEMICOLON | decl_stmt SEMICOLON | block | RETURN expr SEMICOLON | IF expr block | IF expr block ELSE block | FOR block | FOR expr SEMICOLON expr SEMICOLON expr block | FOR IDENT ASSIGN expr SEMICOLON expr SEMICOLON expr block ; %% 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; }