go-analyzer/analyzers/test/test.y

551 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

%{
#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;
}