LINUX.ORG.RU

bison ошибка на этапе выполнения

 ,


0

2

Всем привет!

Сейчас пишу синтаксический анализатор, который по очереди принимает сначала строку (путь к директории), а потом логическое выражение для фильтрации файлов в этой директории, и так до бесконечности. Сам парсер логического выражения практически написал (если кто-то подскажет, как в нем сделать приоритет у оператора AND выше, чем у OR, буду крайне признателен), но когда решил туда добавить первую часть (захват строки директории), то всё пошло крахом - во время выполнения bison-овский код не распознает строку как строку. И у меня уже замылились глаза, искать почему так. В общем, вот сам файл.

При выполнении выдает следующее

./finder
Path in quotes: 
error: syntax error
Path in quotes: 
Path in quotes: 
Path in quotes: "jom"
Path in quotes:

То есть в первый раз при нажатии просто Enter выдает синтаксическую ошибку, а при наборе строки выдает ничего.

★★

если кто-то подскажет, как в нем сделать приоритет у оператора AND выше, чем у OR, буду крайне признателен

%left OR

%left AND

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Проверю, как соберется... Пока что среди ошибок есть еще 4 конфликта сдвига/вывода...

aido ★★
() автор топика
Ответ на: комментарий от aido

А как мне тогда сделать чередование

Как и в обычном языке - синтаксически, первое «слово» или что там у вас - путь, второе - маска. На одной строке или на разных — по вашему желанию. Если пустая строка ничего не обозначает, значить и париться в синтаксическом анализаторе не стоит, если означает, значит это отдельный токен в языке, если означает ошибку, то конкретно правило с ошибкой и рисуйте.

vodz ★★★★★
()
Ответ на: комментарий от aido

У меня вообще вопрос назрел: а зачем реализовывать этот цикл как часть грамматики, если он не часть грамматики по сути? Не логичнее ли читать ввод построчно и отдавать парсеру строку за раз?

xaizek ★★★★★
()

#!/usr/bin/bash -x

и посмотри трассировку.

anonymous
()
Ответ на: комментарий от aido

У меня у самого проблемы сообразить как этот код должен работать интерактивно. Вообще есть функция yy_scan_bytes, но чтобы её можно было использовать надо flex заставить генерировать заголовочный файл.

xaizek ★★★★★
()
Ответ на: комментарий от aido

Как во flex записать «s/^$\n//»?

flex ничего не удаляет, но regex там вполне стандартен. Вы какой вариант выбрали? Конец строки - такой же пробельный символ или синтаксически значимый типа точки с запятой в сишке? Если пробельный - то туда к пробелам и засуньте по аналогии, если нет - то тогда синтаксически и надо обрабатывать.

vodz ★★★★★
()
Ответ на: комментарий от aido

Проглотить пустые строчки flex:

([ \t\r]*[\n])+ {return NEWLINE;}

Не понял как в компиле-тайм считается and, например: "(size>N1) and (attribute==N2)" (операнды известны только в ран-тайме).

anonymous
()
Ответ на: комментарий от aido

А тут что считается?

		| filter AND entry_point
		{
			$$=(*$1) && $3;
		} 

anonymous
()
Ответ на: комментарий от xaizek

Во! нашел источник ошибки при использовании enter - у меня где-то криво работает libreadline и по ходу выдает мусор на выход. Если в finder.l сейчас закомментировать строчку USE_READLINE, то правила заработают.

Оно в буфер строчку нормально складывает, а потом какая-то магия творится и строчка теряется.

aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от aido

Хм, я пытался там исправить что-то связанное с помещением '\n', но толку не было, а вот отключить readline не догадался.

В репозиторий неплохо бы добавить пример использования, хоть попробовать как оно вообще должно работать.

У меня кстати без таких изменений не собирается (в первом чанке добавляется -lcurses):

diff --git a/Makefile b/Makefile
index e815293..85548cb 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ predicate_abstract_factory.o: predicate_abstract_factory.hpp predicate_abstract_
 .       g++ -std=c++11 predicate_abstract_factory.cpp -c -o predicate_abstract_factory.o
 
 finder: finder.o lexer.o predicate_abstract_factory.o 
-.       g++ -ggdb lexer.o finder.tab.o predicate_abstract_factory.o -lboost_system -lboost_filesystem -lfl -lreadline -o finder
+.       g++ -ggdb lexer.o finder.tab.o predicate_abstract_factory.o -lboost_system -lboost_filesystem -lfl -lreadline -lcurses -o finder
 
 clean:
 .       rm finder finder.tab.c lex.yy.c finder.tab.h
diff --git a/finder.l b/finder.l
index 94ea91b..2cea0ab 100644
--- a/finder.l
+++ b/finder.l
@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdint.h>
 
-#define YY_DECL int yylex()
+#define YY_DECL extern "C" int yylex()
 
 #include "finder.tab.hpp"
 
diff --git a/finder.y b/finder.y
index 70330a5..7766fd1 100644
--- a/finder.y
+++ b/finder.y
@@ -19,7 +19,7 @@
 #include <iostream>
 #include "predicate_abstract_factory.hpp"
 using namespace std;
-extern int yylex();
+extern "C" int yylex();
 extern int yyparse();
 extern FILE* yyin;

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Частично поправил (extern «C»). Есть идеи, как прикрутить libreadline?

Помнится, года 2 назад flex не умел генерить код, который адекватно скомпилируется С++, поэтому мне тогда приходилось идти на различные развязки C/C++ - компилировать флексовский код gcc, а остальное - g++. Но я не помню, из-за чего конкретно такое понадобилось. Может и связано с readline косвенно...

aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от aido

Будешь собирать - в конфиге включи дефайн. И теперь собирается через cmake

aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от aido

А что за система? У меня без ncurses собирается прекрасно.

Slackware, libreadline требует curses:

/usr/lib64/gcc/x86_64-slackware-linux/5.3.0/../../../../lib64/libreadline.so: undefined reference to `tgetnum'
...

Есть идеи, как прикрутить libreadline?

Это в заголовках readline :)

#ifndef NEWLINE
#define NEWLINE '\n'
#endif

Отсюда часть проблем. Надо переименовать токен или использовать '\n'.

Реализация без других проблем:

	inline int readline_input(char* buf, const size_t max_size)
	{
		static char* residue_string = nullptr;
		static char* input_line = nullptr;

		if (residue_string == nullptr)
		{
			input_line = readline(begin_line);
			residue_string = input_line;
		}

		int n;
		for (n = 0; n < max_size && residue_string[n] != '\0'; ++n)
		{
			buf[n] = residue_string[n];
		}

		if (n < max_size)
		{
			buf[n++] = '\n';
		}

		residue_string = &input_line[n];
		if (residue_string[0] == '\0')
		{
			residue_string = nullptr;
			free(input_line);
		}
		//printf("%s\tresult: %d\n", buf, n);
		return n;
	}

И теперь собирается через cmake

Если есть Makefile, я использую его.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Ну с большего проблема решилась, только до сих пор не ясно, почему первая строка не распознается:

~/finder/build$ ./finder 
>
Unexpected input character '[', ignoring
Unexpected input character '
                            ', ignoring
Parse error: syntax error
Unexpected input character '_', ignoring
Unexpected input character '', ignoring
>^C
~/finder/build$ ./finder 
>
Unexpected input character '', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring
>
aido ★★
() автор топика
Ответ на: комментарий от xaizek
$ ./finder 
>

	result: 1
{
	result: 6
Unexpected input character '{', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring
Unexpected input character '', ignoring

Получается, что при первом нажатии enter функция почему-то вызывается дважды и во второй раз в буфере лежит мусор..

aido ★★
() автор топика
Последнее исправление: aido (всего исправлений: 1)
Ответ на: комментарий от aido

Порядок if-ов неправильный, должен быть:

			if (residue_string[0] == '\0')
			{
				residue_string=NULL;
				free(input_line);
			}
			if (n < max_size)
			{
				buf[n++]='\n';
			}
и этого не хватает
				input_line=readline(begin_line);
				if (input_line == nullptr)
				{
					input_line = strdup("");
				}

«@» это у меня readline чего-то выводит, наверное, думает, что это продолжение ввода.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Пасиб. вопросы исчерпаны.

aido ★★
() автор топика
Ответ на: комментарий от xaizek

Реализация без других проблем:

Да ну, хрень какая-то. Разрежет «оченьоченьдлинная\n» на «очень\n» «очень\n» «длинная\n» - накой такое надо? Ни лексически ни синтаксически не верно.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Почему разрежет? '\n' добавится, если мы дошли до конца ранее введенной строки. Там есть баг с порядком проверок, это да, я потом уже увидел. Разрезала как раз исходная версия.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Почему разрежет?

Ну собственно это и есть «задача» этой функции.

'\n' добавится, если мы дошли до конца ранее введенной строки.

А, ну да, но это ничего не меняет. Особо смешно, что readline без '\n' на конце и как yylex то сами динамичекие...

vodz ★★★★★
()
Ответ на: комментарий от anonymous

Ух ты, пользователь Slackware! Они существуют!

Тут даже не один.

vodz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.