flex-bison-in-action/analyzers/c_analyzer/c_analyzer.y

137 lines
4.4 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 <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;
}