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