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 этой директории!!!
|
# *.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"
|
FLEX_EXE_PATH = r"C:\tools\win_flex_bison\win_flex.exe"
|
||||||
BISON_EXE_PATH = r"C:\tools\win_flex_bison\win_bison.exe"
|
BISON_EXE_PATH = r"C:\tools\win_flex_bison\win_bison.exe"
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ def main():
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print("\033[91mErrors:\033[0m")
|
print("\033[91mErrors:\033[0m")
|
||||||
print(e.stderr)
|
print(e.stderr)
|
||||||
return
|
|
||||||
|
|
||||||
# Очистка промежуточных файлов (только если все команды успешны)
|
# Очистка промежуточных файлов (только если все команды успешны)
|
||||||
for path in ['lex.yy.c', f'{analyzer_name}.tab.c', f'{analyzer_name}.tab.h']:
|
for path in ['lex.yy.c', f'{analyzer_name}.tab.c', f'{analyzer_name}.tab.h']:
|
||||||
|
|
Loading…
Reference in New Issue