551 lines
15 KiB
Plaintext
551 lines
15 KiB
Plaintext
%{
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <math.h>
|
||
|
||
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 INTERFACE
|
||
%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 <str> 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:
|
||
| method_declaration
|
||
| 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
|
||
|
||
interface_types:
|
||
INTERFACE {printf("INTERFACE\n"); } LBRACE interface_declarate_field_list RBRACE
|
||
|
||
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 { }
|
||
| IDENTIFIER
|
||
| chan_types
|
||
| map_types
|
||
| slice_types
|
||
| arr_types { }
|
||
| interface_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
|
||
|
||
// Анонимная функция
|
||
anon_func:
|
||
FUNC LPAREN arg_list RPAREN return_type block
|
||
{ printf("\033[1;35mANONYMOUS FUNC\n\033[0m"); }
|
||
;
|
||
|
||
// Литерал функции (если нужно для других правил)
|
||
func_literal: anon_func;
|
||
|
||
// Вызов функции
|
||
func_call:
|
||
any_identifier LPAREN math_expr_or_literals_list_or_empty RPAREN
|
||
| anon_func LPAREN math_expr_or_literals_list_or_empty RPAREN
|
||
| anon_func // Позволяет использовать func(){} как значение
|
||
;
|
||
|
||
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); }
|
||
;
|
||
|
||
// Объявление метода
|
||
method_declaration:
|
||
FUNC LPAREN IDENTIFIER type RPAREN IDENTIFIER
|
||
{ printf("\033[1;35mMETHOD DECL: %s\n\033[0m", $6); }
|
||
LPAREN arg_list RPAREN return_type block
|
||
{ printf("\033[1;35mEND METHOD\n\033[0m"); }
|
||
;
|
||
|
||
|
||
// 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
|
||
|
||
// interface
|
||
|
||
interface_field:
|
||
IDENTIFIER LPAREN arg_list RPAREN {printf("ret type interface\n");} return_type
|
||
|
||
interface_declarate_field_list:
|
||
| interface_field SEMICOLON
|
||
| interface_declarate_field_list interface_field SEMICOLON
|
||
;
|
||
|
||
// struct
|
||
declarate_field_list:
|
||
| arg_declaration SEMICOLON
|
||
| IDENTIFIER SEMICOLON
|
||
| declarate_field_list arg_declaration SEMICOLON
|
||
| declarate_field_list IDENTIFIER SEMICOLON
|
||
;
|
||
|
||
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;
|
||
} |