return, print, operands added
parent
f5a2854934
commit
30c0a403e3
|
@ -0,0 +1,36 @@
|
|||
%{
|
||||
#include "c_analyzer.tab.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int line_number = 1;
|
||||
|
||||
void yyerror(const char *s) {
|
||||
fprintf(stderr, "\033[91mError at line %i: %s near '%s'\033[0m\n", line_number, s, yytext);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
"{" { return LBRACE; }
|
||||
"}" { return RBRACE; }
|
||||
";" { return SEMICOLON; }
|
||||
"=" { return ASSIGN; }
|
||||
"+" { return PLUS; }
|
||||
"-" { return MINUS; }
|
||||
"*" { return MULT; }
|
||||
"/" { return DIV; }
|
||||
"return" { return RET; }
|
||||
"print" { return PRINT; }
|
||||
[0-9]+ { yylval.str = strdup(yytext); return NUMBER; }
|
||||
[a-zA-Z_][a-zA-Z0-9_]* { yylval.str = strdup(yytext); return IDENTIFIER; }
|
||||
[ \t] ;
|
||||
\n { line_number++; }
|
||||
. { yyerror("Invalid character"); }
|
||||
%%
|
||||
|
||||
int yywrap() {
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern char *yytext;
|
||||
|
||||
void yyerror(const char *s);
|
||||
extern int yylex();
|
||||
extern FILE *yyin;
|
||||
%}
|
||||
|
||||
%union {
|
||||
char *str;
|
||||
}
|
||||
|
||||
%token <str> IDENTIFIER NUMBER RET PRINT
|
||||
%token LBRACE RBRACE SEMICOLON ASSIGN PLUS MINUS MULT DIV
|
||||
|
||||
%type <str> expr program statement block
|
||||
|
||||
%%
|
||||
|
||||
// Program - последовательность утверждений
|
||||
program:
|
||||
| program statement
|
||||
;
|
||||
|
||||
// Утверждение - либо блок {...}, либо выражение с ; в конце
|
||||
statement:
|
||||
expr SEMICOLON
|
||||
| block
|
||||
;
|
||||
|
||||
// Блок - { program }, т.е. это последовательность утверждений и она находится в скобках { }
|
||||
block:
|
||||
LBRACE program RBRACE
|
||||
;
|
||||
|
||||
// Возможные выражения
|
||||
expr:
|
||||
RET expr // выражение вида return expr
|
||||
| PRINT expr // выражение вида print expr
|
||||
| IDENTIFIER ASSIGN expr // выражения вида a=expr
|
||||
| expr PLUS expr // выражения вида expr+expr
|
||||
| expr MINUS expr // выражения вида expr-expr
|
||||
| expr MULT expr // выражения вида expr*expr
|
||||
| expr DIV expr // выражения вида expr/expr
|
||||
| IDENTIFIER { printf("IDENTIFIER = %s\n", $1); free($1); }
|
||||
| NUMBER { printf("NUMBER = %s\n", $1); free($1); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
FILE *f = fopen(argv[1], "r");
|
||||
if (!f) {
|
||||
perror("\033[91mFail open file\033[0m");
|
||||
return 1;
|
||||
}
|
||||
yyin = f;
|
||||
}
|
||||
yyparse();
|
||||
printf("\033[92mSuccess parsed!\033[0m");
|
||||
return 0;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
%{
|
||||
#include "cpl.tab.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int yylineno;
|
||||
char *last_lexeme; // Глобальная переменная для хранения текущей лексемы
|
||||
void yyerror(const char *s);
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
|
||||
DIGIT [0-9]
|
||||
ID [a-zA-Z][a-zA-Z0-9_]*
|
||||
WS [ \t]+
|
||||
|
||||
%%
|
||||
|
||||
"if" { last_lexeme = strdup("if"); return IF; }
|
||||
"else" { last_lexeme = strdup("else"); return ELSE; }
|
||||
"while" { last_lexeme = strdup("while"); return WHILE; }
|
||||
"return" { last_lexeme = strdup("return"); return RETURN; }
|
||||
"print" { last_lexeme = strdup("print"); return PRINT; }
|
||||
"&&" { last_lexeme = strdup("&&"); return AND; }
|
||||
"||" { last_lexeme = strdup("||"); return OR; }
|
||||
"!" { last_lexeme = strdup("!"); return NOT; }
|
||||
">=" { last_lexeme = strdup(">="); return GE; }
|
||||
"<=" { last_lexeme = strdup("<="); return LE; }
|
||||
"==" { last_lexeme = strdup("=="); return EQ; }
|
||||
"!=" { last_lexeme = strdup("!="); return NE; }
|
||||
">" { last_lexeme = strdup(">"); return '>'; }
|
||||
"<" { last_lexeme = strdup("<"); return '<'; }
|
||||
"+" { last_lexeme = strdup("+"); return '+'; }
|
||||
"-" { last_lexeme = strdup("-"); return '-'; }
|
||||
"*" { last_lexeme = strdup("*"); return '*'; }
|
||||
"/" { last_lexeme = strdup("/"); return '/'; }
|
||||
"%" { last_lexeme = strdup("%"); return '%'; }
|
||||
"(" { last_lexeme = strdup("("); return '('; }
|
||||
")" { last_lexeme = strdup(")"); return ')'; }
|
||||
";" { last_lexeme = strdup(";"); return ';'; }
|
||||
"=" { last_lexeme = strdup("="); return '='; }
|
||||
"{" { last_lexeme = strdup("{"); return '{'; }
|
||||
"}" { last_lexeme = strdup("}"); return '}'; }
|
||||
|
||||
{DIGIT}+ { last_lexeme = strdup(yytext); yylval.num = atoi(yytext); return NUMBER; }
|
||||
{ID} { last_lexeme = strdup(yytext); yylval.str = strdup(yytext); return IDENTIFIER; }
|
||||
{WS} /* skip whitespace */
|
||||
\n { yylineno++; }
|
||||
. { last_lexeme = strdup(yytext); yyerror("invalid character"); }
|
||||
|
||||
%%
|
|
@ -1,106 +0,0 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int yylineno;
|
||||
extern char *last_lexeme;
|
||||
void yyerror(const char *s);
|
||||
int yylex();
|
||||
|
||||
extern FILE *yyin;
|
||||
%}
|
||||
|
||||
%union {
|
||||
int num;
|
||||
char *str;
|
||||
}
|
||||
|
||||
%token <num> NUMBER
|
||||
%token <str> IDENTIFIER
|
||||
%token IF ELSE WHILE RETURN PRINT
|
||||
%token AND OR NOT GE LE EQ NE
|
||||
|
||||
%right '='
|
||||
%left OR
|
||||
%left AND
|
||||
%left EQ NE
|
||||
%left '<' '>' GE LE
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%right NOT UMINUS
|
||||
|
||||
%%
|
||||
|
||||
program:
|
||||
| program statement
|
||||
;
|
||||
|
||||
statement:
|
||||
expr ';' semicolons
|
||||
| IF '(' expr ')' statement ELSE statement
|
||||
| IF '(' expr ')' statement
|
||||
| WHILE '(' expr ')' statement
|
||||
| RETURN expr ';' semicolons
|
||||
| PRINT expr ';' semicolons
|
||||
| '{' program '}'
|
||||
;
|
||||
|
||||
semicolons:
|
||||
/* empty */
|
||||
| semicolons ';'
|
||||
;
|
||||
|
||||
expr:
|
||||
NUMBER
|
||||
| IDENTIFIER
|
||||
| IDENTIFIER '=' expr
|
||||
| expr '+' expr
|
||||
| expr '-' expr
|
||||
| expr '*' expr
|
||||
| expr '/' expr
|
||||
| expr '%' expr
|
||||
| expr AND expr
|
||||
| expr OR expr
|
||||
| NOT expr
|
||||
| '-' expr %prec UMINUS
|
||||
| '+' expr
|
||||
| expr '>' expr
|
||||
| expr '<' expr
|
||||
| expr GE expr
|
||||
| expr LE expr
|
||||
| expr EQ expr
|
||||
| expr NE expr
|
||||
| '(' expr ')'
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void yyerror(const char *s) {
|
||||
if (last_lexeme) {
|
||||
fprintf(stderr, "\033[91mError at line %d: %s (near '%s')\n\033[0m", yylineno, s, last_lexeme);
|
||||
} else {
|
||||
fprintf(stderr, "\033[91mError at line %d: %s\n\033[0m", yylineno, s);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "\033[91mUsage: %s <input_file>\n\033[0m", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *input = fopen(argv[1], "r");
|
||||
if (!input) {
|
||||
perror("\033[91mError opening file"); printf("\033[0m");
|
||||
return 1;
|
||||
}
|
||||
|
||||
yyin = input;
|
||||
yyparse();
|
||||
fclose(input);
|
||||
|
||||
printf("\033[92mParsing completed successfully!\033[0m\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
PIMPUMPUMpam = 5;
|
||||
per__emennaya = 3;
|
||||
|
||||
PIMPUMPUMpam = PIMPUMPUMpam + (per__emennaya - 1);
|
||||
|
||||
x = 10+1-2;;;;
|
||||
y = ++-+20;
|
||||
|
||||
if (++---x > y) {
|
||||
print x * !x;
|
||||
} else {
|
||||
print y;
|
||||
}
|
||||
|
||||
while (x > 123 || (x < 1 || x > 10) && x == 5) {
|
||||
{x = x + 1;}
|
||||
x = x % 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
x = 2 + 1;
|
||||
x = z + 3 + 5;
|
||||
{
|
||||
x = 10;
|
||||
y = x + 5;
|
||||
{
|
||||
z = y * 2 / 5 * 3;
|
||||
}
|
||||
}
|
||||
print x;
|
||||
return x / 2 + 5;
|
||||
}
|
3
main.py
3
main.py
|
@ -3,7 +3,7 @@ import subprocess
|
|||
|
||||
# ЭТИ ПУТИ НАДО ЗАДАТЬ ВРУЧНУЮ
|
||||
# *.l и *.y файлы из директории ANALYZERS_DIR ДОЛЖНЫ НАЗЫВАТЬСЯ как basename этой директории!!!
|
||||
ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\flex_bison_test\analyzers\test'
|
||||
ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\flex_bison_test\analyzers\c_analyzer'
|
||||
FLEX_EXE_PATH = r"C:\tools\win_flex_bison\win_flex.exe"
|
||||
BISON_EXE_PATH = r"C:\tools\win_flex_bison\win_bison.exe"
|
||||
|
||||
|
@ -35,7 +35,6 @@ def main():
|
|||
except subprocess.CalledProcessError as e:
|
||||
print("\033[91mErrors:\033[0m")
|
||||
print(e.stderr)
|
||||
return
|
||||
|
||||
# Очистка промежуточных файлов (только если все команды успешны)
|
||||
for path in ['lex.yy.c', f'{analyzer_name}.tab.c', f'{analyzer_name}.tab.h']:
|
||||
|
|
Loading…
Reference in New Issue