134 lines
4.3 KiB
Plaintext
134 lines
4.3 KiB
Plaintext
%{
|
||
#include <stdio.h>
|
||
#include <stdbool.h>
|
||
|
||
void yyerror(const char *s);
|
||
extern int yylex();
|
||
extern char *yytext;
|
||
extern FILE *yyin;
|
||
|
||
bool debug = false; // debug mode
|
||
|
||
%}
|
||
|
||
%union {
|
||
char *str;
|
||
}
|
||
|
||
%token <str> IDENTIFIER NUMBER
|
||
%token LBRACE RBRACE LPAREN RPAREN SEMICOLON ASSIGN PLUS MINUS MULT DIV MOD RET PRINT WHILE IF ELSE AND OR NOT
|
||
%token FUNC COMMA
|
||
|
||
%type <str> expr program statement block func_decl param_list params
|
||
|
||
%left OR
|
||
%left AND
|
||
%right NOT
|
||
%left PLUS MINUS
|
||
%left MULT DIV MOD
|
||
%right UNARY
|
||
|
||
%%
|
||
|
||
// Program - последовательность утверждений
|
||
program:
|
||
| program statement
|
||
;
|
||
|
||
// Утверждение - либо блок {...}, либо выражение с ; в конце,
|
||
// либо цикл while, либо конструкиця if, либо конструкций if-else
|
||
statement:
|
||
{ if (debug) printf("\033[93mANOTHER STATEMENT\n\033[0m"); } expr SEMICOLON
|
||
|
||
| { if (debug) printf("\033[93mNEW BLOCK\n\033[0m"); } block
|
||
|
||
| WHILE { if (debug) printf("\033[1;34mWHILE LOOP DETECTED\033[0m\n"); }
|
||
LPAREN expr RPAREN
|
||
{ if (debug) printf("\033[1;34mWHILE BODY STARTS\033[0m\n"); }
|
||
block
|
||
{ if (debug) printf("\033[1;34mWHILE LOOP ENDED\033[0m\n"); }
|
||
|
||
| IF LPAREN expr RPAREN block
|
||
{ if (debug) printf("\033[1;34mIF BLOCK ENDED\033[0m\n"); }
|
||
| IF LPAREN expr RPAREN block
|
||
{ if (debug) printf("\033[1;34mIF BLOCK ENDED\033[0m\n"); }
|
||
ELSE
|
||
{ if (debug) printf("\033[1;34mELSE BLOCK STARTED\033[0m\n"); }
|
||
block
|
||
{ if (debug) printf("\033[1;34mELSE BLOCK ENDED\033[0m\n"); }
|
||
|
||
| func_decl
|
||
;
|
||
|
||
func_decl:
|
||
FUNC IDENTIFIER { if (debug) printf("\033[1;35mFUNCTION: %s\033[0m\n", $2); free($2); }
|
||
LPAREN param_list RPAREN
|
||
{ if (debug) printf("\033[1;35mFUNCTION PARAMS END\033[0m\n"); }
|
||
block
|
||
{ if (debug) printf("\033[1;35mFUNCTION END\033[0m\n"); }
|
||
;
|
||
|
||
param_list:
|
||
| params
|
||
;
|
||
|
||
params:
|
||
IDENTIFIER { if (debug) printf("\033[1;35mPARAM: %s\033[0m\n", $1); free($1); }
|
||
| params COMMA IDENTIFIER { if (debug) printf("\033[1;35mPARAM: %s\033[0m\n", $3); free($3); }
|
||
;
|
||
|
||
// Блок - { program }, т.е. это последовательность утверждений и она находится в скобках { }
|
||
block:
|
||
LBRACE program RBRACE
|
||
;
|
||
|
||
// Возможные выражения
|
||
expr:
|
||
RET { if (debug) printf("RET\n") } expr // выражение вида return expr
|
||
| PLUS { if (debug) printf("UNARY PLUS\n"); } expr %prec UNARY // выражение вида +expr
|
||
| MINUS { if (debug) printf("UNARY MINUS\n"); } expr %prec UNARY // выражение вида -expr
|
||
| PRINT { if (debug) printf("PRINT\n") } expr // выражение вида print expr
|
||
| IDENTIFIER { if (debug) printf("IDENTIFIER(%s)\n", $1); free($1); } // выражения вида a=expr
|
||
ASSIGN { if (debug) printf("ASSIGN\n"); } expr
|
||
| expr PLUS { if (debug) printf("PLUS\n") } expr // выражения вида expr+expr
|
||
| expr MINUS { if (debug) printf("MINUS\n") } expr // выражения вида expr-expr
|
||
| expr MULT { if (debug) printf("MULT\n") } expr // выражения вида expr*expr
|
||
| expr DIV { if (debug) printf("DIV\n") } expr // выражения вида expr/expr
|
||
| expr MOD { if (debug) printf("MOD\n") } expr // выражения вида expr%expr
|
||
| LPAREN { if (debug) printf("LPAREN\n") } expr RPAREN { if (debug) printf("RPAREN\n") } // выражения вида (expr)
|
||
| expr OR expr
|
||
| expr AND expr
|
||
| NOT expr
|
||
| IDENTIFIER { if (debug) printf("IDENTIFIER(%s)\n", $1); free($1); }
|
||
| NUMBER { if (debug) printf("NUMBER(%s)\n", $1); free($1); }
|
||
;
|
||
|
||
%%
|
||
|
||
int main(int argc, char **argv) {
|
||
if (argc > 1) {
|
||
char* path;
|
||
|
||
// debug mode
|
||
if (argc > 2) {
|
||
path = argv[2];
|
||
if (!strcmp(argv[1], "-d")) {
|
||
debug = true;
|
||
}
|
||
} else {
|
||
path = argv[1];
|
||
}
|
||
|
||
// default mode
|
||
FILE *f = fopen(path, "r");
|
||
if (!f) {
|
||
perror("\033[91mFail open file\033[0m");
|
||
return 1;
|
||
}
|
||
yyin = f;
|
||
|
||
}
|
||
yyparse();
|
||
printf("\033[92m\nGood code\033[0m");
|
||
return 0;
|
||
} |