381 lines
9.9 KiB
Plaintext
381 lines
9.9 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 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
|
|
%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 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:
|
|
| 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"); }
|
|
| 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); }
|
|
;
|
|
|
|
block:
|
|
LBRACE statements_list RBRACE
|
|
;
|
|
|
|
any_identifier:
|
|
IDENTIFIER
|
|
| WITH_DOT_IDENTIFIER
|
|
//
|
|
|
|
// lists
|
|
statements_list:
|
|
| statements_list statement
|
|
| statements_list block
|
|
| statements_list expr SEMICOLON
|
|
;
|
|
|
|
identifiers_list:
|
|
IDENTIFIER { }
|
|
| identifiers_list COMMA 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
|
|
|
|
//
|
|
|
|
// condition
|
|
condition:
|
|
IF var_multiple_short_declaration 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 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:
|
|
IDENTIFIER ASSIGN math_expr { }
|
|
| 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
|
|
|
|
| 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"); }
|
|
| IDENTIFIER { printf("IDENTIFIER: %s\n", $1); }
|
|
| IDENTIFIER INC { printf("POST-INCREMENT: %s++\n", $1); }
|
|
| IDENTIFIER DEC { printf("POST-DECREMENT: %s--\n", $1); }
|
|
| func_call { printf("FUNCTION CALL IN EXPR\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
|
|
|
|
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 RPAREN return_type
|
|
|
|
type:
|
|
int_types { }
|
|
| func_types { }
|
|
| string_types { }
|
|
| float_types { }
|
|
| complex_types { }
|
|
| bool_types { }
|
|
;
|
|
|
|
//
|
|
|
|
|
|
// literals
|
|
literal:
|
|
STRING_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
|
|
;
|
|
//
|
|
|
|
// functions
|
|
|
|
func_literal:
|
|
FUNC
|
|
{ printf("\033[1;35mHELLO, ANON FUNC\n\033[0m"); }
|
|
LPAREN arg_list RPAREN return_type block
|
|
{ printf("\033[1;35mBY, ANON FUNC\n\n\033[0m"); }
|
|
|
|
func_call:
|
|
any_identifier LPAREN math_expr_or_literals_list_or_empty RPAREN
|
|
|
|
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 { }
|
|
;
|
|
|
|
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_multiple_short_declaration:
|
|
identifiers_list SHORT_DECLARATION math_expr_or_literals_list
|
|
|
|
var_declaration:
|
|
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;
|
|
} |