68 lines
2.6 KiB
Plaintext
68 lines
2.6 KiB
Plaintext
%{
|
||
#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;
|
||
} |