2015-02-02 3 views
2

Я пытаюсь выяснить генератор синтаксического анализатора Lemon, поэтому я написал небольшой тест, чтобы помочь мне полностью понять. Файлы генерируются без проблем, и компилятор не жалуется, но когда я пытаюсь запустить его, я получаю ошибку сегментации. Что я делаю неправильно?Ошибка сегментации из созданного лимоном парсера в C++

lexicon.l:

%{ 
#include "grammar.h" 
%} 

%option noyywrap 

%% 

[A-Za-z_][A-Za-z0-9]* return IDENTIFIER; 
\".*\"     return STRING; 
[0-9]+     return NUMBER; 
"="      return EQUALS; 
\n      return NEWLINE; 
%% 

grammar.y:

%include { 
#include <vector> 
#include <iostream> 
#include <cassert> 
#include <sstream> 
#include "AST.h" 
} 

%token_type {char *} 
%extra_argument {std::vector<Identifier>& identifiers} 

start ::= assignments. { 
    std::cout << "start resolved" << std::endl; 
} 

assignments ::= assignment. 
{ 
    std::cout << "assignments resolved" << std::endl; 
} 
assignments ::= assignments NEWLINE assignment. 

assignment ::= IDENTIFIER(id) EQUALS STRING(str). 
{ 
    std::cout << "I get here too" << std::endl; 
    identifiers.push_back(Identifier(id, str)); 
} 

assignment ::= IDENTIFIER(id) EQUALS NUMBER(num). 
{ 
    std::stringstream ss; 
    ss << num; 
    identifiers.push_back(Identifier(id, ss.str())); 
} 

main.cpp:

#include "AST.h" 

using namespace std; 

void* ParseAlloc(void* (*allocProc)(size_t)); 
void Parse(void*, int, char *, vector<Identifier>&); 
void ParseFree(void*, void(*freeProc)(void*)); 

int yylex(); 
extern char * yytext; 

int main() { 
    vector<Identifier> identifiers; 
    void* parser = ParseAlloc(malloc); 
    cout << "Line 20" << endl; 
    while (int lexcode = yylex()) { 
     cout << "Getting in the loop: " << yytext << endl; 
     Parse(parser, lexcode, yytext, identifiers); 
    } 
    Parse(parser, 0, NULL, identifiers); 
    cout << "Line 25" << endl; 
    ParseFree(parser, free); 

    return 0; 
} 

AST.h:

#include <string> 
#include <iostream> 

class Identifier { 
    std::string name; 
    std::string value; 
public: 
    Identifier(std::string _name, std::string _value) 
    : name(_name), 
     value(_value) { 
     std::cout << "Initializing " << name << " as " << value << std::endl; 
    } 

    std::string getName(); 
    std::string getValue(); 
    void setValue(std::string _value); 
}; 

AST.cpp:

#include "AST.h" 

std::string Identifier::getName() { 
    return name; 
} 

std::string Identifier::getValue() { 
    return value; 
} 

void Identifier::setValue(std::string _value) { 
    value = _value; 
} 

И, наконец, вход тест:

alpha = "Hello" 
beta = "World" 
gamma = 15 

И выход:

[email protected]:~/Scrivania/bison test$ cat text | ./parserLine 20 
Getting in the loop: alpha 
Segmentation Fault 

ответ

0

Используйте указатель для представления std::vector идентификаторов. Я не уверен, как это не произошло при ошибке компиляции, но где-то в коде он попытается присвоить переменную типа std::vector<Identifier>&. Если я правильно помню, вы не можете приписывать ссылки.

Таким образом, смена на std::vector<Identifier>* решает проблему.

+0

Как вы можете видеть из журналов отладки, точка, в которой используется вектор идентификаторов, даже не достигнута. –

+0

@Glaedr это segfaults при попытке выполнить 'yypParser-> identifiers = identifiers', левая сторона имеет тип' std :: vector & ', эта ссылка объединяется, поэтому она указывает на NULL. Он будет заканчиваться на 'std :: vector <Идентификатор, std :: allocator > :: operator = (this = 0x0, __x = std :: vector length 0, capacity 0)', посмотрите на 'this = 0x0' , Я использовал gdb, чтобы ответить, я не просто догадывался. –

+0

Значит, странное поведение связано с разными указателями и ссылками на подход при назначении, причем последний подвергается перегрузке оператора? –