c-like lang analizer start coding

master
serr 2025-03-30 19:38:08 +03:00
parent 381805e980
commit 7dbb3f0125
4 changed files with 178 additions and 22 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
*.exe
*.exe
*test*

51
analyzers/cpl/cpl.l Normal file
View File

@ -0,0 +1,51 @@
%{
#include "cpl.tab.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylineno;
void yyerror(const char *s);
%}
%option noyywrap
DIGIT [0-9]
ID [a-zA-Z][a-zA-Z0-9_]*
WS [ \t]+
%%
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"return" { return RETURN; }
"print" { return PRINT; }
"&&" { return AND; }
"||" { return OR; }
"!" { return NOT; }
">=" { return GE; }
"<=" { return LE; }
"==" { return EQ; }
"!=" { return NE; }
">" { return '>'; }
"<" { return '<'; }
"+" { return '+'; }
"-" { return '-'; }
"*" { return '*'; }
"/" { return '/'; }
"%" { return '%'; }
"(" { return '('; }
")" { return ')'; }
";" { return ';'; }
"=" { return '='; }
"{" { return '{'; }
"}" { return '}'; }
{DIGIT}+ { yylval.num = atoi(yytext); return NUMBER; }
{ID} { yylval.str = strdup(yytext); return IDENTIFIER; }
{WS} /* skip whitespace */
\n { yylineno++; }
. { yyerror("Invalid character"); }
%%

99
analyzers/cpl/cpl.y Normal file
View File

@ -0,0 +1,99 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylineno;
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
%nonassoc '>' '<' GE LE EQ NE
%left OR
%left AND
%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) {
fprintf(stderr, "Error at line %d: %s\n", yylineno, s);
exit(1);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <input_file>\n", argv[0]);
return 1;
}
FILE *input = fopen(argv[1], "r");
if (!input) {
perror("Error opening file");
return 1;
}
yyin = input;
yyparse();
fclose(input);
printf("Parsing completed successfully!\n");
return 0;
}

47
main.py
View File

@ -2,42 +2,47 @@ import os
import subprocess
# ЭТИ ПУТИ НАДО ЗАДАТЬ ВРУЧНУЮ
# АНАЛИЗАТОРЫ .l, .y ДОЛЖНЫ ИМЕТЬ ОДИНАКОВЫЙ basename
# И ЛЕЖАТЬ В ПАПАКЕ С ИМЕНЕМ basename
ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\flex_bison_test\analyzers\calc'
ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\flex_bison_test\analyzers\cpl'
FLEX_EXE_PATH = r"C:\tools\win_flex_bison\win_flex.exe"
BISON_EXE_PATH = r"C:\tools\win_flex_bison\win_bison.exe"
#
def main():
# Подготовка путей
analyzer_name = os.path.basename(ANALYZERS_DIR)
lexical_analyzer_path = fr"{ANALYZERS_DIR}\{analyzer_name}.l"
syntaxic_analyzer_path = fr"{ANALYZERS_DIR}\{analyzer_name}.y"
#
# Подготовка списка команд
cmds = [f'{FLEX_EXE_PATH} {lexical_analyzer_path}',
f'{BISON_EXE_PATH} -d {syntaxic_analyzer_path}',
f'gcc lex.yy.c {analyzer_name}.tab.c -o {analyzer_name}.exe']
#
cmds = [
f'{FLEX_EXE_PATH} {lexical_analyzer_path}',
f'{BISON_EXE_PATH} -d {syntaxic_analyzer_path}',
f'gcc lex.yy.c {analyzer_name}.tab.c -o {analyzer_name}.exe'
]
# Исполнение команд
# Исполнение команд с выводом
for cmd in cmds:
print(f"\n\033[1mExecuting: {cmd}\033[0m")
try:
subprocess.run(cmd, capture_output=True, check=True)
print(f'\033[92mSuccess execute \033[0m{cmd}!')
result = subprocess.run(
cmd,
shell=True,
check=True,
text=True,
stderr=subprocess.PIPE
)
print(f'\033[92mSuccessfully executed!\033[0m')
except subprocess.CalledProcessError as e:
print(f"\033[91mError: {e}\033[0m")
#
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']:
os.remove(path)
#
# Очистка промежуточных файлов (только если все команды успешны)
for path in ['lex.yy.c', f'{analyzer_name}.tab.c', f'{analyzer_name}.tab.h']:
try:
os.remove(path)
print(f"Removed: {path}")
except FileNotFoundError:
pass
if __name__ == "__main__":
main()