Реализация функций eval и load внутри обработчика сценариев с помощью Flex и Bison.

Привет, ребята, я разрабатываю скриптовый движок с помощью flex и bison, и теперь я реализую функции eval и load для этого языка. Просто чтобы дать вам пример, синтаксис выглядит так:

import std.*;

load( "some_script.hy" );

eval( "foo = 123;" );

println( foo );

Итак, в моем лексере я реализовал функцию:

void hyb_parse_string( const char *str ){
    extern int yyparse(void);
    YY_BUFFER_STATE prev, next;
    /*
     * Save current buffer.
     */
    prev = YY_CURRENT_BUFFER;
    /*
     * yy_scan_string will call yy_switch_to_buffer.
     */
    next = yy_scan_string( str );
    /*
     * Do actual parsing (yyparse calls yylex).
     */
    yyparse();
    /*
     * Restore previous buffer.
     */
    yy_switch_to_buffer(prev);
}

Но, похоже, это не работает. Что ж, это так, но когда строка (загруженная из файла или непосредственно оцененная) завершена, я получаю sigsegv :

Program received signal SIGSEGV, Segmentation fault.
0xb7f2b801 in yylex () at src/lexer.cpp:1658
1658            if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )

Как вы могли заметить, sigsegv генерируется кодом flex/bison, а не моим... какие-нибудь подсказки или, по крайней мере, какие-нибудь примеры того, как реализовать такие функции?

PS: я успешно реализовал директиву include, но мне нужно, чтобы eval и load работали не во время синтаксического анализа, а во время выполнения (вроде директив PHP include/require).


person Simone Margaritelli    schedule 19.05.2010    source источник


Ответы (1)


Эта ошибка, по-видимому, указывает на то, что YY_CURRENT_BUFFER недействителен, возможно, нулевой. Это произойдет, если вы вызовете yypop_buffer_state для извлечения последнего входного буфера. Если вы сделаете это в правиле <<EOF>> (например, имея дело с директивой include, как вы говорите, вы реализовали ее), вам нужно проверить YY_CURRENT_BUFFER и, если она нулевая, вызвать yyterminate, иначе произойдет сбой, как вы видите.

Изменить

Симона, я не уверен, что понял твой комментарий. Если у вас есть правило <<EOF>>, это действие должно либо вызвать yyterminate(), либо каким-то образом установить новый источник ввода, иначе вы получите сбой, аналогичный тому, о котором вы сообщаете. Когда вы видите сбой, это в функции hyb_parse_string (в вызове yyparse), которую вы опубликовали? Используйте команду gdb bt, чтобы просмотреть трассировку стека. Каково ваше правило <<EOF>>?

person Chris Dodd    schedule 19.05.2010
comment
Я не делаю этого ни в одном правиле, это просто отдельная функция, вызываемая ПОСЛЕ анализа сценария. Директиву Include легко реализовать, потому что я могу иметь дело с ‹‹EOF››, как вы сказали, внутри правила лексера, но что, если мне нужно реализовать что-то внешнее по отношению к правилу? - person Simone Margaritelli; 19.05.2010