Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
#1

BISON, освобождение памяти при синтаксической ошибке. - C++

04.05.2011, 16:14. Просмотров 1008. Ответов 2

Здравствуйте. При работе с BISON, как освободить память выделенную под возвращаемые продукциями "объекты" в случае синтаксической ошибки? Все мануалы облазил (штук 5-6) не нашел ничего кроме описания зачем нужен токен error и yyerrok и все такое.
Вот составил пример, чтобы вопрос был ясен и было на чем показать. В нем надо как-то, в продукции line строка 36, освободить память, занятую деревом, если произошла ошибка разбора.
Код
/* Синтаксический анализатор для простых арифметических выражений.  */
%{
#include <stdio.h>
#include <stdlib.h>
#define YYDEBUG 1
static int yylex(void);
static int yyerror(char*);

float variable;

typedef struct tree {
  struct tree *left;
  struct tree *right;
  float val;
  int op;
} tree;
#define YYSTYPE tree*
tree *make_tree(tree *l, tree *r, float v, int o);
void print_tree(tree *t);
void free_tree(tree *t);
%}

%token NUM
%left '+' '-'
%left '/' '*'
%left UNARY
%left '('

%%
input:
    line                 { print_tree($1); free_tree($1); }
  | input line           { print_tree($2); free_tree($2); }
  ;
line:
    exp '\n'             { $$ = $1; }
  | error '\n'           { /* Тут надо освободить память. */ }
  ;
exp:
    prim
  | exp '+' exp          { $$ = make_tree($1, $3, 0, '+'); }
  | exp '-' exp          { $$ = make_tree($1, $3, 0, '-'); }
  | exp '*' exp          { $$ = make_tree($1, $3, 0, '*'); }
  | exp '/' exp          { $$ = make_tree($1, $3, 0, '/'); }
  ;
prim:
    '(' exp ')'          { $$ = $2; }
  | '-' prim %prec UNARY { $$ = make_tree($2, NULL, 0, 'u'); }
  | NUM                  { $$ = make_tree(NULL, NULL, variable, 'v'); }
  ;
%%
tree *make_tree(tree *l, tree *r, float v, int o)
{
  tree* t = (tree*)malloc(sizeof(tree));
  t->left = l;
  t->right = r;
  t->val = v;
  t->op = o;
  return t;
}
void print_tree(tree *t)
{
  static n = 0;
  if (t != NULL) {
    int i;
    for (i = 0; i < n; i++)
      printf(" ");
    switch(t->op) {
    case 'u': printf("- unary\n"); break;
    case 'v': printf("%f\n", t->val); break;
    default:
      printf("%c\n", t->op);
    }
    n++;
    print_tree(t->left);
    print_tree(t->right);
    n--;
  }
}
void free_tree(tree *t)
{
  if (t != NULL) {
    free_tree(t->left);
    free_tree(t->right);
    free(t);
  }
}
int yylex()
{
  int c;
  while (!feof(stdin) && (c = getc(stdin)) == ' ');
  if (feof(stdin)) return 0;
  switch (c) {
  case '+':
  case '-':
  case '*':
  case '/':
  case '(':
  case ')':
  case '\n':
        return c;
  default:
    break;
  }
  if (isdigit(c)) {
    ungetc(c, stdin);
    fscanf(stdin, "%f", &variable);
    return NUM;
  }
}

int yyerror(char *s)
{
  fprintf(stderr, "%s.\n", s);
  return 1;
}
int main()
{
  /* yydebug = 1; */
  return yyparse();
}
Единственная моя идея: сделать стек с указателями на узлы дерева, и при появлении токена error все эти указатели освобождать. Но это плохой вариант, слишком много лишнего кода. Пример выше - всего лишь пример, есть "реальная программа" для построения синтаксического дерева для исходника на C, и там время работы критично, мне кажется... Нет ли у BISON какого-нибудь "родного" способа освободить память? Собственным стеком бизона yyvs пользоваться не получается ошибка сегментирования или ноль реакции на print_tree и free_tree.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.05.2011, 16:14     BISON, освобождение памяти при синтаксической ошибке.
Посмотрите здесь:

C++ Освобождение памяти
C++ Builder Освобождение памяти
Освобождение памяти C++
с++ Освобождение памяти C++
C++ Освобождение памяти
C++ Builder Корректное освобождение памяти при принудительном завершении потока TThread
C++ Освобождение памяти в c++
Освобождение памяти C++
C++ Освобождение памяти
C++ Освобождение памяти при удалении структуры
C++ Освобождение выделенной памяти при закрытии программы
Правильное освобождение памяти при std::vector C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
dev001
36 / 36 / 3
Регистрация: 13.05.2010
Сообщений: 70
09.12.2011, 16:35     BISON, освобождение памяти при синтаксической ошибке. #2
в функцию yyparse можно передать параметр при вызове.
и что если вместо malloc использовать обвертку, в которой будет вызываться память использую контролирующий объект

т.е

C
1
yyparse( NULL, MyObject );
и
C
1
2
3
4
5
6
7
8
9
tree *make_tree(SomeObject *MyObject, tree *l, tree *r, float v, int o)
{
  tree* t = (tree*)tree_alloc(MyObject->tree_heap, sizeof(tree));
  t->left = l;
  t->right = r;
  t->val = v;
  t->op = o;
  return t;
}

да и не забыть объявить #define YYPARSE_PARAM dummy, SomeObject *MyObject
и собрать с ключом %pure_parser (может и без него)

Тогда ваш общий объект будет доступен как доп параметр во все функции.
Qazan
211 / 59 / 9
Регистрация: 30.04.2013
Сообщений: 797
Записей в блоге: 10
04.03.2016, 16:34     BISON, освобождение памяти при синтаксической ошибке. #3
Aye Aye, лучше поздно, чем никогда

сделайте в вашей структуре метод delete , который в себе бы вызывал методы delete потомков.
C
1
2
3
4
5
6
7
8
9
10
11
struct A {
  A* left;
  A *right;
 
  void delete {
     left->delete();
     right->delete();
     free(left);
     free(right);
  }
};
Yandex
Объявления
04.03.2016, 16:34     BISON, освобождение памяти при синтаксической ошибке.
Ответ Создать тему
Опции темы

Текущее время: 17:00. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru