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
|
||||
|
||||
# ЭТИ ПУТИ НАДО ЗАДАТЬ ВРУЧНУЮ
|
||||
# АНАЛИЗАТОРЫ .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()
|
Loading…
Reference in New Issue