block parse added
parent
57bc30a39c
commit
f5a2854934
|
@ -0,0 +1,22 @@
|
||||||
|
%{
|
||||||
|
#include "test.tab.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int yylineno;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
"{" { return LBRACE; }
|
||||||
|
"}" { return RBRACE; }
|
||||||
|
\n { yylineno++; }
|
||||||
|
[^{}]+ {
|
||||||
|
yylval.str = strdup(yytext);
|
||||||
|
return TEXT;
|
||||||
|
}
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yywrap() {
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern int yylineno;
|
||||||
|
extern char *yytext;
|
||||||
|
|
||||||
|
void yyerror(const char *s) {
|
||||||
|
fprintf(stderr, "\033[91mError at line %i\033[0m", yylineno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
extern int yylex();
|
||||||
|
extern FILE *yyin;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
char *str;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token <str> TEXT
|
||||||
|
%token LBRACE RBRACE
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
block:
|
||||||
|
LBRACE content RBRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
content:
|
||||||
|
| content TEXT { printf("TOKEN ('%s')\n", $2); free($2); }
|
||||||
|
| content block {}
|
||||||
|
;
|
||||||
|
%%
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
yylineno = 1;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
FILE *f = fopen(argv[1], "r");
|
||||||
|
if (!f) {
|
||||||
|
perror("\033[91mFail open file\033[0m");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
yyin = f;
|
||||||
|
}
|
||||||
|
yyparse();
|
||||||
|
return 0;
|
||||||
|
}
|
2
main.py
2
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\cpl'
|
ANALYZERS_DIR = r'C:\Users\user\Desktop\УЧЕБА\6_СЕМ\КОМПИЛЯТОРЫ\flex_bison_test\analyzers\test'
|
||||||
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"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
{ 1 231233
|
||||||
|
{1}{}
|
||||||
|
block1 {
|
||||||
|
block2 { block3 }
|
||||||
|
block4 asjdb asd bajds ba
|
||||||
|
} 126316
|
||||||
|
block5
|
||||||
|
}
|
||||||
|
{
|
||||||
|
123
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
%{
|
||||||
|
#include "test.tab.h"
|
||||||
|
В файле test.l есть строка:
|
||||||
|
c
|
||||||
|
Copy
|
||||||
|
|
||||||
|
#include "test.tab.h"
|
||||||
|
|
||||||
|
// Этот заголовочный файл генерируется Bison'ом и содержит:
|
||||||
|
// 2. Содержимое test.tab.h (примерно)
|
||||||
|
|
||||||
|
// typedef union {
|
||||||
|
// char *str;
|
||||||
|
// } YYSTYPE;
|
||||||
|
// extern YYSTYPE yylval;
|
||||||
|
|
||||||
|
// #define TEXT 258
|
||||||
|
// #define LBRACE 259
|
||||||
|
// #define RBRACE 260
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void yyerror(const char *s);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
"{" { return LBRACE; }
|
||||||
|
"}" { return RBRACE; }
|
||||||
|
[^{}]+ { // [^{}]+ = "один или больше символов, ни один из которых не является { или }"
|
||||||
|
yylval.str = strdup(yytext); // сохранение данных
|
||||||
|
return TEXT; } // возвращение типа токена
|
||||||
|
. { }
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yywrap() {
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void yyerror(const char *s) {
|
||||||
|
fprintf(stderr, "Error: %s\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int yylex();
|
||||||
|
extern FILE *yyin;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// %union задаёт все возможные типы значений, которые могут быть у токенов и нетерминалов.
|
||||||
|
%union {
|
||||||
|
char *str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Этот блок в Bison (%token) определяет терминальные символы (токены),
|
||||||
|
// которые лексический анализатор (Flex) передаёт парсеру (Bison)
|
||||||
|
%token <str> TEXT // <str> — указывает, что этот токен имеет ассоциированное значение типа str (как объявлено в %union).
|
||||||
|
%token LBRACE RBRACE // LBRACE и RBRACE — это токены без ассоциированного значения. Они просто возвращают символы {,}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
/* правило задающее блок - структуру вида {...}, разбирается как
|
||||||
|
открывающая скобка { (LBRACE)
|
||||||
|
затем content (содержимое внутри скобок),
|
||||||
|
затем закрывающая скобка } (RBRACE).*/
|
||||||
|
block:
|
||||||
|
LBRACE content RBRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
/* правило, задающее content
|
||||||
|
если контент пустой, то ничего не происходит
|
||||||
|
если контент это контент и TEXT, то освобождается память выделенная под предыдущий результат
|
||||||
|
еще контент может быть блоком
|
||||||
|
*/
|
||||||
|
content:
|
||||||
|
/* пусто */
|
||||||
|
| content TEXT { printf("TOKEN ('%s')\n", $2); free($2); }
|
||||||
|
| content block
|
||||||
|
;
|
||||||
|
%%
|
||||||
|
|
||||||
|
// 3. Как работает разбор на примере { A { B } C }
|
||||||
|
// Лексер (Flex) разбивает вход на токены:
|
||||||
|
// LBRACE ({), TEXT (A), LBRACE ({), TEXT (B), RBRACE (}), TEXT (C), RBRACE (})
|
||||||
|
// Парсер (Bison) применяет правила:
|
||||||
|
// Видит { → начинает block.
|
||||||
|
// Внутри block ожидается content.
|
||||||
|
// content может быть TEXT (A).
|
||||||
|
// Затем content может включать block ({ B }).
|
||||||
|
// Затем ещё TEXT (C).
|
||||||
|
// Закрывается } → конец block.
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc > 1) {
|
||||||
|
FILE *f = fopen(argv[1], "r");
|
||||||
|
if (!f) {
|
||||||
|
perror("Fail open file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
yyin = f;
|
||||||
|
}
|
||||||
|
yyparse();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue