107 lines
3.6 KiB
Plaintext
107 lines
3.6 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
|
||
|
||
%type <str> expr program statement block
|
||
|
||
%left PLUS MINUS
|
||
%left MULT DIV MOD
|
||
%right UNARY
|
||
|
||
%%
|
||
|
||
// Program - последовательность утверждений
|
||
program:
|
||
| program statement
|
||
;
|
||
|
||
// Утверждение - либо блок {...}, либо выражение с ; в конце, либо цикл while, либо конструкций if-else
|
||
statement:
|
||
{ if (debug) printf("\033[93mANOTHER STATEMENT\n\033[0m"); } expr SEMICOLON
|
||
|
||
| 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"); }
|
||
;
|
||
|
||
// Блок - { 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)
|
||
| 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;
|
||
} |