return, print, operands added

master
serr 2025-04-01 17:01:40 +03:00
parent f5a2854934
commit 30c0a403e3
7 changed files with 117 additions and 182 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"); }
%%

View File

@ -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;
}

View File

@ -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;
}

13
code.txt Normal file
View File

@ -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;
}

View File

@ -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']: