Реализация функций 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).

1 ответ

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

редактировать

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

Другие вопросы по тегам